Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeniofunc.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/iofunc.c 00005 * PURPOSE: Generic I/O Functions that build IRPs for various operations 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Gunnar Dalsnes 00008 * Filip Navara (navaraf@reactos.org) 00009 */ 00010 00011 /* INCLUDES *****************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #include <ioevent.h> 00015 #define NDEBUG 00016 #include <debug.h> 00017 #include "internal/io_i.h" 00018 00019 /* PRIVATE FUNCTIONS *********************************************************/ 00020 00021 VOID 00022 NTAPI 00023 IopCleanupAfterException(IN PFILE_OBJECT FileObject, 00024 IN PIRP Irp, 00025 IN PKEVENT Event OPTIONAL, 00026 IN PKEVENT LocalEvent OPTIONAL) 00027 { 00028 PAGED_CODE(); 00029 IOTRACE(IO_API_DEBUG, "IRP: %p. FO: %p \n", Irp, FileObject); 00030 00031 /* Check if we had a buffer */ 00032 if (Irp->AssociatedIrp.SystemBuffer) 00033 { 00034 /* Free it */ 00035 ExFreePool(Irp->AssociatedIrp.SystemBuffer); 00036 } 00037 00038 /* Free the mdl */ 00039 if (Irp->MdlAddress) IoFreeMdl(Irp->MdlAddress); 00040 00041 /* Free the IRP */ 00042 IoFreeIrp(Irp); 00043 00044 /* Check if we had a file lock */ 00045 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 00046 { 00047 /* Release it */ 00048 IopUnlockFileObject(FileObject); 00049 } 00050 00051 /* Check if we had an event */ 00052 if (Event) ObDereferenceObject(Event); 00053 00054 /* Check if we had a local event */ 00055 if (LocalEvent) ExFreePool(LocalEvent); 00056 00057 /* Derefenrce the FO */ 00058 ObDereferenceObject(FileObject); 00059 } 00060 00061 NTSTATUS 00062 NTAPI 00063 IopFinalizeAsynchronousIo(IN NTSTATUS SynchStatus, 00064 IN PKEVENT Event, 00065 IN PIRP Irp, 00066 IN KPROCESSOR_MODE PreviousMode, 00067 IN PIO_STATUS_BLOCK KernelIosb, 00068 OUT PIO_STATUS_BLOCK IoStatusBlock) 00069 { 00070 NTSTATUS FinalStatus = SynchStatus; 00071 PAGED_CODE(); 00072 IOTRACE(IO_API_DEBUG, "IRP: %p. Status: %lx \n", Irp, SynchStatus); 00073 00074 /* Make sure the IRP was completed, but returned pending */ 00075 if (FinalStatus == STATUS_PENDING) 00076 { 00077 /* Wait for the IRP */ 00078 FinalStatus = KeWaitForSingleObject(Event, 00079 Executive, 00080 PreviousMode, 00081 FALSE, 00082 NULL); 00083 if (FinalStatus == STATUS_USER_APC) 00084 { 00085 /* Abort the request */ 00086 IopAbortInterruptedIrp(Event, Irp); 00087 } 00088 00089 /* Set the final status */ 00090 FinalStatus = KernelIosb->Status; 00091 } 00092 00093 /* Wrap potential user-mode write in SEH */ 00094 _SEH2_TRY 00095 { 00096 *IoStatusBlock = *KernelIosb; 00097 } 00098 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00099 { 00100 /* Get the exception code */ 00101 FinalStatus = _SEH2_GetExceptionCode(); 00102 } 00103 _SEH2_END; 00104 00105 /* Free the event and return status */ 00106 ExFreePool(Event); 00107 return FinalStatus; 00108 } 00109 00110 NTSTATUS 00111 NTAPI 00112 IopPerformSynchronousRequest(IN PDEVICE_OBJECT DeviceObject, 00113 IN PIRP Irp, 00114 IN PFILE_OBJECT FileObject, 00115 IN BOOLEAN Deferred, 00116 IN KPROCESSOR_MODE PreviousMode, 00117 IN BOOLEAN SynchIo, 00118 IN IOP_TRANSFER_TYPE TransferType) 00119 { 00120 NTSTATUS Status; 00121 PKNORMAL_ROUTINE NormalRoutine; 00122 PVOID NormalContext; 00123 KIRQL OldIrql; 00124 PAGED_CODE(); 00125 IOTRACE(IO_API_DEBUG, "IRP: %p. DO: %p. FO: %p \n", 00126 Irp, DeviceObject, FileObject); 00127 00128 /* Queue the IRP */ 00129 IopQueueIrpToThread(Irp); 00130 00131 /* Update operation counts */ 00132 IopUpdateOperationCount(TransferType); 00133 00134 /* Call the driver */ 00135 Status = IoCallDriver(DeviceObject, Irp); 00136 00137 /* Check if we're optimizing this case */ 00138 if (Deferred) 00139 { 00140 /* We are! Check if the IRP wasn't completed */ 00141 if (Status != STATUS_PENDING) 00142 { 00143 /* Complete it ourselves */ 00144 ASSERT(!Irp->PendingReturned); 00145 KeRaiseIrql(APC_LEVEL, &OldIrql); 00146 IopCompleteRequest(&Irp->Tail.Apc, 00147 &NormalRoutine, 00148 &NormalContext, 00149 (PVOID*)&FileObject, 00150 &NormalContext); 00151 KeLowerIrql(OldIrql); 00152 } 00153 } 00154 00155 /* Check if this was synch I/O */ 00156 if (SynchIo) 00157 { 00158 /* Make sure the IRP was completed, but returned pending */ 00159 if (Status == STATUS_PENDING) 00160 { 00161 /* Wait for the IRP */ 00162 Status = KeWaitForSingleObject(&FileObject->Event, 00163 Executive, 00164 PreviousMode, 00165 (FileObject->Flags & 00166 FO_ALERTABLE_IO), 00167 NULL); 00168 if ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC)) 00169 { 00170 /* Abort the request */ 00171 IopAbortInterruptedIrp(&FileObject->Event, Irp); 00172 } 00173 00174 /* Set the final status */ 00175 Status = FileObject->FinalStatus; 00176 } 00177 00178 /* Release the file lock */ 00179 IopUnlockFileObject(FileObject); 00180 } 00181 00182 /* Return status */ 00183 return Status; 00184 } 00185 00186 NTSTATUS 00187 NTAPI 00188 IopDeviceFsIoControl(IN HANDLE DeviceHandle, 00189 IN HANDLE Event OPTIONAL, 00190 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 00191 IN PVOID UserApcContext OPTIONAL, 00192 OUT PIO_STATUS_BLOCK IoStatusBlock, 00193 IN ULONG IoControlCode, 00194 IN PVOID InputBuffer, 00195 IN ULONG InputBufferLength OPTIONAL, 00196 OUT PVOID OutputBuffer, 00197 IN ULONG OutputBufferLength OPTIONAL, 00198 IN BOOLEAN IsDevIoCtl) 00199 { 00200 NTSTATUS Status; 00201 PFILE_OBJECT FileObject; 00202 PDEVICE_OBJECT DeviceObject; 00203 PIRP Irp; 00204 PIO_STACK_LOCATION StackPtr; 00205 PKEVENT EventObject = NULL; 00206 BOOLEAN LockedForSynch = FALSE; 00207 ULONG AccessType; 00208 OBJECT_HANDLE_INFORMATION HandleInformation; 00209 ACCESS_MASK DesiredAccess; 00210 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00211 ULONG BufferLength; 00212 IOTRACE(IO_CTL_DEBUG, "Handle: %lx. CTL: %lx. Type: %lx \n", 00213 DeviceHandle, IoControlCode, IsDevIoCtl); 00214 00215 /* Get the access type */ 00216 AccessType = IO_METHOD_FROM_CTL_CODE(IoControlCode); 00217 00218 /* Check if we came from user mode */ 00219 if (PreviousMode != KernelMode) 00220 { 00221 _SEH2_TRY 00222 { 00223 /* Probe the status block */ 00224 ProbeForWriteIoStatusBlock(IoStatusBlock); 00225 00226 /* Check if this is buffered I/O */ 00227 if (AccessType == METHOD_BUFFERED) 00228 { 00229 /* Check if we have an output buffer */ 00230 if (OutputBuffer) 00231 { 00232 /* Probe the output buffer */ 00233 ProbeForWrite(OutputBuffer, 00234 OutputBufferLength, 00235 sizeof(CHAR)); 00236 } 00237 else 00238 { 00239 /* Make sure the caller can't fake this as we depend on this */ 00240 OutputBufferLength = 0; 00241 } 00242 } 00243 00244 /* Check if we we have an input buffer I/O */ 00245 if (AccessType != METHOD_NEITHER) 00246 { 00247 /* Check if we have an input buffer */ 00248 if (InputBuffer) 00249 { 00250 /* Probe the input buffer */ 00251 ProbeForRead(InputBuffer, InputBufferLength, sizeof(CHAR)); 00252 } 00253 else 00254 { 00255 /* Make sure the caller can't fake this as we depend on this */ 00256 InputBufferLength = 0; 00257 } 00258 } 00259 } 00260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00261 { 00262 /* Return the exception code */ 00263 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00264 } 00265 _SEH2_END; 00266 } 00267 00268 /* Don't check for access rights right now, KernelMode can do anything */ 00269 Status = ObReferenceObjectByHandle(DeviceHandle, 00270 0, 00271 IoFileObjectType, 00272 PreviousMode, 00273 (PVOID*)&FileObject, 00274 &HandleInformation); 00275 if (!NT_SUCCESS(Status)) return Status; 00276 00277 /* Can't use an I/O completion port and an APC in the same time */ 00278 if ((FileObject->CompletionContext) && (UserApcRoutine)) 00279 { 00280 /* Fail */ 00281 ObDereferenceObject(FileObject); 00282 return STATUS_INVALID_PARAMETER; 00283 } 00284 00285 /* Check if we from user mode */ 00286 if (PreviousMode != KernelMode) 00287 { 00288 /* Get the access mask */ 00289 DesiredAccess = (ACCESS_MASK)((IoControlCode >> 14) & 3); 00290 00291 /* Check if we can open it */ 00292 if ((DesiredAccess != FILE_ANY_ACCESS) && 00293 (HandleInformation.GrantedAccess & DesiredAccess) != DesiredAccess) 00294 { 00295 /* Dereference the file object and fail */ 00296 ObDereferenceObject(FileObject); 00297 return STATUS_ACCESS_DENIED; 00298 } 00299 } 00300 00301 /* Check for an event */ 00302 if (Event) 00303 { 00304 /* Reference it */ 00305 Status = ObReferenceObjectByHandle(Event, 00306 EVENT_MODIFY_STATE, 00307 ExEventObjectType, 00308 PreviousMode, 00309 (PVOID*)&EventObject, 00310 NULL); 00311 if (!NT_SUCCESS(Status)) 00312 { 00313 /* Dereference the file object and fail */ 00314 ObDereferenceObject(FileObject); 00315 return Status; 00316 } 00317 00318 /* Clear it */ 00319 KeClearEvent(EventObject); 00320 } 00321 00322 /* Check if this is a file that was opened for Synch I/O */ 00323 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 00324 { 00325 /* Lock it */ 00326 IopLockFileObject(FileObject); 00327 00328 /* Remember to unlock later */ 00329 LockedForSynch = TRUE; 00330 } 00331 00332 /* Check if this is a direct open or not */ 00333 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 00334 { 00335 /* It's a direct open, get the attached device */ 00336 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 00337 } 00338 else 00339 { 00340 /* Otherwise get the related device */ 00341 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00342 } 00343 00344 /* Clear the event */ 00345 KeClearEvent(&FileObject->Event); 00346 00347 /* Allocate IRP */ 00348 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00349 if (!Irp) return IopCleanupFailedIrp(FileObject, Event, NULL); 00350 00351 /* Setup the IRP */ 00352 Irp->UserIosb = IoStatusBlock; 00353 Irp->UserEvent = EventObject; 00354 Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine; 00355 Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext; 00356 Irp->Cancel = FALSE; 00357 Irp->CancelRoutine = NULL; 00358 Irp->PendingReturned = FALSE; 00359 Irp->RequestorMode = PreviousMode; 00360 Irp->MdlAddress = NULL; 00361 Irp->AssociatedIrp.SystemBuffer = NULL; 00362 Irp->Flags = 0; 00363 Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 00364 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00365 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00366 00367 /* Set stack location settings */ 00368 StackPtr = IoGetNextIrpStackLocation(Irp); 00369 StackPtr->FileObject = FileObject; 00370 StackPtr->MajorFunction = IsDevIoCtl ? 00371 IRP_MJ_DEVICE_CONTROL : 00372 IRP_MJ_FILE_SYSTEM_CONTROL; 00373 StackPtr->MinorFunction = 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */ 00374 StackPtr->Control = 0; 00375 StackPtr->Flags = 0; 00376 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = NULL; 00377 00378 /* Set the IOCTL Data */ 00379 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode; 00380 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; 00381 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 00382 OutputBufferLength; 00383 00384 /* Handle the Methods */ 00385 switch (AccessType) 00386 { 00387 /* Buffered I/O */ 00388 case METHOD_BUFFERED: 00389 00390 /* Enter SEH for allocations */ 00391 _SEH2_TRY 00392 { 00393 /* Select the right Buffer Length */ 00394 BufferLength = (InputBufferLength > OutputBufferLength) ? 00395 InputBufferLength : OutputBufferLength; 00396 00397 /* Make sure there is one */ 00398 if (BufferLength) 00399 { 00400 /* Allocate the System Buffer */ 00401 Irp->AssociatedIrp.SystemBuffer = 00402 ExAllocatePoolWithTag(NonPagedPool, 00403 BufferLength, 00404 TAG_SYS_BUF); 00405 00406 /* Check if we got a buffer */ 00407 if (InputBuffer) 00408 { 00409 /* Copy into the System Buffer */ 00410 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 00411 InputBuffer, 00412 InputBufferLength); 00413 } 00414 00415 /* Write the flags */ 00416 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 00417 if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION; 00418 00419 /* Save the Buffer */ 00420 Irp->UserBuffer = OutputBuffer; 00421 } 00422 else 00423 { 00424 /* Clear the Flags and Buffer */ 00425 Irp->UserBuffer = NULL; 00426 } 00427 } 00428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00429 { 00430 /* Cleanup after exception and return */ 00431 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 00432 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00433 } 00434 _SEH2_END; 00435 break; 00436 00437 /* Direct I/O */ 00438 case METHOD_IN_DIRECT: 00439 case METHOD_OUT_DIRECT: 00440 00441 /* Enter SEH */ 00442 _SEH2_TRY 00443 { 00444 /* Check if we got an input buffer */ 00445 if ((InputBufferLength) && (InputBuffer)) 00446 { 00447 /* Allocate the System Buffer */ 00448 Irp->AssociatedIrp.SystemBuffer = 00449 ExAllocatePoolWithTag(NonPagedPool, 00450 InputBufferLength, 00451 TAG_SYS_BUF); 00452 00453 /* Copy into the System Buffer */ 00454 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 00455 InputBuffer, 00456 InputBufferLength); 00457 00458 /* Write the flags */ 00459 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 00460 } 00461 00462 /* Check if we got an output buffer */ 00463 if (OutputBuffer) 00464 { 00465 /* Allocate the System Buffer */ 00466 Irp->MdlAddress = IoAllocateMdl(OutputBuffer, 00467 OutputBufferLength, 00468 FALSE, 00469 FALSE, 00470 Irp); 00471 if (!Irp->MdlAddress) 00472 { 00473 /* Raise exception we'll catch */ 00474 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 00475 } 00476 00477 /* Do the probe */ 00478 MmProbeAndLockPages(Irp->MdlAddress, 00479 PreviousMode, 00480 (AccessType == METHOD_IN_DIRECT) ? 00481 IoReadAccess : IoWriteAccess); 00482 } 00483 } 00484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00485 { 00486 /* Cleanup after exception and return */ 00487 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 00488 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00489 } 00490 _SEH2_END; 00491 break; 00492 00493 case METHOD_NEITHER: 00494 00495 /* Just save the Buffer */ 00496 Irp->UserBuffer = OutputBuffer; 00497 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; 00498 } 00499 00500 /* Use deferred completion for FS I/O */ 00501 Irp->Flags |= (!IsDevIoCtl) ? IRP_DEFER_IO_COMPLETION : 0; 00502 00503 /* Perform the call */ 00504 return IopPerformSynchronousRequest(DeviceObject, 00505 Irp, 00506 FileObject, 00507 !IsDevIoCtl, 00508 PreviousMode, 00509 LockedForSynch, 00510 IopOtherTransfer); 00511 } 00512 00513 NTSTATUS 00514 NTAPI 00515 IopQueryDeviceInformation(IN PFILE_OBJECT FileObject, 00516 IN ULONG InformationClass, 00517 IN ULONG Length, 00518 OUT PVOID Information, 00519 OUT PULONG ReturnedLength, 00520 IN BOOLEAN File) 00521 { 00522 IO_STATUS_BLOCK IoStatusBlock; 00523 PIRP Irp; 00524 PDEVICE_OBJECT DeviceObject; 00525 PIO_STACK_LOCATION StackPtr; 00526 BOOLEAN LocalEvent = FALSE; 00527 KEVENT Event; 00528 NTSTATUS Status; 00529 PAGED_CODE(); 00530 IOTRACE(IO_API_DEBUG, "Handle: %p. CTL: %lx. Type: %lx \n", 00531 FileObject, InformationClass, File); 00532 00533 /* Reference the object */ 00534 ObReferenceObject(FileObject); 00535 00536 /* Check if this is a file that was opened for Synch I/O */ 00537 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 00538 { 00539 /* Lock it */ 00540 IopLockFileObject(FileObject); 00541 00542 /* Use File Object event */ 00543 KeClearEvent(&FileObject->Event); 00544 } 00545 else 00546 { 00547 /* Use local event */ 00548 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 00549 LocalEvent = TRUE; 00550 } 00551 00552 /* Get the Device Object */ 00553 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00554 00555 /* Allocate the IRP */ 00556 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00557 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 00558 00559 /* Set the IRP */ 00560 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00561 Irp->RequestorMode = KernelMode; 00562 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 00563 Irp->UserIosb = &IoStatusBlock; 00564 Irp->UserEvent = (LocalEvent) ? &Event : NULL; 00565 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 00566 Irp->Flags |= IRP_BUFFERED_IO; 00567 Irp->AssociatedIrp.SystemBuffer = Information; 00568 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00569 00570 /* Set the Stack Data */ 00571 StackPtr = IoGetNextIrpStackLocation(Irp); 00572 StackPtr->MajorFunction = File ? IRP_MJ_QUERY_INFORMATION: 00573 IRP_MJ_QUERY_VOLUME_INFORMATION; 00574 StackPtr->FileObject = FileObject; 00575 00576 /* Check which type this is */ 00577 if (File) 00578 { 00579 /* Set Parameters */ 00580 StackPtr->Parameters.QueryFile.FileInformationClass = InformationClass; 00581 StackPtr->Parameters.QueryFile.Length = Length; 00582 } 00583 else 00584 { 00585 /* Set Parameters */ 00586 StackPtr->Parameters.QueryVolume.FsInformationClass = InformationClass; 00587 StackPtr->Parameters.QueryVolume.Length = Length; 00588 } 00589 00590 /* Queue the IRP */ 00591 IopQueueIrpToThread(Irp); 00592 00593 /* Call the Driver */ 00594 Status = IoCallDriver(DeviceObject, Irp); 00595 00596 /* Check if this was synch I/O */ 00597 if (!LocalEvent) 00598 { 00599 /* Check if the requet is pending */ 00600 if (Status == STATUS_PENDING) 00601 { 00602 /* Wait on the file object */ 00603 Status = KeWaitForSingleObject(&FileObject->Event, 00604 Executive, 00605 KernelMode, 00606 FileObject->Flags & FO_ALERTABLE_IO, 00607 NULL); 00608 if (Status == STATUS_ALERTED) 00609 { 00610 /* Abort the operation */ 00611 IopAbortInterruptedIrp(&FileObject->Event, Irp); 00612 } 00613 00614 /* Get the final status */ 00615 Status = FileObject->FinalStatus; 00616 } 00617 00618 /* Release the file lock */ 00619 IopUnlockFileObject(FileObject); 00620 } 00621 else if (Status == STATUS_PENDING) 00622 { 00623 /* Wait on the local event and get the final status */ 00624 KeWaitForSingleObject(&Event, 00625 Executive, 00626 KernelMode, 00627 FALSE, 00628 NULL); 00629 Status = IoStatusBlock.Status; 00630 } 00631 00632 /* Return the Length and Status. ReturnedLength is NOT optional */ 00633 *ReturnedLength = (ULONG)IoStatusBlock.Information; 00634 return Status; 00635 } 00636 00637 /* PUBLIC FUNCTIONS **********************************************************/ 00638 00639 /* 00640 * @implemented 00641 */ 00642 NTSTATUS 00643 NTAPI 00644 IoSynchronousPageWrite(IN PFILE_OBJECT FileObject, 00645 IN PMDL Mdl, 00646 IN PLARGE_INTEGER Offset, 00647 IN PKEVENT Event, 00648 IN PIO_STATUS_BLOCK StatusBlock) 00649 { 00650 PIRP Irp; 00651 PIO_STACK_LOCATION StackPtr; 00652 PDEVICE_OBJECT DeviceObject; 00653 IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p \n", 00654 FileObject, Mdl, Offset); 00655 00656 /* Get the Device Object */ 00657 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00658 00659 /* Allocate IRP */ 00660 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00661 if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; 00662 00663 /* Get the Stack */ 00664 StackPtr = IoGetNextIrpStackLocation(Irp); 00665 00666 /* Create the IRP Settings */ 00667 Irp->MdlAddress = Mdl; 00668 Irp->UserBuffer = MmGetMdlVirtualAddress(Mdl); 00669 Irp->UserIosb = StatusBlock; 00670 Irp->UserEvent = Event; 00671 Irp->RequestorMode = KernelMode; 00672 Irp->Flags = IRP_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_PAGING_IO; 00673 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00674 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00675 00676 /* Set the Stack Settings */ 00677 StackPtr->Parameters.Write.Length = MmGetMdlByteCount(Mdl); 00678 StackPtr->Parameters.Write.ByteOffset = *Offset; 00679 StackPtr->MajorFunction = IRP_MJ_WRITE; 00680 StackPtr->FileObject = FileObject; 00681 00682 /* Call the Driver */ 00683 return IoCallDriver(DeviceObject, Irp); 00684 } 00685 00686 /* 00687 * @implemented 00688 */ 00689 NTSTATUS 00690 NTAPI 00691 IoPageRead(IN PFILE_OBJECT FileObject, 00692 IN PMDL Mdl, 00693 IN PLARGE_INTEGER Offset, 00694 IN PKEVENT Event, 00695 IN PIO_STATUS_BLOCK StatusBlock) 00696 { 00697 PIRP Irp; 00698 PIO_STACK_LOCATION StackPtr; 00699 PDEVICE_OBJECT DeviceObject; 00700 IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p \n", 00701 FileObject, Mdl, Offset); 00702 00703 /* Get the Device Object */ 00704 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00705 00706 /* Allocate IRP */ 00707 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00708 if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; 00709 00710 /* Get the Stack */ 00711 StackPtr = IoGetNextIrpStackLocation(Irp); 00712 00713 /* Create the IRP Settings */ 00714 Irp->MdlAddress = Mdl; 00715 Irp->UserBuffer = MmGetMdlVirtualAddress(Mdl); 00716 Irp->UserIosb = StatusBlock; 00717 Irp->UserEvent = Event; 00718 Irp->RequestorMode = KernelMode; 00719 Irp->Flags = IRP_PAGING_IO | 00720 IRP_NOCACHE | 00721 IRP_SYNCHRONOUS_PAGING_IO | 00722 IRP_INPUT_OPERATION; 00723 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00724 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00725 00726 /* Set the Stack Settings */ 00727 StackPtr->Parameters.Read.Length = MmGetMdlByteCount(Mdl); 00728 StackPtr->Parameters.Read.ByteOffset = *Offset; 00729 StackPtr->MajorFunction = IRP_MJ_READ; 00730 StackPtr->FileObject = FileObject; 00731 00732 /* Call the Driver */ 00733 return IoCallDriver(DeviceObject, Irp); 00734 } 00735 00736 /* 00737 * @implemented 00738 */ 00739 NTSTATUS 00740 NTAPI 00741 IoQueryFileInformation(IN PFILE_OBJECT FileObject, 00742 IN FILE_INFORMATION_CLASS FileInformationClass, 00743 IN ULONG Length, 00744 OUT PVOID FileInformation, 00745 OUT PULONG ReturnedLength) 00746 { 00747 /* Call the shared routine */ 00748 return IopQueryDeviceInformation(FileObject, 00749 FileInformationClass, 00750 Length, 00751 FileInformation, 00752 ReturnedLength, 00753 TRUE); 00754 } 00755 00756 /* 00757 * @implemented 00758 */ 00759 NTSTATUS 00760 NTAPI 00761 IoQueryVolumeInformation(IN PFILE_OBJECT FileObject, 00762 IN FS_INFORMATION_CLASS FsInformationClass, 00763 IN ULONG Length, 00764 OUT PVOID FsInformation, 00765 OUT PULONG ReturnedLength) 00766 { 00767 /* Call the shared routine */ 00768 return IopQueryDeviceInformation(FileObject, 00769 FsInformationClass, 00770 Length, 00771 FsInformation, 00772 ReturnedLength, 00773 FALSE); 00774 } 00775 00776 /* 00777 * @implemented 00778 */ 00779 NTSTATUS 00780 NTAPI 00781 IoSetInformation(IN PFILE_OBJECT FileObject, 00782 IN FILE_INFORMATION_CLASS FileInformationClass, 00783 IN ULONG Length, 00784 IN PVOID FileInformation) 00785 { 00786 IO_STATUS_BLOCK IoStatusBlock; 00787 PIRP Irp; 00788 PDEVICE_OBJECT DeviceObject; 00789 PIO_STACK_LOCATION StackPtr; 00790 BOOLEAN LocalEvent = FALSE; 00791 KEVENT Event; 00792 NTSTATUS Status; 00793 PAGED_CODE(); 00794 IOTRACE(IO_API_DEBUG, "FileObject: %p. Class: %lx. Length: %lx \n", 00795 FileObject, FileInformationClass, Length); 00796 00797 /* Reference the object */ 00798 ObReferenceObject(FileObject); 00799 00800 /* Check if this is a file that was opened for Synch I/O */ 00801 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 00802 { 00803 /* Lock it */ 00804 IopLockFileObject(FileObject); 00805 00806 /* Use File Object event */ 00807 KeClearEvent(&FileObject->Event); 00808 } 00809 else 00810 { 00811 /* Use local event */ 00812 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 00813 LocalEvent = TRUE; 00814 } 00815 00816 /* Get the Device Object */ 00817 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00818 00819 /* Allocate the IRP */ 00820 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00821 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 00822 00823 /* Set the IRP */ 00824 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00825 Irp->RequestorMode = KernelMode; 00826 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 00827 Irp->UserIosb = &IoStatusBlock; 00828 Irp->UserEvent = (LocalEvent) ? &Event : NULL; 00829 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 00830 Irp->Flags |= IRP_BUFFERED_IO; 00831 Irp->AssociatedIrp.SystemBuffer = FileInformation; 00832 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00833 00834 /* Set the Stack Data */ 00835 StackPtr = IoGetNextIrpStackLocation(Irp); 00836 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION; 00837 StackPtr->FileObject = FileObject; 00838 00839 /* Set Parameters */ 00840 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass; 00841 StackPtr->Parameters.SetFile.Length = Length; 00842 00843 /* Queue the IRP */ 00844 IopQueueIrpToThread(Irp); 00845 00846 /* Call the Driver */ 00847 Status = IoCallDriver(DeviceObject, Irp); 00848 00849 /* Check if this was synch I/O */ 00850 if (!LocalEvent) 00851 { 00852 /* Check if the requet is pending */ 00853 if (Status == STATUS_PENDING) 00854 { 00855 /* Wait on the file object */ 00856 Status = KeWaitForSingleObject(&FileObject->Event, 00857 Executive, 00858 KernelMode, 00859 FileObject->Flags & FO_ALERTABLE_IO, 00860 NULL); 00861 if (Status == STATUS_ALERTED) 00862 { 00863 /* Abort the operation */ 00864 IopAbortInterruptedIrp(&FileObject->Event, Irp); 00865 } 00866 00867 /* Get the final status */ 00868 Status = FileObject->FinalStatus; 00869 } 00870 00871 /* Release the file lock */ 00872 IopUnlockFileObject(FileObject); 00873 } 00874 else if (Status == STATUS_PENDING) 00875 { 00876 /* Wait on the local event and get the final status */ 00877 KeWaitForSingleObject(&Event, 00878 Executive, 00879 KernelMode, 00880 FALSE, 00881 NULL); 00882 Status = IoStatusBlock.Status; 00883 } 00884 00885 /* Return the status */ 00886 return Status; 00887 } 00888 00889 /* NATIVE SERVICES ***********************************************************/ 00890 00891 /* 00892 * @implemented 00893 */ 00894 NTSTATUS 00895 NTAPI 00896 NtDeviceIoControlFile(IN HANDLE DeviceHandle, 00897 IN HANDLE Event OPTIONAL, 00898 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 00899 IN PVOID UserApcContext OPTIONAL, 00900 OUT PIO_STATUS_BLOCK IoStatusBlock, 00901 IN ULONG IoControlCode, 00902 IN PVOID InputBuffer, 00903 IN ULONG InputBufferLength OPTIONAL, 00904 OUT PVOID OutputBuffer, 00905 IN ULONG OutputBufferLength OPTIONAL) 00906 { 00907 /* Call the Generic Function */ 00908 return IopDeviceFsIoControl(DeviceHandle, 00909 Event, 00910 UserApcRoutine, 00911 UserApcContext, 00912 IoStatusBlock, 00913 IoControlCode, 00914 InputBuffer, 00915 InputBufferLength, 00916 OutputBuffer, 00917 OutputBufferLength, 00918 TRUE); 00919 } 00920 00921 /* 00922 * @implemented 00923 */ 00924 NTSTATUS 00925 NTAPI 00926 NtFsControlFile(IN HANDLE DeviceHandle, 00927 IN HANDLE Event OPTIONAL, 00928 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 00929 IN PVOID UserApcContext OPTIONAL, 00930 OUT PIO_STATUS_BLOCK IoStatusBlock, 00931 IN ULONG IoControlCode, 00932 IN PVOID InputBuffer, 00933 IN ULONG InputBufferLength OPTIONAL, 00934 OUT PVOID OutputBuffer, 00935 IN ULONG OutputBufferLength OPTIONAL) 00936 { 00937 /* Call the Generic Function */ 00938 return IopDeviceFsIoControl(DeviceHandle, 00939 Event, 00940 UserApcRoutine, 00941 UserApcContext, 00942 IoStatusBlock, 00943 IoControlCode, 00944 InputBuffer, 00945 InputBufferLength, 00946 OutputBuffer, 00947 OutputBufferLength, 00948 FALSE); 00949 } 00950 00951 NTSTATUS 00952 NTAPI 00953 NtFlushBuffersFile(IN HANDLE FileHandle, 00954 OUT PIO_STATUS_BLOCK IoStatusBlock) 00955 { 00956 PFILE_OBJECT FileObject; 00957 PIRP Irp; 00958 PIO_STACK_LOCATION StackPtr; 00959 NTSTATUS Status; 00960 PDEVICE_OBJECT DeviceObject; 00961 PKEVENT Event = NULL; 00962 BOOLEAN LocalEvent = FALSE; 00963 OBJECT_HANDLE_INFORMATION ObjectHandleInfo; 00964 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00965 IO_STATUS_BLOCK KernelIosb; 00966 PAGED_CODE(); 00967 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 00968 00969 if (PreviousMode != KernelMode) 00970 { 00971 /* Protect probes */ 00972 _SEH2_TRY 00973 { 00974 /* Probe the I/O Status block */ 00975 ProbeForWriteIoStatusBlock(IoStatusBlock); 00976 } 00977 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00978 { 00979 /* Return the exception code */ 00980 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00981 } 00982 _SEH2_END; 00983 } 00984 00985 /* Get the File Object */ 00986 Status = ObReferenceObjectByHandle(FileHandle, 00987 0, 00988 IoFileObjectType, 00989 PreviousMode, 00990 (PVOID*)&FileObject, 00991 &ObjectHandleInfo); 00992 if (!NT_SUCCESS(Status)) return Status; 00993 00994 /* 00995 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was 00996 * granted. However, if this is a named pipe, make sure we don't ask for 00997 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE 00998 * access right! 00999 */ 01000 if (!(ObjectHandleInfo.GrantedAccess & 01001 ((!(FileObject->Flags & FO_NAMED_PIPE) ? FILE_APPEND_DATA : 0) | 01002 FILE_WRITE_DATA))) 01003 { 01004 /* We failed */ 01005 ObDereferenceObject(FileObject); 01006 return STATUS_ACCESS_DENIED; 01007 } 01008 01009 /* Check if we should use Sync IO or not */ 01010 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01011 { 01012 /* Lock it */ 01013 IopLockFileObject(FileObject); 01014 } 01015 else 01016 { 01017 /* Use local event */ 01018 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 01019 if (!Event) 01020 { 01021 /* We failed */ 01022 ObDereferenceObject(FileObject); 01023 return STATUS_INSUFFICIENT_RESOURCES; 01024 } 01025 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 01026 LocalEvent = TRUE; 01027 } 01028 01029 /* Get the Device Object */ 01030 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01031 01032 /* Clear the event */ 01033 KeClearEvent(&FileObject->Event); 01034 01035 /* Allocate the IRP */ 01036 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); 01037 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); 01038 01039 /* Set up the IRP */ 01040 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 01041 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 01042 Irp->UserEvent = (LocalEvent) ? Event : NULL; 01043 Irp->RequestorMode = PreviousMode; 01044 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01045 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01046 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 01047 01048 /* Set up Stack Data */ 01049 StackPtr = IoGetNextIrpStackLocation(Irp); 01050 StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS; 01051 StackPtr->FileObject = FileObject; 01052 01053 /* Call the Driver */ 01054 Status = IopPerformSynchronousRequest(DeviceObject, 01055 Irp, 01056 FileObject, 01057 FALSE, 01058 PreviousMode, 01059 !LocalEvent, 01060 IopOtherTransfer); 01061 01062 /* Check if this was async I/O */ 01063 if (LocalEvent) 01064 { 01065 /* It was, finalize this request */ 01066 Status = IopFinalizeAsynchronousIo(Status, 01067 Event, 01068 Irp, 01069 PreviousMode, 01070 &KernelIosb, 01071 IoStatusBlock); 01072 } 01073 01074 /* Return the Status */ 01075 return Status; 01076 } 01077 01078 /* 01079 * @implemented 01080 */ 01081 NTSTATUS 01082 NTAPI 01083 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle, 01084 IN HANDLE EventHandle OPTIONAL, 01085 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 01086 IN PVOID ApcContext OPTIONAL, 01087 OUT PIO_STATUS_BLOCK IoStatusBlock, 01088 OUT PVOID Buffer, 01089 IN ULONG BufferSize, 01090 IN ULONG CompletionFilter, 01091 IN BOOLEAN WatchTree) 01092 { 01093 PIRP Irp; 01094 PKEVENT Event = NULL; 01095 PDEVICE_OBJECT DeviceObject; 01096 PFILE_OBJECT FileObject; 01097 PIO_STACK_LOCATION IoStack; 01098 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 01099 NTSTATUS Status; 01100 BOOLEAN LockedForSync = FALSE; 01101 PAGED_CODE(); 01102 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 01103 01104 /* Check if we're called from user mode */ 01105 if (PreviousMode != KernelMode) 01106 { 01107 /* Enter SEH for probing */ 01108 _SEH2_TRY 01109 { 01110 /* Probe the I/O STatus block */ 01111 ProbeForWriteIoStatusBlock(IoStatusBlock); 01112 01113 /* Probe the buffer */ 01114 if (BufferSize) ProbeForWrite(Buffer, BufferSize, sizeof(ULONG)); 01115 } 01116 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01117 { 01118 /* Return the exception code */ 01119 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01120 } 01121 _SEH2_END; 01122 01123 /* Check if CompletionFilter is valid */ 01124 if (!CompletionFilter || (CompletionFilter & ~FILE_NOTIFY_VALID_MASK)) 01125 { 01126 return STATUS_INVALID_PARAMETER; 01127 } 01128 } 01129 01130 /* Get File Object */ 01131 Status = ObReferenceObjectByHandle(FileHandle, 01132 FILE_LIST_DIRECTORY, 01133 IoFileObjectType, 01134 PreviousMode, 01135 (PVOID*)&FileObject, 01136 NULL); 01137 if (!NT_SUCCESS(Status)) return Status; 01138 01139 /* Check if we have an event handle */ 01140 if (EventHandle) 01141 { 01142 /* Reference it */ 01143 Status = ObReferenceObjectByHandle(EventHandle, 01144 EVENT_MODIFY_STATE, 01145 ExEventObjectType, 01146 PreviousMode, 01147 (PVOID *)&Event, 01148 NULL); 01149 if (Status != STATUS_SUCCESS) 01150 { 01151 ObDereferenceObject(FileObject); 01152 return Status; 01153 } 01154 KeClearEvent(Event); 01155 } 01156 01157 /* Check if we should use Sync IO or not */ 01158 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01159 { 01160 /* Lock it */ 01161 IopLockFileObject(FileObject); 01162 LockedForSync = TRUE; 01163 } 01164 01165 /* Clear File Object event */ 01166 KeClearEvent(&FileObject->Event); 01167 01168 /* Get the device object */ 01169 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01170 01171 /* Allocate the IRP */ 01172 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 01173 if (!Irp) return IopCleanupFailedIrp(FileObject, Event, NULL); 01174 01175 /* Set up the IRP */ 01176 Irp->RequestorMode = PreviousMode; 01177 Irp->UserIosb = IoStatusBlock; 01178 Irp->UserEvent = Event; 01179 Irp->UserBuffer = Buffer; 01180 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01181 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01182 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01183 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01184 01185 /* Set up Stack Data */ 01186 IoStack = IoGetNextIrpStackLocation(Irp); 01187 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 01188 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY; 01189 IoStack->FileObject = FileObject; 01190 01191 /* Set parameters */ 01192 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter; 01193 IoStack->Parameters.NotifyDirectory.Length = BufferSize; 01194 if (WatchTree) IoStack->Flags = SL_WATCH_TREE; 01195 01196 /* Perform the call */ 01197 return IopPerformSynchronousRequest(DeviceObject, 01198 Irp, 01199 FileObject, 01200 FALSE, 01201 PreviousMode, 01202 LockedForSync, 01203 IopOtherTransfer); 01204 } 01205 01206 /* 01207 * @implemented 01208 */ 01209 NTSTATUS 01210 NTAPI 01211 NtLockFile(IN HANDLE FileHandle, 01212 IN HANDLE EventHandle OPTIONAL, 01213 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 01214 IN PVOID ApcContext OPTIONAL, 01215 OUT PIO_STATUS_BLOCK IoStatusBlock, 01216 IN PLARGE_INTEGER ByteOffset, 01217 IN PLARGE_INTEGER Length, 01218 IN ULONG Key, 01219 IN BOOLEAN FailImmediately, 01220 IN BOOLEAN ExclusiveLock) 01221 { 01222 PFILE_OBJECT FileObject; 01223 PLARGE_INTEGER LocalLength = NULL; 01224 PIRP Irp; 01225 PIO_STACK_LOCATION StackPtr; 01226 PDEVICE_OBJECT DeviceObject; 01227 PKEVENT Event = NULL; 01228 BOOLEAN LockedForSync = FALSE; 01229 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 01230 LARGE_INTEGER CapturedByteOffset, CapturedLength; 01231 NTSTATUS Status; 01232 OBJECT_HANDLE_INFORMATION HandleInformation; 01233 PAGED_CODE(); 01234 CapturedByteOffset.QuadPart = 0; 01235 CapturedLength.QuadPart = 0; 01236 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 01237 01238 /* Get File Object */ 01239 Status = ObReferenceObjectByHandle(FileHandle, 01240 0, 01241 IoFileObjectType, 01242 PreviousMode, 01243 (PVOID*)&FileObject, 01244 &HandleInformation); 01245 if (!NT_SUCCESS(Status)) return Status; 01246 01247 /* Check if we're called from user mode */ 01248 if (PreviousMode != KernelMode) 01249 { 01250 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */ 01251 if (!(HandleInformation.GrantedAccess & 01252 (FILE_WRITE_DATA | FILE_READ_DATA))) 01253 { 01254 ObDereferenceObject(FileObject); 01255 return STATUS_ACCESS_DENIED; 01256 } 01257 01258 /* Enter SEH for probing */ 01259 _SEH2_TRY 01260 { 01261 /* Probe the I/O STatus block */ 01262 ProbeForWriteIoStatusBlock(IoStatusBlock); 01263 01264 /* Probe and capture the large integers */ 01265 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); 01266 CapturedLength = ProbeForReadLargeInteger(Length); 01267 } 01268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01269 { 01270 /* Dereference the object and return exception code */ 01271 ObDereferenceObject(FileObject); 01272 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01273 } 01274 _SEH2_END; 01275 } 01276 else 01277 { 01278 /* Otherwise, capture them directly */ 01279 CapturedByteOffset = *ByteOffset; 01280 CapturedLength = *Length; 01281 } 01282 01283 /* Check if we have an event handle */ 01284 if (EventHandle) 01285 { 01286 /* Reference it */ 01287 Status = ObReferenceObjectByHandle(EventHandle, 01288 EVENT_MODIFY_STATE, 01289 ExEventObjectType, 01290 PreviousMode, 01291 (PVOID *)&Event, 01292 NULL); 01293 if (Status != STATUS_SUCCESS) return Status; 01294 KeClearEvent(Event); 01295 } 01296 01297 /* Get the device object */ 01298 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01299 01300 /* Check if we should use Sync IO or not */ 01301 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01302 { 01303 /* Lock it */ 01304 IopLockFileObject(FileObject); 01305 LockedForSync = TRUE; 01306 } 01307 01308 /* Clear File Object event */ 01309 KeClearEvent(&FileObject->Event); 01310 FileObject->LockOperation = TRUE; 01311 01312 /* Allocate the IRP */ 01313 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 01314 if (!Irp) return IopCleanupFailedIrp(FileObject, Event, NULL); 01315 01316 /* Set up the IRP */ 01317 Irp->RequestorMode = PreviousMode; 01318 Irp->UserIosb = IoStatusBlock; 01319 Irp->UserEvent = Event; 01320 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01321 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01322 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01323 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01324 01325 /* Set up Stack Data */ 01326 StackPtr = IoGetNextIrpStackLocation(Irp); 01327 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; 01328 StackPtr->MinorFunction = IRP_MN_LOCK; 01329 StackPtr->FileObject = FileObject; 01330 01331 /* Enter SEH */ 01332 _SEH2_TRY 01333 { 01334 /* Allocate local buffer */ 01335 LocalLength = ExAllocatePoolWithTag(NonPagedPool, 01336 sizeof(LARGE_INTEGER), 01337 TAG_LOCK); 01338 01339 /* Set the length */ 01340 *LocalLength = CapturedLength; 01341 Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength; 01342 StackPtr->Parameters.LockControl.Length = LocalLength; 01343 } 01344 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01345 { 01346 /* Allocating failed, clean up and return the exception code */ 01347 IopCleanupAfterException(FileObject, Irp, Event, NULL); 01348 if (LocalLength) ExFreePool(LocalLength); 01349 01350 /* Return the exception code */ 01351 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01352 } 01353 _SEH2_END; 01354 01355 /* Set Parameters */ 01356 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset; 01357 StackPtr->Parameters.LockControl.Key = Key; 01358 01359 /* Set Flags */ 01360 if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY; 01361 if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK; 01362 01363 /* Perform the call */ 01364 return IopPerformSynchronousRequest(DeviceObject, 01365 Irp, 01366 FileObject, 01367 FALSE, 01368 PreviousMode, 01369 LockedForSync, 01370 IopOtherTransfer); 01371 } 01372 01373 /* 01374 * @implemented 01375 */ 01376 NTSTATUS 01377 NTAPI 01378 NtQueryDirectoryFile(IN HANDLE FileHandle, 01379 IN HANDLE EventHandle OPTIONAL, 01380 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 01381 IN PVOID ApcContext OPTIONAL, 01382 OUT PIO_STATUS_BLOCK IoStatusBlock, 01383 OUT PVOID FileInformation, 01384 IN ULONG Length, 01385 IN FILE_INFORMATION_CLASS FileInformationClass, 01386 IN BOOLEAN ReturnSingleEntry, 01387 IN PUNICODE_STRING FileName OPTIONAL, 01388 IN BOOLEAN RestartScan) 01389 { 01390 PIRP Irp; 01391 PDEVICE_OBJECT DeviceObject; 01392 PFILE_OBJECT FileObject; 01393 PIO_STACK_LOCATION StackPtr; 01394 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 01395 NTSTATUS Status; 01396 BOOLEAN LockedForSynch = FALSE; 01397 PKEVENT Event = NULL; 01398 PVOID AuxBuffer = NULL; 01399 PMDL Mdl; 01400 UNICODE_STRING CapturedFileName; 01401 PUNICODE_STRING SearchPattern; 01402 PAGED_CODE(); 01403 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 01404 01405 /* Check if we came from user mode */ 01406 if (PreviousMode != KernelMode) 01407 { 01408 /* Enter SEH for probing */ 01409 _SEH2_TRY 01410 { 01411 /* Probe the I/O Status Block */ 01412 ProbeForWriteIoStatusBlock(IoStatusBlock); 01413 01414 /* Probe the file information */ 01415 ProbeForWrite(FileInformation, Length, sizeof(ULONG)); 01416 01417 /* Check if we have a file name */ 01418 if (FileName) 01419 { 01420 /* Capture it */ 01421 CapturedFileName = ProbeForReadUnicodeString(FileName); 01422 if (CapturedFileName.Length) 01423 { 01424 /* Probe its buffer */ 01425 ProbeForRead(CapturedFileName.Buffer, 01426 CapturedFileName.Length, 01427 1); 01428 } 01429 01430 /* Allocate the auxiliary buffer */ 01431 AuxBuffer = ExAllocatePoolWithTag(NonPagedPool, 01432 CapturedFileName.Length + 01433 sizeof(UNICODE_STRING), 01434 TAG_SYSB); 01435 RtlCopyMemory((PVOID)((ULONG_PTR)AuxBuffer + 01436 sizeof(UNICODE_STRING)), 01437 CapturedFileName.Buffer, 01438 CapturedFileName.Length); 01439 01440 /* Setup the search pattern */ 01441 SearchPattern = (PUNICODE_STRING)AuxBuffer; 01442 SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)AuxBuffer + 01443 sizeof(UNICODE_STRING)); 01444 SearchPattern->Length = CapturedFileName.Length; 01445 SearchPattern->MaximumLength = CapturedFileName.Length; 01446 } 01447 } 01448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01449 { 01450 /* Free buffer and return the exception code */ 01451 if (AuxBuffer) ExFreePool(AuxBuffer); 01452 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01453 } 01454 _SEH2_END; 01455 } 01456 01457 /* Get File Object */ 01458 Status = ObReferenceObjectByHandle(FileHandle, 01459 FILE_LIST_DIRECTORY, 01460 IoFileObjectType, 01461 PreviousMode, 01462 (PVOID *)&FileObject, 01463 NULL); 01464 if (!NT_SUCCESS(Status)) 01465 { 01466 /* Fail */ 01467 if (AuxBuffer) ExFreePool(AuxBuffer); 01468 return Status; 01469 } 01470 01471 /* Check if we have an even handle */ 01472 if (EventHandle) 01473 { 01474 /* Get its pointer */ 01475 Status = ObReferenceObjectByHandle(EventHandle, 01476 EVENT_MODIFY_STATE, 01477 ExEventObjectType, 01478 PreviousMode, 01479 (PVOID *)&Event, 01480 NULL); 01481 if (!NT_SUCCESS(Status)) 01482 { 01483 /* Fail */ 01484 ObDereferenceObject(FileObject); 01485 return Status; 01486 } 01487 01488 /* Clear it */ 01489 KeClearEvent(Event); 01490 } 01491 01492 /* Check if this is a file that was opened for Synch I/O */ 01493 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01494 { 01495 /* Lock it */ 01496 IopLockFileObject(FileObject); 01497 01498 /* Remember to unlock later */ 01499 LockedForSynch = TRUE; 01500 } 01501 01502 /* Get the device object */ 01503 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01504 01505 /* Clear the File Object's event */ 01506 KeClearEvent(&FileObject->Event); 01507 01508 /* Allocate the IRP */ 01509 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); 01510 if (!Irp) return IopCleanupFailedIrp(FileObject, EventHandle, AuxBuffer); 01511 01512 /* Set up the IRP */ 01513 Irp->RequestorMode = PreviousMode; 01514 Irp->UserIosb = IoStatusBlock; 01515 Irp->UserEvent = Event; 01516 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01517 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01518 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01519 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01520 Irp->MdlAddress = NULL; 01521 Irp->Tail.Overlay.AuxiliaryBuffer = AuxBuffer; 01522 Irp->AssociatedIrp.SystemBuffer = NULL; 01523 01524 /* Check if this is buffered I/O */ 01525 if (DeviceObject->Flags & DO_BUFFERED_IO) 01526 { 01527 /* Enter SEH */ 01528 _SEH2_TRY 01529 { 01530 /* Allocate a buffer */ 01531 Irp->AssociatedIrp.SystemBuffer = 01532 ExAllocatePoolWithTag(NonPagedPool, 01533 Length, 01534 TAG_SYSB); 01535 } 01536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01537 { 01538 /* Allocating failed, clean up and return the exception code */ 01539 IopCleanupAfterException(FileObject, Irp, Event, NULL); 01540 if (AuxBuffer) ExFreePool(AuxBuffer); 01541 01542 /* Return the exception code */ 01543 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01544 } 01545 _SEH2_END; 01546 01547 /* Set the buffer and flags */ 01548 Irp->UserBuffer = FileInformation; 01549 Irp->Flags = (IRP_BUFFERED_IO | 01550 IRP_DEALLOCATE_BUFFER | 01551 IRP_INPUT_OPERATION); 01552 } 01553 else if (DeviceObject->Flags & DO_DIRECT_IO) 01554 { 01555 _SEH2_TRY 01556 { 01557 /* Allocate an MDL */ 01558 Mdl = IoAllocateMdl(FileInformation, Length, FALSE, TRUE, Irp); 01559 if (!Mdl) ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); 01560 MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); 01561 } 01562 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01563 { 01564 /* Allocating failed, clean up and return the exception code */ 01565 IopCleanupAfterException(FileObject, Irp, Event, NULL); 01566 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01567 } 01568 _SEH2_END; 01569 } 01570 else 01571 { 01572 /* No allocation flags, and use the buffer directly */ 01573 Irp->UserBuffer = FileInformation; 01574 } 01575 01576 /* Set up Stack Data */ 01577 StackPtr = IoGetNextIrpStackLocation(Irp); 01578 StackPtr->FileObject = FileObject; 01579 StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 01580 StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY; 01581 01582 /* Set Parameters */ 01583 StackPtr->Parameters.QueryDirectory.FileInformationClass = 01584 FileInformationClass; 01585 StackPtr->Parameters.QueryDirectory.FileName = AuxBuffer; 01586 StackPtr->Parameters.QueryDirectory.FileIndex = 0; 01587 StackPtr->Parameters.QueryDirectory.Length = Length; 01588 StackPtr->Flags = 0; 01589 if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN; 01590 if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY; 01591 01592 /* Set deferred I/O */ 01593 Irp->Flags |= IRP_DEFER_IO_COMPLETION; 01594 01595 /* Perform the call */ 01596 return IopPerformSynchronousRequest(DeviceObject, 01597 Irp, 01598 FileObject, 01599 TRUE, 01600 PreviousMode, 01601 LockedForSynch, 01602 IopOtherTransfer); 01603 } 01604 01605 /* 01606 * @unimplemented 01607 */ 01608 NTSTATUS 01609 NTAPI 01610 NtQueryEaFile(IN HANDLE FileHandle, 01611 OUT PIO_STATUS_BLOCK IoStatusBlock, 01612 OUT PVOID Buffer, 01613 IN ULONG Length, 01614 IN BOOLEAN ReturnSingleEntry, 01615 IN PVOID EaList OPTIONAL, 01616 IN ULONG EaListLength, 01617 IN PULONG EaIndex OPTIONAL, 01618 IN BOOLEAN RestartScan) 01619 { 01620 UNIMPLEMENTED; 01621 return STATUS_NOT_IMPLEMENTED; 01622 } 01623 01624 /* 01625 * @implemented 01626 */ 01627 NTSTATUS 01628 NTAPI 01629 NtQueryInformationFile(IN HANDLE FileHandle, 01630 OUT PIO_STATUS_BLOCK IoStatusBlock, 01631 IN PVOID FileInformation, 01632 IN ULONG Length, 01633 IN FILE_INFORMATION_CLASS FileInformationClass) 01634 { 01635 OBJECT_HANDLE_INFORMATION HandleInformation; 01636 PFILE_OBJECT FileObject; 01637 NTSTATUS Status; 01638 PIRP Irp; 01639 PDEVICE_OBJECT DeviceObject; 01640 PIO_STACK_LOCATION StackPtr; 01641 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 01642 PKEVENT Event = NULL; 01643 BOOLEAN LocalEvent = FALSE; 01644 PKNORMAL_ROUTINE NormalRoutine; 01645 PVOID NormalContext; 01646 KIRQL OldIrql; 01647 IO_STATUS_BLOCK KernelIosb; 01648 PAGED_CODE(); 01649 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 01650 01651 /* Check if we're called from user mode */ 01652 if (PreviousMode != KernelMode) 01653 { 01654 /* Validate the information class */ 01655 if ((FileInformationClass >= FileMaximumInformation) || 01656 !(IopQueryOperationLength[FileInformationClass])) 01657 { 01658 /* Invalid class */ 01659 return STATUS_INVALID_INFO_CLASS; 01660 } 01661 01662 /* Validate the length */ 01663 if (Length < IopQueryOperationLength[FileInformationClass]) 01664 { 01665 /* Invalid length */ 01666 return STATUS_INFO_LENGTH_MISMATCH; 01667 } 01668 01669 /* Enter SEH for probing */ 01670 _SEH2_TRY 01671 { 01672 /* Probe the I/O Status block */ 01673 ProbeForWriteIoStatusBlock(IoStatusBlock); 01674 01675 /* Probe the information */ 01676 ProbeForWrite(FileInformation, Length, sizeof(ULONG)); 01677 } 01678 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01679 { 01680 /* Return the exception code */ 01681 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01682 } 01683 _SEH2_END; 01684 } 01685 else 01686 { 01687 /* Validate the information class */ 01688 if ((FileInformationClass >= FileMaximumInformation) || 01689 !(IopQueryOperationLength[FileInformationClass])) 01690 { 01691 /* Invalid class */ 01692 return STATUS_INVALID_INFO_CLASS; 01693 } 01694 01695 /* Validate the length */ 01696 if (Length < IopQueryOperationLength[FileInformationClass]) 01697 { 01698 /* Invalid length */ 01699 return STATUS_INFO_LENGTH_MISMATCH; 01700 } 01701 } 01702 01703 /* Reference the Handle */ 01704 Status = ObReferenceObjectByHandle(FileHandle, 01705 IopQueryOperationAccess 01706 [FileInformationClass], 01707 IoFileObjectType, 01708 PreviousMode, 01709 (PVOID *)&FileObject, 01710 &HandleInformation); 01711 if (!NT_SUCCESS(Status)) return Status; 01712 01713 /* Check if this is a direct open or not */ 01714 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 01715 { 01716 /* Get the device object */ 01717 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 01718 } 01719 else 01720 { 01721 /* Get the device object */ 01722 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01723 } 01724 01725 /* Check if this is a file that was opened for Synch I/O */ 01726 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01727 { 01728 /* Lock it */ 01729 IopLockFileObject(FileObject); 01730 01731 /* Check if the caller just wants the position */ 01732 if (FileInformationClass == FilePositionInformation) 01733 { 01734 /* Protect write in SEH */ 01735 _SEH2_TRY 01736 { 01737 /* Write the offset */ 01738 ((PFILE_POSITION_INFORMATION)FileInformation)-> 01739 CurrentByteOffset = FileObject->CurrentByteOffset; 01740 01741 /* Fill out the I/O Status Block */ 01742 IoStatusBlock->Information = sizeof(FILE_POSITION_INFORMATION); 01743 Status = IoStatusBlock->Status = STATUS_SUCCESS; 01744 } 01745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01746 { 01747 /* Get the exception code */ 01748 Status = _SEH2_GetExceptionCode(); 01749 } 01750 _SEH2_END; 01751 01752 /* Release the file lock, dereference the file and return */ 01753 IopUnlockFileObject(FileObject); 01754 ObDereferenceObject(FileObject); 01755 return Status; 01756 } 01757 } 01758 else 01759 { 01760 /* Use local event */ 01761 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 01762 if (!Event) 01763 { 01764 ObDereferenceObject(FileObject); 01765 return STATUS_INSUFFICIENT_RESOURCES; 01766 } 01767 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 01768 LocalEvent = TRUE; 01769 } 01770 01771 /* Clear the File Object event */ 01772 KeClearEvent(&FileObject->Event); 01773 01774 /* Allocate the IRP */ 01775 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 01776 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); 01777 01778 /* Set the IRP */ 01779 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01780 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01781 Irp->RequestorMode = PreviousMode; 01782 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 01783 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 01784 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 01785 Irp->UserEvent = (LocalEvent) ? Event : NULL; 01786 Irp->AssociatedIrp.SystemBuffer = NULL; 01787 Irp->MdlAddress = NULL; 01788 Irp->UserBuffer = FileInformation; 01789 01790 /* Set the Stack Data */ 01791 StackPtr = IoGetNextIrpStackLocation(Irp); 01792 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION; 01793 StackPtr->FileObject = FileObject; 01794 01795 /* Enter SEH */ 01796 _SEH2_TRY 01797 { 01798 /* Allocate a buffer */ 01799 Irp->AssociatedIrp.SystemBuffer = 01800 ExAllocatePoolWithTag(NonPagedPool, 01801 Length, 01802 TAG_SYSB); 01803 } 01804 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01805 { 01806 /* Allocating failed, clean up and return the exception code */ 01807 IopCleanupAfterException(FileObject, Irp, NULL, Event); 01808 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01809 } 01810 _SEH2_END; 01811 01812 /* Set the flags */ 01813 Irp->Flags |= (IRP_BUFFERED_IO | 01814 IRP_DEALLOCATE_BUFFER | 01815 IRP_INPUT_OPERATION | 01816 IRP_DEFER_IO_COMPLETION); 01817 01818 /* Set the Parameters */ 01819 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass; 01820 StackPtr->Parameters.QueryFile.Length = Length; 01821 01822 /* Queue the IRP */ 01823 IopQueueIrpToThread(Irp); 01824 01825 /* Update operation counts */ 01826 IopUpdateOperationCount(IopOtherTransfer); 01827 01828 /* Call the Driver */ 01829 Status = IoCallDriver(DeviceObject, Irp); 01830 if (Status == STATUS_PENDING) 01831 { 01832 /* Check if this was async I/O */ 01833 if (LocalEvent) 01834 { 01835 /* Then to a non-alertable wait */ 01836 Status = KeWaitForSingleObject(Event, 01837 Executive, 01838 PreviousMode, 01839 FALSE, 01840 NULL); 01841 if (Status == STATUS_USER_APC) 01842 { 01843 /* Abort the request */ 01844 IopAbortInterruptedIrp(Event, Irp); 01845 } 01846 01847 /* Set the final status */ 01848 Status = KernelIosb.Status; 01849 01850 /* Enter SEH to write the IOSB back */ 01851 _SEH2_TRY 01852 { 01853 /* Write it back to the caller */ 01854 *IoStatusBlock = KernelIosb; 01855 } 01856 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01857 { 01858 /* Get the exception code */ 01859 Status = _SEH2_GetExceptionCode(); 01860 } 01861 _SEH2_END; 01862 01863 /* Free the event */ 01864 ExFreePool(Event); 01865 } 01866 else 01867 { 01868 /* Wait for the IRP */ 01869 Status = KeWaitForSingleObject(&FileObject->Event, 01870 Executive, 01871 PreviousMode, 01872 FileObject->Flags & FO_ALERTABLE_IO, 01873 NULL); 01874 if ((Status == STATUS_USER_APC) || (Status == STATUS_ALERTED)) 01875 { 01876 /* Abort the request */ 01877 IopAbortInterruptedIrp(&FileObject->Event, Irp); 01878 } 01879 01880 /* Set the final status */ 01881 Status = FileObject->FinalStatus; 01882 01883 /* Release the file lock */ 01884 IopUnlockFileObject(FileObject); 01885 } 01886 } 01887 else 01888 { 01889 /* Free the event if we had one */ 01890 if (LocalEvent) 01891 { 01892 /* Clear it in the IRP for completion */ 01893 Irp->UserEvent = NULL; 01894 ExFreePoolWithTag(Event, TAG_IO); 01895 } 01896 01897 /* Set the caller IOSB */ 01898 Irp->UserIosb = IoStatusBlock; 01899 01900 /* The IRP wasn't completed, complete it ourselves */ 01901 KeRaiseIrql(APC_LEVEL, &OldIrql); 01902 IopCompleteRequest(&Irp->Tail.Apc, 01903 &NormalRoutine, 01904 &NormalContext, 01905 (PVOID*)&FileObject, 01906 &NormalContext); 01907 KeLowerIrql(OldIrql); 01908 01909 /* Release the file object if we had locked it*/ 01910 if (!LocalEvent) IopUnlockFileObject(FileObject); 01911 } 01912 01913 /* Return the Status */ 01914 return Status; 01915 } 01916 01917 /* 01918 * @unimplemented 01919 */ 01920 NTSTATUS 01921 NTAPI 01922 NtQueryQuotaInformationFile(IN HANDLE FileHandle, 01923 OUT PIO_STATUS_BLOCK IoStatusBlock, 01924 OUT PVOID Buffer, 01925 IN ULONG Length, 01926 IN BOOLEAN ReturnSingleEntry, 01927 IN PVOID SidList OPTIONAL, 01928 IN ULONG SidListLength, 01929 IN PSID StartSid OPTIONAL, 01930 IN BOOLEAN RestartScan) 01931 { 01932 UNIMPLEMENTED; 01933 return STATUS_NOT_IMPLEMENTED; 01934 } 01935 01936 /* 01937 * @implemented 01938 */ 01939 NTSTATUS 01940 NTAPI 01941 NtReadFile(IN HANDLE FileHandle, 01942 IN HANDLE Event OPTIONAL, 01943 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 01944 IN PVOID ApcContext OPTIONAL, 01945 OUT PIO_STATUS_BLOCK IoStatusBlock, 01946 OUT PVOID Buffer, 01947 IN ULONG Length, 01948 IN PLARGE_INTEGER ByteOffset OPTIONAL, 01949 IN PULONG Key OPTIONAL) 01950 { 01951 NTSTATUS Status; 01952 PFILE_OBJECT FileObject; 01953 PIRP Irp; 01954 PDEVICE_OBJECT DeviceObject; 01955 PIO_STACK_LOCATION StackPtr; 01956 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 01957 PKEVENT EventObject = NULL; 01958 LARGE_INTEGER CapturedByteOffset; 01959 ULONG CapturedKey = 0; 01960 BOOLEAN Synchronous = FALSE; 01961 PMDL Mdl; 01962 PAGED_CODE(); 01963 CapturedByteOffset.QuadPart = 0; 01964 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 01965 01966 /* Validate User-Mode Buffers */ 01967 if (PreviousMode != KernelMode) 01968 { 01969 _SEH2_TRY 01970 { 01971 /* Probe the status block */ 01972 ProbeForWriteIoStatusBlock(IoStatusBlock); 01973 01974 /* Probe the read buffer */ 01975 ProbeForWrite(Buffer, Length, 1); 01976 01977 /* Check if we got a byte offset */ 01978 if (ByteOffset) 01979 { 01980 /* Capture and probe it */ 01981 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); 01982 } 01983 01984 /* Capture and probe the key */ 01985 if (Key) CapturedKey = ProbeForReadUlong(Key); 01986 } 01987 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01988 { 01989 /* Return the exception code */ 01990 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01991 } 01992 _SEH2_END; 01993 } 01994 else 01995 { 01996 /* Kernel mode: capture directly */ 01997 if (ByteOffset) CapturedByteOffset = *ByteOffset; 01998 if (Key) CapturedKey = *Key; 01999 } 02000 02001 /* Get File Object */ 02002 Status = ObReferenceObjectByHandle(FileHandle, 02003 FILE_READ_DATA, 02004 IoFileObjectType, 02005 PreviousMode, 02006 (PVOID*)&FileObject, 02007 NULL); 02008 if (!NT_SUCCESS(Status)) return Status; 02009 02010 /* Check for event */ 02011 if (Event) 02012 { 02013 /* Reference it */ 02014 Status = ObReferenceObjectByHandle(Event, 02015 EVENT_MODIFY_STATE, 02016 ExEventObjectType, 02017 PreviousMode, 02018 (PVOID*)&EventObject, 02019 NULL); 02020 if (!NT_SUCCESS(Status)) 02021 { 02022 /* Fail */ 02023 ObDereferenceObject(FileObject); 02024 return Status; 02025 } 02026 02027 /* Otherwise reset the event */ 02028 KeClearEvent(EventObject); 02029 } 02030 02031 /* Check if we should use Sync IO or not */ 02032 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 02033 { 02034 /* Lock the file object */ 02035 IopLockFileObject(FileObject); 02036 02037 /* Check if we don't have a byte offset avilable */ 02038 if (!(ByteOffset) || 02039 ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) && 02040 (CapturedByteOffset.u.HighPart == -1))) 02041 { 02042 /* Use the Current Byte Offset instead */ 02043 CapturedByteOffset = FileObject->CurrentByteOffset; 02044 } 02045 02046 /* Remember we are sync */ 02047 Synchronous = TRUE; 02048 } 02049 else if (!(ByteOffset) && 02050 !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) 02051 { 02052 /* Otherwise, this was async I/O without a byte offset, so fail */ 02053 if (EventObject) ObDereferenceObject(EventObject); 02054 ObDereferenceObject(FileObject); 02055 return STATUS_INVALID_PARAMETER; 02056 } 02057 02058 /* Get the device object */ 02059 DeviceObject = IoGetRelatedDeviceObject(FileObject); 02060 02061 /* Clear the File Object's event */ 02062 KeClearEvent(&FileObject->Event); 02063 02064 /* Allocate the IRP */ 02065 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 02066 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 02067 02068 /* Set the IRP */ 02069 Irp->Tail.Overlay.OriginalFileObject = FileObject; 02070 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 02071 Irp->RequestorMode = PreviousMode; 02072 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 02073 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 02074 Irp->UserIosb = IoStatusBlock; 02075 Irp->UserEvent = EventObject; 02076 Irp->PendingReturned = FALSE; 02077 Irp->Cancel = FALSE; 02078 Irp->CancelRoutine = NULL; 02079 Irp->AssociatedIrp.SystemBuffer = NULL; 02080 Irp->MdlAddress = NULL; 02081 02082 /* Set the Stack Data */ 02083 StackPtr = IoGetNextIrpStackLocation(Irp); 02084 StackPtr->MajorFunction = IRP_MJ_READ; 02085 StackPtr->FileObject = FileObject; 02086 StackPtr->Parameters.Read.Key = CapturedKey; 02087 StackPtr->Parameters.Read.Length = Length; 02088 StackPtr->Parameters.Read.ByteOffset = CapturedByteOffset; 02089 02090 /* Check if this is buffered I/O */ 02091 if (DeviceObject->Flags & DO_BUFFERED_IO) 02092 { 02093 /* Check if we have a buffer length */ 02094 if (Length) 02095 { 02096 /* Enter SEH */ 02097 _SEH2_TRY 02098 { 02099 /* Allocate a buffer */ 02100 Irp->AssociatedIrp.SystemBuffer = 02101 ExAllocatePoolWithTag(NonPagedPool, 02102 Length, 02103 TAG_SYSB); 02104 } 02105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02106 { 02107 /* Allocating failed, clean up and return the exception code */ 02108 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 02109 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02110 } 02111 _SEH2_END; 02112 02113 /* Set the buffer and flags */ 02114 Irp->UserBuffer = Buffer; 02115 Irp->Flags = (IRP_BUFFERED_IO | 02116 IRP_DEALLOCATE_BUFFER | 02117 IRP_INPUT_OPERATION); 02118 } 02119 else 02120 { 02121 /* Not reading anything */ 02122 Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; 02123 } 02124 } 02125 else if (DeviceObject->Flags & DO_DIRECT_IO) 02126 { 02127 /* Check if we have a buffer length */ 02128 if (Length) 02129 { 02130 _SEH2_TRY 02131 { 02132 /* Allocate an MDL */ 02133 Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); 02134 MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); 02135 } 02136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02137 { 02138 /* Allocating failed, clean up and return the exception code */ 02139 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 02140 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02141 } 02142 _SEH2_END; 02143 02144 } 02145 02146 /* No allocation flags */ 02147 Irp->Flags = 0; 02148 } 02149 else 02150 { 02151 /* No allocation flags, and use the buffer directly */ 02152 Irp->Flags = 0; 02153 Irp->UserBuffer = Buffer; 02154 } 02155 02156 /* Now set the deferred read flags */ 02157 Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION); 02158 #if 0 02159 /* FIXME: VFAT SUCKS */ 02160 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; 02161 #endif 02162 02163 /* Perform the call */ 02164 return IopPerformSynchronousRequest(DeviceObject, 02165 Irp, 02166 FileObject, 02167 TRUE, 02168 PreviousMode, 02169 Synchronous, 02170 IopReadTransfer); 02171 } 02172 02173 /* 02174 * @unimplemented 02175 */ 02176 NTSTATUS 02177 NTAPI 02178 NtReadFileScatter(IN HANDLE FileHandle, 02179 IN HANDLE Event OPTIONAL, 02180 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 02181 IN PVOID UserApcContext OPTIONAL, 02182 OUT PIO_STATUS_BLOCK UserIoStatusBlock, 02183 IN FILE_SEGMENT_ELEMENT BufferDescription [], 02184 IN ULONG BufferLength, 02185 IN PLARGE_INTEGER ByteOffset, 02186 IN PULONG Key OPTIONAL) 02187 { 02188 UNIMPLEMENTED; 02189 return STATUS_NOT_IMPLEMENTED; 02190 } 02191 02192 /* 02193 * @unimplemented 02194 */ 02195 NTSTATUS 02196 NTAPI 02197 NtSetEaFile(IN HANDLE FileHandle, 02198 IN PIO_STATUS_BLOCK IoStatusBlock, 02199 IN PVOID EaBuffer, 02200 IN ULONG EaBufferSize) 02201 { 02202 UNIMPLEMENTED; 02203 return STATUS_NOT_IMPLEMENTED; 02204 } 02205 02206 /* 02207 * @implemented 02208 */ 02209 NTSTATUS 02210 NTAPI 02211 NtSetInformationFile(IN HANDLE FileHandle, 02212 OUT PIO_STATUS_BLOCK IoStatusBlock, 02213 IN PVOID FileInformation, 02214 IN ULONG Length, 02215 IN FILE_INFORMATION_CLASS FileInformationClass) 02216 { 02217 PFILE_OBJECT FileObject; 02218 NTSTATUS Status; 02219 PIRP Irp; 02220 PDEVICE_OBJECT DeviceObject; 02221 PIO_STACK_LOCATION StackPtr; 02222 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 02223 PKEVENT Event = NULL; 02224 BOOLEAN LocalEvent = FALSE; 02225 PKNORMAL_ROUTINE NormalRoutine; 02226 PVOID NormalContext; 02227 KIRQL OldIrql; 02228 IO_STATUS_BLOCK KernelIosb; 02229 PVOID Queue; 02230 PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation; 02231 PIO_COMPLETION_CONTEXT Context; 02232 PAGED_CODE(); 02233 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 02234 02235 /* Check if we're called from user mode */ 02236 if (PreviousMode != KernelMode) 02237 { 02238 /* Validate the information class */ 02239 if ((FileInformationClass >= FileMaximumInformation) || 02240 !(IopSetOperationLength[FileInformationClass])) 02241 { 02242 /* Invalid class */ 02243 return STATUS_INVALID_INFO_CLASS; 02244 } 02245 02246 /* Validate the length */ 02247 if (Length < IopSetOperationLength[FileInformationClass]) 02248 { 02249 /* Invalid length */ 02250 return STATUS_INFO_LENGTH_MISMATCH; 02251 } 02252 02253 /* Enter SEH for probing */ 02254 _SEH2_TRY 02255 { 02256 /* Probe the I/O Status block */ 02257 ProbeForWriteIoStatusBlock(IoStatusBlock); 02258 02259 /* Probe the information */ 02260 ProbeForRead(FileInformation, 02261 Length, 02262 (Length == sizeof(BOOLEAN)) ? 02263 sizeof(BOOLEAN) : sizeof(ULONG)); 02264 } 02265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02266 { 02267 /* Return the exception code */ 02268 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02269 } 02270 _SEH2_END; 02271 } 02272 else 02273 { 02274 /* Validate the information class */ 02275 if ((FileInformationClass >= FileMaximumInformation) || 02276 !(IopSetOperationLength[FileInformationClass])) 02277 { 02278 /* Invalid class */ 02279 return STATUS_INVALID_INFO_CLASS; 02280 } 02281 02282 /* Validate the length */ 02283 if (Length < IopSetOperationLength[FileInformationClass]) 02284 { 02285 /* Invalid length */ 02286 return STATUS_INFO_LENGTH_MISMATCH; 02287 } 02288 } 02289 02290 /* Reference the Handle */ 02291 Status = ObReferenceObjectByHandle(FileHandle, 02292 IopSetOperationAccess 02293 [FileInformationClass], 02294 IoFileObjectType, 02295 PreviousMode, 02296 (PVOID *)&FileObject, 02297 NULL); 02298 if (!NT_SUCCESS(Status)) return Status; 02299 02300 /* Check if this is a direct open or not */ 02301 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 02302 { 02303 /* Get the device object */ 02304 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 02305 } 02306 else 02307 { 02308 /* Get the device object */ 02309 DeviceObject = IoGetRelatedDeviceObject(FileObject); 02310 } 02311 02312 /* Check if this is a file that was opened for Synch I/O */ 02313 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 02314 { 02315 /* Lock it */ 02316 IopLockFileObject(FileObject); 02317 02318 /* Check if the caller just wants the position */ 02319 if (FileInformationClass == FilePositionInformation) 02320 { 02321 /* Protect write in SEH */ 02322 _SEH2_TRY 02323 { 02324 /* Write the offset */ 02325 FileObject->CurrentByteOffset = 02326 ((PFILE_POSITION_INFORMATION)FileInformation)-> 02327 CurrentByteOffset; 02328 02329 /* Fill out the I/O Status Block */ 02330 IoStatusBlock->Information = 0; 02331 Status = IoStatusBlock->Status = STATUS_SUCCESS; 02332 } 02333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02334 { 02335 /* Get the exception code */ 02336 Status = _SEH2_GetExceptionCode(); 02337 } 02338 _SEH2_END; 02339 02340 /* Update transfer count */ 02341 IopUpdateTransferCount(IopOtherTransfer, Length); 02342 02343 /* Release the file lock, dereference the file and return */ 02344 IopUnlockFileObject(FileObject); 02345 ObDereferenceObject(FileObject); 02346 return Status; 02347 } 02348 } 02349 else 02350 { 02351 /* Use local event */ 02352 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 02353 if (!Event) 02354 { 02355 ObDereferenceObject(FileObject); 02356 return STATUS_INSUFFICIENT_RESOURCES; 02357 } 02358 02359 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 02360 LocalEvent = TRUE; 02361 } 02362 02363 /* Clear the File Object event */ 02364 KeClearEvent(&FileObject->Event); 02365 02366 /* Allocate the IRP */ 02367 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); 02368 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); 02369 02370 /* Set the IRP */ 02371 Irp->Tail.Overlay.OriginalFileObject = FileObject; 02372 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 02373 Irp->RequestorMode = PreviousMode; 02374 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 02375 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 02376 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 02377 Irp->UserEvent = (LocalEvent) ? Event : NULL; 02378 Irp->AssociatedIrp.SystemBuffer = NULL; 02379 Irp->MdlAddress = NULL; 02380 Irp->UserBuffer = FileInformation; 02381 02382 /* Set the Stack Data */ 02383 StackPtr = IoGetNextIrpStackLocation(Irp); 02384 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION; 02385 StackPtr->FileObject = FileObject; 02386 02387 /* Enter SEH */ 02388 _SEH2_TRY 02389 { 02390 /* Allocate a buffer */ 02391 Irp->AssociatedIrp.SystemBuffer = 02392 ExAllocatePoolWithTag(NonPagedPool, 02393 Length, 02394 TAG_SYSB); 02395 02396 /* Copy the data into it */ 02397 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 02398 FileInformation, 02399 Length); 02400 } 02401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02402 { 02403 /* Allocating failed, clean up and return the exception code */ 02404 IopCleanupAfterException(FileObject, Irp, NULL, Event); 02405 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02406 } 02407 _SEH2_END; 02408 02409 /* Set the flags */ 02410 Irp->Flags |= (IRP_BUFFERED_IO | 02411 IRP_DEALLOCATE_BUFFER | 02412 IRP_DEFER_IO_COMPLETION); 02413 02414 /* Set the Parameters */ 02415 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass; 02416 StackPtr->Parameters.SetFile.Length = Length; 02417 02418 /* Queue the IRP */ 02419 IopQueueIrpToThread(Irp); 02420 02421 /* Update operation counts */ 02422 IopUpdateOperationCount(IopOtherTransfer); 02423 02424 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */ 02425 /* Handle IO Completion Port quickly */ 02426 if (FileInformationClass == FileCompletionInformation) 02427 { 02428 /* Check if the file object already has a completion port */ 02429 if ((FileObject->Flags & FO_SYNCHRONOUS_IO) || 02430 (FileObject->CompletionContext)) 02431 { 02432 /* Fail */ 02433 Status = STATUS_INVALID_PARAMETER; 02434 } 02435 else 02436 { 02437 /* Reference the Port */ 02438 CompletionInfo = Irp->AssociatedIrp.SystemBuffer; 02439 Status = ObReferenceObjectByHandle(CompletionInfo->Port, 02440 IO_COMPLETION_MODIFY_STATE, 02441 IoCompletionType, 02442 PreviousMode, 02443 (PVOID*)&Queue, 02444 NULL); 02445 if (NT_SUCCESS(Status)) 02446 { 02447 /* Allocate the Context */ 02448 Context = ExAllocatePoolWithTag(PagedPool, 02449 sizeof(IO_COMPLETION_CONTEXT), 02450 IOC_TAG); 02451 if (Context) 02452 { 02453 /* Set the Data */ 02454 Context->Key = CompletionInfo->Key; 02455 Context->Port = Queue; 02456 if (InterlockedCompareExchangePointer((PVOID*)&FileObject-> 02457 CompletionContext, 02458 Context, 02459 NULL)) 02460 { 02461 /* 02462 * Someone else set the completion port in the 02463 * meanwhile, so dereference the port and fail. 02464 */ 02465 ExFreePool(Context); 02466 ObDereferenceObject(Queue); 02467 Status = STATUS_INVALID_PARAMETER; 02468 } 02469 } 02470 else 02471 { 02472 /* Dereference the Port now */ 02473 ObDereferenceObject(Queue); 02474 Status = STATUS_INSUFFICIENT_RESOURCES; 02475 } 02476 } 02477 } 02478 02479 /* Set the IRP Status */ 02480 Irp->IoStatus.Status = Status; 02481 Irp->IoStatus.Information = 0; 02482 } 02483 else 02484 { 02485 /* Call the Driver */ 02486 Status = IoCallDriver(DeviceObject, Irp); 02487 } 02488 02489 /* Check if we're waiting for the IRP to complete */ 02490 if (Status == STATUS_PENDING) 02491 { 02492 /* Check if this was async I/O */ 02493 if (LocalEvent) 02494 { 02495 /* Then to a non-alertable wait */ 02496 Status = KeWaitForSingleObject(Event, 02497 Executive, 02498 PreviousMode, 02499 FALSE, 02500 NULL); 02501 if (Status == STATUS_USER_APC) 02502 { 02503 /* Abort the request */ 02504 IopAbortInterruptedIrp(Event, Irp); 02505 } 02506 02507 /* Set the final status */ 02508 Status = KernelIosb.Status; 02509 02510 /* Enter SEH to write the IOSB back */ 02511 _SEH2_TRY 02512 { 02513 /* Write it back to the caller */ 02514 *IoStatusBlock = KernelIosb; 02515 } 02516 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02517 { 02518 /* Get the exception code */ 02519 Status = _SEH2_GetExceptionCode(); 02520 } 02521 _SEH2_END; 02522 02523 /* Free the event */ 02524 ExFreePool(Event); 02525 } 02526 else 02527 { 02528 /* Wait for the IRP */ 02529 Status = KeWaitForSingleObject(&FileObject->Event, 02530 Executive, 02531 PreviousMode, 02532 FileObject->Flags & FO_ALERTABLE_IO, 02533 NULL); 02534 if ((Status == STATUS_USER_APC) || (Status == STATUS_ALERTED)) 02535 { 02536 /* Abort the request */ 02537 IopAbortInterruptedIrp(&FileObject->Event, Irp); 02538 } 02539 02540 /* Set the final status */ 02541 Status = FileObject->FinalStatus; 02542 02543 /* Release the file lock */ 02544 IopUnlockFileObject(FileObject); 02545 } 02546 } 02547 else 02548 { 02549 /* Free the event if we had one */ 02550 if (LocalEvent) 02551 { 02552 /* Clear it in the IRP for completion */ 02553 Irp->UserEvent = NULL; 02554 ExFreePool(Event); 02555 } 02556 02557 /* Set the caller IOSB */ 02558 Irp->UserIosb = IoStatusBlock; 02559 02560 /* The IRP wasn't completed, complete it ourselves */ 02561 KeRaiseIrql(APC_LEVEL, &OldIrql); 02562 IopCompleteRequest(&Irp->Tail.Apc, 02563 &NormalRoutine, 02564 &NormalContext, 02565 (PVOID*)&FileObject, 02566 &NormalContext); 02567 KeLowerIrql(OldIrql); 02568 02569 /* Release the file object if we had locked it*/ 02570 if (!LocalEvent) IopUnlockFileObject(FileObject); 02571 } 02572 02573 /* Return the Status */ 02574 return Status; 02575 } 02576 02577 /* 02578 * @unimplemented 02579 */ 02580 NTSTATUS 02581 NTAPI 02582 NtSetQuotaInformationFile(IN HANDLE FileHandle, 02583 OUT PIO_STATUS_BLOCK IoStatusBlock, 02584 IN PVOID Buffer, 02585 IN ULONG BufferLength) 02586 { 02587 UNIMPLEMENTED; 02588 return STATUS_NOT_IMPLEMENTED; 02589 } 02590 02591 /* 02592 * @implemented 02593 */ 02594 NTSTATUS 02595 NTAPI 02596 NtUnlockFile(IN HANDLE FileHandle, 02597 OUT PIO_STATUS_BLOCK IoStatusBlock, 02598 IN PLARGE_INTEGER ByteOffset, 02599 IN PLARGE_INTEGER Length, 02600 IN ULONG Key OPTIONAL) 02601 { 02602 PFILE_OBJECT FileObject; 02603 PLARGE_INTEGER LocalLength = NULL; 02604 PIRP Irp; 02605 PIO_STACK_LOCATION StackPtr; 02606 PDEVICE_OBJECT DeviceObject; 02607 PKEVENT Event = NULL; 02608 BOOLEAN LocalEvent = FALSE; 02609 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 02610 LARGE_INTEGER CapturedByteOffset, CapturedLength; 02611 NTSTATUS Status; 02612 OBJECT_HANDLE_INFORMATION HandleInformation; 02613 IO_STATUS_BLOCK KernelIosb; 02614 PAGED_CODE(); 02615 CapturedByteOffset.QuadPart = 0; 02616 CapturedLength.QuadPart = 0; 02617 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 02618 02619 /* Get File Object */ 02620 Status = ObReferenceObjectByHandle(FileHandle, 02621 0, 02622 IoFileObjectType, 02623 PreviousMode, 02624 (PVOID*)&FileObject, 02625 &HandleInformation); 02626 if (!NT_SUCCESS(Status)) return Status; 02627 02628 /* Check if we're called from user mode */ 02629 if (PreviousMode != KernelMode) 02630 { 02631 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */ 02632 if (!(HandleInformation.GrantedAccess & 02633 (FILE_WRITE_DATA | FILE_READ_DATA))) 02634 { 02635 ObDereferenceObject(FileObject); 02636 return STATUS_ACCESS_DENIED; 02637 } 02638 02639 /* Enter SEH for probing */ 02640 _SEH2_TRY 02641 { 02642 /* Probe the I/O Status block */ 02643 ProbeForWriteIoStatusBlock(IoStatusBlock); 02644 02645 /* Probe and capture the large integers */ 02646 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); 02647 CapturedLength = ProbeForReadLargeInteger(Length); 02648 } 02649 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02650 { 02651 /* Dereference the object and return exception code */ 02652 ObDereferenceObject(FileObject); 02653 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02654 } 02655 _SEH2_END; 02656 } 02657 else 02658 { 02659 /* Otherwise, capture them directly */ 02660 CapturedByteOffset = *ByteOffset; 02661 CapturedLength = *Length; 02662 } 02663 02664 /* Check if this is a direct open or not */ 02665 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 02666 { 02667 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 02668 } 02669 else 02670 { 02671 DeviceObject = IoGetRelatedDeviceObject(FileObject); 02672 } 02673 02674 /* Check if we should use Sync IO or not */ 02675 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 02676 { 02677 /* Lock it */ 02678 IopLockFileObject(FileObject); 02679 } 02680 else 02681 { 02682 /* Use local event */ 02683 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 02684 if (!Event) 02685 { 02686 ObDereferenceObject(FileObject); 02687 return STATUS_INSUFFICIENT_RESOURCES; 02688 } 02689 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 02690 LocalEvent = TRUE; 02691 } 02692 02693 /* Clear File Object event */ 02694 KeClearEvent(&FileObject->Event); 02695 02696 /* Allocate the IRP */ 02697 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 02698 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); 02699 02700 /* Set up the IRP */ 02701 Irp->RequestorMode = PreviousMode; 02702 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 02703 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 02704 Irp->UserEvent = (LocalEvent) ? Event : NULL; 02705 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 02706 Irp->Tail.Overlay.OriginalFileObject = FileObject; 02707 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 02708 02709 /* Set up Stack Data */ 02710 StackPtr = IoGetNextIrpStackLocation(Irp); 02711 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; 02712 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE; 02713 StackPtr->FileObject = FileObject; 02714 02715 /* Enter SEH */ 02716 _SEH2_TRY 02717 { 02718 /* Allocate a buffer */ 02719 LocalLength = ExAllocatePoolWithTag(NonPagedPool, 02720 sizeof(LARGE_INTEGER), 02721 TAG_LOCK); 02722 02723 /* Set the length */ 02724 *LocalLength = CapturedLength; 02725 Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength; 02726 StackPtr->Parameters.LockControl.Length = LocalLength; 02727 } 02728 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02729 { 02730 /* Allocating failed, clean up and return the exception code */ 02731 IopCleanupAfterException(FileObject, Irp, NULL, Event); 02732 if (LocalLength) ExFreePool(LocalLength); 02733 02734 /* Return the exception code */ 02735 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02736 } 02737 _SEH2_END; 02738 02739 /* Set Parameters */ 02740 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset; 02741 StackPtr->Parameters.LockControl.Key = Key; 02742 02743 /* Call the Driver */ 02744 Status = IopPerformSynchronousRequest(DeviceObject, 02745 Irp, 02746 FileObject, 02747 FALSE, 02748 PreviousMode, 02749 !LocalEvent, 02750 IopOtherTransfer); 02751 02752 /* Check if this was async I/O */ 02753 if (LocalEvent) 02754 { 02755 /* It was, finalize this request */ 02756 Status = IopFinalizeAsynchronousIo(Status, 02757 Event, 02758 Irp, 02759 PreviousMode, 02760 &KernelIosb, 02761 IoStatusBlock); 02762 } 02763 02764 /* Return status */ 02765 return Status; 02766 } 02767 02768 /* 02769 * @implemented 02770 */ 02771 NTSTATUS 02772 NTAPI 02773 NtWriteFile(IN HANDLE FileHandle, 02774 IN HANDLE Event OPTIONAL, 02775 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 02776 IN PVOID ApcContext OPTIONAL, 02777 OUT PIO_STATUS_BLOCK IoStatusBlock, 02778 IN PVOID Buffer, 02779 IN ULONG Length, 02780 IN PLARGE_INTEGER ByteOffset OPTIONAL, 02781 IN PULONG Key OPTIONAL) 02782 { 02783 NTSTATUS Status; 02784 PFILE_OBJECT FileObject; 02785 PIRP Irp; 02786 PDEVICE_OBJECT DeviceObject; 02787 PIO_STACK_LOCATION StackPtr; 02788 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 02789 PKEVENT EventObject = NULL; 02790 LARGE_INTEGER CapturedByteOffset; 02791 ULONG CapturedKey = 0; 02792 BOOLEAN Synchronous = FALSE; 02793 PMDL Mdl; 02794 OBJECT_HANDLE_INFORMATION ObjectHandleInfo; 02795 PAGED_CODE(); 02796 CapturedByteOffset.QuadPart = 0; 02797 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 02798 02799 /* Get File Object */ 02800 Status = ObReferenceObjectByHandle(FileHandle, 02801 0, 02802 IoFileObjectType, 02803 PreviousMode, 02804 (PVOID*)&FileObject, 02805 &ObjectHandleInfo); 02806 if (!NT_SUCCESS(Status)) return Status; 02807 02808 /* Validate User-Mode Buffers */ 02809 if (PreviousMode != KernelMode) 02810 { 02811 _SEH2_TRY 02812 { 02813 /* 02814 * Check if the handle has either FILE_WRITE_DATA or 02815 * FILE_APPEND_DATA granted. However, if this is a named pipe, 02816 * make sure we don't ask for FILE_APPEND_DATA as it interferes 02817 * with the FILE_CREATE_PIPE_INSTANCE access right! 02818 */ 02819 if (!(ObjectHandleInfo.GrantedAccess & 02820 ((!(FileObject->Flags & FO_NAMED_PIPE) ? 02821 FILE_APPEND_DATA : 0) | FILE_WRITE_DATA))) 02822 { 02823 /* We failed */ 02824 ObDereferenceObject(FileObject); 02825 _SEH2_YIELD(return STATUS_ACCESS_DENIED); 02826 } 02827 02828 /* Probe the status block */ 02829 ProbeForWriteIoStatusBlock(IoStatusBlock); 02830 02831 /* Probe the read buffer */ 02832 ProbeForRead(Buffer, Length, 1); 02833 02834 /* Check if we got a byte offset */ 02835 if (ByteOffset) 02836 { 02837 /* Capture and probe it */ 02838 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); 02839 } 02840 02841 /* Capture and probe the key */ 02842 if (Key) CapturedKey = ProbeForReadUlong(Key); 02843 } 02844 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02845 { 02846 /* Return the exception code */ 02847 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02848 } 02849 _SEH2_END; 02850 } 02851 else 02852 { 02853 /* Kernel mode: capture directly */ 02854 if (ByteOffset) CapturedByteOffset = *ByteOffset; 02855 if (Key) CapturedKey = *Key; 02856 } 02857 02858 /* Check if this is an append operation */ 02859 if ((ObjectHandleInfo.GrantedAccess & 02860 (FILE_APPEND_DATA | FILE_WRITE_DATA)) == FILE_APPEND_DATA) 02861 { 02862 /* Give the drivers something to understand */ 02863 CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE; 02864 CapturedByteOffset.u.HighPart = -1; 02865 } 02866 02867 /* Check for event */ 02868 if (Event) 02869 { 02870 /* Reference it */ 02871 Status = ObReferenceObjectByHandle(Event, 02872 EVENT_MODIFY_STATE, 02873 ExEventObjectType, 02874 PreviousMode, 02875 (PVOID*)&EventObject, 02876 NULL); 02877 if (!NT_SUCCESS(Status)) 02878 { 02879 /* Fail */ 02880 ObDereferenceObject(FileObject); 02881 return Status; 02882 } 02883 02884 /* Otherwise reset the event */ 02885 KeClearEvent(EventObject); 02886 } 02887 02888 /* Check if we should use Sync IO or not */ 02889 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 02890 { 02891 /* Lock the file object */ 02892 IopLockFileObject(FileObject); 02893 02894 /* Check if we don't have a byte offset avilable */ 02895 if (!(ByteOffset) || 02896 ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) && 02897 (CapturedByteOffset.u.HighPart == -1))) 02898 { 02899 /* Use the Current Byte Offset instead */ 02900 CapturedByteOffset = FileObject->CurrentByteOffset; 02901 } 02902 02903 /* Remember we are sync */ 02904 Synchronous = TRUE; 02905 } 02906 else if (!(ByteOffset) && 02907 !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) 02908 { 02909 /* Otherwise, this was async I/O without a byte offset, so fail */ 02910 if (EventObject) ObDereferenceObject(EventObject); 02911 ObDereferenceObject(FileObject); 02912 return STATUS_INVALID_PARAMETER; 02913 } 02914 02915 /* Get the device object */ 02916 DeviceObject = IoGetRelatedDeviceObject(FileObject); 02917 02918 /* Clear the File Object's event */ 02919 KeClearEvent(&FileObject->Event); 02920 02921 /* Allocate the IRP */ 02922 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 02923 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 02924 02925 /* Set the IRP */ 02926 Irp->Tail.Overlay.OriginalFileObject = FileObject; 02927 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 02928 Irp->RequestorMode = PreviousMode; 02929 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 02930 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 02931 Irp->UserIosb = IoStatusBlock; 02932 Irp->UserEvent = EventObject; 02933 Irp->PendingReturned = FALSE; 02934 Irp->Cancel = FALSE; 02935 Irp->CancelRoutine = NULL; 02936 Irp->AssociatedIrp.SystemBuffer = NULL; 02937 Irp->MdlAddress = NULL; 02938 02939 /* Set the Stack Data */ 02940 StackPtr = IoGetNextIrpStackLocation(Irp); 02941 StackPtr->MajorFunction = IRP_MJ_WRITE; 02942 StackPtr->FileObject = FileObject; 02943 StackPtr->Flags = FileObject->Flags & FO_WRITE_THROUGH ? 02944 SL_WRITE_THROUGH : 0; 02945 StackPtr->Parameters.Write.Key = CapturedKey; 02946 StackPtr->Parameters.Write.Length = Length; 02947 StackPtr->Parameters.Write.ByteOffset = CapturedByteOffset; 02948 02949 /* Check if this is buffered I/O */ 02950 if (DeviceObject->Flags & DO_BUFFERED_IO) 02951 { 02952 /* Check if we have a buffer length */ 02953 if (Length) 02954 { 02955 /* Enter SEH */ 02956 _SEH2_TRY 02957 { 02958 /* Allocate a buffer */ 02959 Irp->AssociatedIrp.SystemBuffer = 02960 ExAllocatePoolWithTag(NonPagedPool, 02961 Length, 02962 TAG_SYSB); 02963 02964 /* Copy the data into it */ 02965 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length); 02966 } 02967 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02968 { 02969 /* Allocating failed, clean up and return the exception code */ 02970 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 02971 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02972 } 02973 _SEH2_END; 02974 02975 /* Set the flags */ 02976 Irp->Flags = (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); 02977 } 02978 else 02979 { 02980 /* Not writing anything */ 02981 Irp->Flags = IRP_BUFFERED_IO; 02982 } 02983 } 02984 else if (DeviceObject->Flags & DO_DIRECT_IO) 02985 { 02986 /* Check if we have a buffer length */ 02987 if (Length) 02988 { 02989 _SEH2_TRY 02990 { 02991 /* Allocate an MDL */ 02992 Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); 02993 MmProbeAndLockPages(Mdl, PreviousMode, IoReadAccess); 02994 } 02995 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02996 { 02997 /* Allocating failed, clean up and return the exception code */ 02998 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); 02999 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03000 } 03001 _SEH2_END; 03002 } 03003 03004 /* No allocation flags */ 03005 Irp->Flags = 0; 03006 } 03007 else 03008 { 03009 /* No allocation flags, and use the buffer directly */ 03010 Irp->Flags = 0; 03011 Irp->UserBuffer = Buffer; 03012 } 03013 03014 /* Now set the deferred read flags */ 03015 Irp->Flags |= (IRP_WRITE_OPERATION | IRP_DEFER_IO_COMPLETION); 03016 #if 0 03017 /* FIXME: VFAT SUCKS */ 03018 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; 03019 #endif 03020 03021 /* Perform the call */ 03022 return IopPerformSynchronousRequest(DeviceObject, 03023 Irp, 03024 FileObject, 03025 TRUE, 03026 PreviousMode, 03027 Synchronous, 03028 IopWriteTransfer); 03029 } 03030 03031 NTSTATUS 03032 NTAPI 03033 NtWriteFileGather(IN HANDLE FileHandle, 03034 IN HANDLE Event OPTIONAL, 03035 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, 03036 IN PVOID UserApcContext OPTIONAL, 03037 OUT PIO_STATUS_BLOCK UserIoStatusBlock, 03038 IN FILE_SEGMENT_ELEMENT BufferDescription [], 03039 IN ULONG BufferLength, 03040 IN PLARGE_INTEGER ByteOffset, 03041 IN PULONG Key OPTIONAL) 03042 { 03043 UNIMPLEMENTED; 03044 return STATUS_NOT_IMPLEMENTED; 03045 } 03046 03047 /* 03048 * @implemented 03049 */ 03050 NTSTATUS 03051 NTAPI 03052 NtQueryVolumeInformationFile(IN HANDLE FileHandle, 03053 OUT PIO_STATUS_BLOCK IoStatusBlock, 03054 OUT PVOID FsInformation, 03055 IN ULONG Length, 03056 IN FS_INFORMATION_CLASS FsInformationClass) 03057 { 03058 PFILE_OBJECT FileObject; 03059 PIRP Irp; 03060 PIO_STACK_LOCATION StackPtr; 03061 PDEVICE_OBJECT DeviceObject; 03062 PKEVENT Event = NULL; 03063 BOOLEAN LocalEvent = FALSE; 03064 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 03065 NTSTATUS Status; 03066 IO_STATUS_BLOCK KernelIosb; 03067 PAGED_CODE(); 03068 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 03069 03070 /* Check if we're called from user mode */ 03071 if (PreviousMode != KernelMode) 03072 { 03073 /* Validate the information class */ 03074 if ((FsInformationClass >= FileFsMaximumInformation) || 03075 !(IopQueryFsOperationLength[FsInformationClass])) 03076 { 03077 /* Invalid class */ 03078 return STATUS_INVALID_INFO_CLASS; 03079 } 03080 03081 /* Validate the length */ 03082 if (Length < IopQueryFsOperationLength[FsInformationClass]) 03083 { 03084 /* Invalid length */ 03085 return STATUS_INFO_LENGTH_MISMATCH; 03086 } 03087 03088 /* Enter SEH for probing */ 03089 _SEH2_TRY 03090 { 03091 /* Probe the I/O Status block */ 03092 ProbeForWriteIoStatusBlock(IoStatusBlock); 03093 03094 /* Probe the information */ 03095 ProbeForWrite(FsInformation, Length, sizeof(ULONG)); 03096 } 03097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03098 { 03099 /* Return the exception code */ 03100 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03101 } 03102 _SEH2_END; 03103 } 03104 03105 /* Get File Object */ 03106 Status = ObReferenceObjectByHandle(FileHandle, 03107 IopQueryFsOperationAccess 03108 [FsInformationClass], 03109 IoFileObjectType, 03110 PreviousMode, 03111 (PVOID*)&FileObject, 03112 NULL); 03113 if (!NT_SUCCESS(Status)) return Status; 03114 03115 /* Check if we should use Sync IO or not */ 03116 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 03117 { 03118 /* Lock it */ 03119 IopLockFileObject(FileObject); 03120 } 03121 else 03122 { 03123 /* Use local event */ 03124 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 03125 if (!Event) 03126 { 03127 ObDereferenceObject(FileObject); 03128 return STATUS_INSUFFICIENT_RESOURCES; 03129 } 03130 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 03131 LocalEvent = TRUE; 03132 } 03133 03134 /* Get the device object */ 03135 DeviceObject = IoGetRelatedDeviceObject(FileObject); 03136 03137 /* Clear File Object event */ 03138 KeClearEvent(&FileObject->Event); 03139 03140 /* Allocate the IRP */ 03141 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 03142 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); 03143 03144 /* Set up the IRP */ 03145 Irp->RequestorMode = PreviousMode; 03146 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 03147 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 03148 Irp->UserEvent = (LocalEvent) ? Event : NULL; 03149 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 03150 Irp->Tail.Overlay.OriginalFileObject = FileObject; 03151 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 03152 Irp->UserBuffer = FsInformation; 03153 Irp->AssociatedIrp.SystemBuffer = NULL; 03154 Irp->MdlAddress = NULL; 03155 03156 /* Set up Stack Data */ 03157 StackPtr = IoGetNextIrpStackLocation(Irp); 03158 StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; 03159 StackPtr->FileObject = FileObject; 03160 03161 /* Enter SEH */ 03162 _SEH2_TRY 03163 { 03164 /* Allocate a buffer */ 03165 Irp->AssociatedIrp.SystemBuffer = 03166 ExAllocatePoolWithTag(NonPagedPool, 03167 Length, 03168 TAG_SYSB); 03169 } 03170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03171 { 03172 /* Allocating failed, clean up and return the exception code */ 03173 IopCleanupAfterException(FileObject, Irp, NULL, Event); 03174 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03175 } 03176 _SEH2_END; 03177 03178 /* Set the flags for this buffered + deferred I/O */ 03179 Irp->Flags |= (IRP_BUFFERED_IO | 03180 IRP_DEALLOCATE_BUFFER | 03181 IRP_INPUT_OPERATION | 03182 IRP_DEFER_IO_COMPLETION); 03183 03184 /* Set Parameters */ 03185 StackPtr->Parameters.QueryVolume.Length = Length; 03186 StackPtr->Parameters.QueryVolume.FsInformationClass = FsInformationClass; 03187 03188 /* Call the Driver */ 03189 Status = IopPerformSynchronousRequest(DeviceObject, 03190 Irp, 03191 FileObject, 03192 TRUE, 03193 PreviousMode, 03194 !LocalEvent, 03195 IopOtherTransfer); 03196 03197 /* Check if this was async I/O */ 03198 if (LocalEvent) 03199 { 03200 /* It was, finalize this request */ 03201 Status = IopFinalizeAsynchronousIo(Status, 03202 Event, 03203 Irp, 03204 PreviousMode, 03205 &KernelIosb, 03206 IoStatusBlock); 03207 } 03208 03209 /* Return status */ 03210 return Status; 03211 } 03212 03213 /* 03214 * @implemented 03215 */ 03216 NTSTATUS 03217 NTAPI 03218 NtSetVolumeInformationFile(IN HANDLE FileHandle, 03219 OUT PIO_STATUS_BLOCK IoStatusBlock, 03220 IN PVOID FsInformation, 03221 IN ULONG Length, 03222 IN FS_INFORMATION_CLASS FsInformationClass) 03223 { 03224 PFILE_OBJECT FileObject; 03225 PIRP Irp; 03226 PIO_STACK_LOCATION StackPtr; 03227 PDEVICE_OBJECT DeviceObject, TargetDeviceObject; 03228 PKEVENT Event = NULL; 03229 BOOLEAN LocalEvent = FALSE; 03230 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 03231 NTSTATUS Status; 03232 IO_STATUS_BLOCK KernelIosb; 03233 TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure; 03234 PAGED_CODE(); 03235 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 03236 03237 /* Check if we're called from user mode */ 03238 if (PreviousMode != KernelMode) 03239 { 03240 /* Validate the information class */ 03241 if ((FsInformationClass >= FileFsMaximumInformation) || 03242 !(IopSetFsOperationLength[FsInformationClass])) 03243 { 03244 /* Invalid class */ 03245 return STATUS_INVALID_INFO_CLASS; 03246 } 03247 03248 /* Validate the length */ 03249 if (Length < IopSetFsOperationLength[FsInformationClass]) 03250 { 03251 /* Invalid length */ 03252 return STATUS_INFO_LENGTH_MISMATCH; 03253 } 03254 03255 /* Enter SEH for probing */ 03256 _SEH2_TRY 03257 { 03258 /* Probe the I/O Status block */ 03259 ProbeForWriteIoStatusBlock(IoStatusBlock); 03260 03261 /* Probe the information */ 03262 ProbeForRead(FsInformation, Length, sizeof(ULONG)); 03263 } 03264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03265 { 03266 /* Return the exception code */ 03267 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03268 } 03269 _SEH2_END; 03270 } 03271 03272 /* Get File Object */ 03273 Status = ObReferenceObjectByHandle(FileHandle, 03274 IopSetFsOperationAccess 03275 [FsInformationClass], 03276 IoFileObjectType, 03277 PreviousMode, 03278 (PVOID*)&FileObject, 03279 NULL); 03280 if (!NT_SUCCESS(Status)) return Status; 03281 03282 /* Get target device for notification */ 03283 Status = IoGetRelatedTargetDevice(FileObject, &TargetDeviceObject); 03284 if (!NT_SUCCESS(Status)) TargetDeviceObject = NULL; 03285 03286 /* Check if we should use Sync IO or not */ 03287 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 03288 { 03289 /* Lock it */ 03290 IopLockFileObject(FileObject); 03291 } 03292 else 03293 { 03294 /* Use local event */ 03295 Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); 03296 if (!Event) 03297 { 03298 ObDereferenceObject(FileObject); 03299 if (TargetDeviceObject) ObDereferenceObject(TargetDeviceObject); 03300 return STATUS_INSUFFICIENT_RESOURCES; 03301 } 03302 KeInitializeEvent(Event, SynchronizationEvent, FALSE); 03303 LocalEvent = TRUE; 03304 } 03305 03306 /* Get the device object */ 03307 DeviceObject = IoGetRelatedDeviceObject(FileObject); 03308 03309 /* Clear File Object event */ 03310 KeClearEvent(&FileObject->Event); 03311 03312 /* Allocate the IRP */ 03313 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 03314 if (!Irp) 03315 { 03316 if (TargetDeviceObject) ObDereferenceObject(TargetDeviceObject); 03317 return IopCleanupFailedIrp(FileObject, NULL, Event); 03318 } 03319 03320 /* Set up the IRP */ 03321 Irp->RequestorMode = PreviousMode; 03322 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 03323 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; 03324 Irp->UserEvent = (LocalEvent) ? Event : NULL; 03325 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 03326 Irp->Tail.Overlay.OriginalFileObject = FileObject; 03327 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 03328 Irp->UserBuffer = FsInformation; 03329 Irp->AssociatedIrp.SystemBuffer = NULL; 03330 Irp->MdlAddress = NULL; 03331 03332 /* Set up Stack Data */ 03333 StackPtr = IoGetNextIrpStackLocation(Irp); 03334 StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION; 03335 StackPtr->FileObject = FileObject; 03336 03337 /* Enter SEH */ 03338 _SEH2_TRY 03339 { 03340 /* Allocate a buffer */ 03341 Irp->AssociatedIrp.SystemBuffer = 03342 ExAllocatePoolWithTag(NonPagedPool, 03343 Length, 03344 TAG_SYSB); 03345 03346 /* Copy the data into it */ 03347 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, FsInformation, Length); 03348 } 03349 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 03350 { 03351 /* Allocating failed, clean up and return the exception code */ 03352 IopCleanupAfterException(FileObject, Irp, NULL, Event); 03353 if (TargetDeviceObject) ObDereferenceObject(TargetDeviceObject); 03354 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 03355 } 03356 _SEH2_END; 03357 03358 /* Set the flags for this buffered + deferred I/O */ 03359 Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); 03360 03361 /* Set Parameters */ 03362 StackPtr->Parameters.SetVolume.Length = Length; 03363 StackPtr->Parameters.SetVolume.FsInformationClass = FsInformationClass; 03364 03365 /* Call the Driver */ 03366 Status = IopPerformSynchronousRequest(DeviceObject, 03367 Irp, 03368 FileObject, 03369 FALSE, 03370 PreviousMode, 03371 !LocalEvent, 03372 IopOtherTransfer); 03373 03374 /* Check if this was async I/O */ 03375 if (LocalEvent) 03376 { 03377 /* It was, finalize this request */ 03378 Status = IopFinalizeAsynchronousIo(Status, 03379 Event, 03380 Irp, 03381 PreviousMode, 03382 &KernelIosb, 03383 IoStatusBlock); 03384 } 03385 03386 if (TargetDeviceObject && NT_SUCCESS(Status)) 03387 { 03388 /* Time to report change */ 03389 NotificationStructure.Version = 1; 03390 NotificationStructure.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION); 03391 NotificationStructure.Event = GUID_IO_VOLUME_NAME_CHANGE; 03392 NotificationStructure.FileObject = NULL; 03393 NotificationStructure.NameBufferOffset = - 1; 03394 Status = IoReportTargetDeviceChange(TargetDeviceObject, &NotificationStructure); 03395 } 03396 03397 /* Return status */ 03398 return Status; 03399 } 03400 03401 /* 03402 * @unimplemented 03403 */ 03404 NTSTATUS 03405 NTAPI 03406 NtCancelDeviceWakeupRequest(IN HANDLE DeviceHandle) 03407 { 03408 UNIMPLEMENTED; 03409 return STATUS_NOT_IMPLEMENTED; 03410 } 03411 03412 /* 03413 * @unimplemented 03414 */ 03415 NTSTATUS 03416 NTAPI 03417 NtRequestDeviceWakeup(IN HANDLE DeviceHandle) 03418 { 03419 UNIMPLEMENTED; 03420 return STATUS_NOT_IMPLEMENTED; 03421 } Generated on Sat May 26 2012 04:36:09 for ReactOS by
1.7.6.1
|