Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrawfs.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/iomgr/rawfs.c 00005 * PURPOSE: Raw File System Driver 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* TYPES *******************************************************************/ 00016 00017 typedef struct _VCB 00018 { 00019 USHORT NodeTypeCode; 00020 USHORT NodeByteSize; 00021 PDEVICE_OBJECT TargetDeviceObject; 00022 PVPB Vpb; 00023 ULONG VcbState; 00024 KMUTEX Mutex; 00025 CLONG OpenCount; 00026 SHARE_ACCESS ShareAccess; 00027 ULONG BytesPerSector; 00028 LARGE_INTEGER SectorsOnDisk; 00029 } VCB, *PVCB; 00030 00031 typedef struct _VOLUME_DEVICE_OBJECT 00032 { 00033 DEVICE_OBJECT DeviceObject; 00034 VCB Vcb; 00035 } VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT; 00036 00037 /* GLOBALS *******************************************************************/ 00038 00039 PDEVICE_OBJECT RawDiskDeviceObject, RawCdromDeviceObject, RawTapeDeviceObject; 00040 00041 /* FUNCTIONS *****************************************************************/ 00042 00043 VOID 00044 NTAPI 00045 RawInitializeVcb(IN OUT PVCB Vcb, 00046 IN PDEVICE_OBJECT TargetDeviceObject, 00047 IN PVPB Vpb) 00048 { 00049 PAGED_CODE(); 00050 00051 /* Clear it */ 00052 RtlZeroMemory(Vcb, sizeof(VCB)); 00053 00054 /* Associate to system objects */ 00055 Vcb->TargetDeviceObject = TargetDeviceObject; 00056 Vcb->Vpb = Vpb; 00057 00058 /* Initialize the lock */ 00059 KeInitializeMutex(&Vcb->Mutex, 0); 00060 } 00061 00062 BOOLEAN 00063 NTAPI 00064 RawCheckForDismount(IN PVCB Vcb, 00065 IN BOOLEAN CreateOperation) 00066 { 00067 KIRQL OldIrql; 00068 PVPB Vpb; 00069 BOOLEAN Delete; 00070 00071 /* Lock VPB */ 00072 IoAcquireVpbSpinLock(&OldIrql); 00073 00074 /* Reference it and check if a create is being done */ 00075 Vpb = Vcb->Vpb; 00076 if (Vcb->Vpb->ReferenceCount != CreateOperation) 00077 { 00078 /* Don't do anything */ 00079 Delete = FALSE; 00080 } 00081 else 00082 { 00083 /* Otherwise, delete the volume */ 00084 Delete = TRUE; 00085 00086 /* Check if it has a VPB and unmount it */ 00087 if (Vpb->RealDevice->Vpb == Vpb) 00088 { 00089 Vpb->DeviceObject = NULL; 00090 Vpb->Flags &= ~VPB_MOUNTED; 00091 } 00092 } 00093 00094 /* Release lock and return status */ 00095 IoReleaseVpbSpinLock(OldIrql); 00096 return Delete; 00097 } 00098 00099 NTSTATUS 00100 NTAPI 00101 RawCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, 00102 IN PIRP Irp, 00103 IN PVOID Context) 00104 { 00105 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 00106 00107 /* Check if this was a valid sync R/W request */ 00108 if (((IoStackLocation->MajorFunction == IRP_MJ_READ) || 00109 (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) && 00110 ((IoStackLocation->FileObject)) && 00111 (FlagOn(IoStackLocation->FileObject->Flags, FO_SYNCHRONOUS_IO)) && 00112 (NT_SUCCESS(Irp->IoStatus.Status))) 00113 { 00114 /* Update byte offset */ 00115 IoStackLocation->FileObject->CurrentByteOffset.QuadPart += 00116 Irp->IoStatus.Information; 00117 } 00118 00119 /* Mark the IRP Pending if it was */ 00120 if (Irp->PendingReturned) IoMarkIrpPending(Irp); 00121 return STATUS_SUCCESS; 00122 } 00123 00124 NTSTATUS 00125 NTAPI 00126 RawClose(IN PVCB Vcb, 00127 IN PIRP Irp, 00128 IN PIO_STACK_LOCATION IoStackLocation) 00129 { 00130 NTSTATUS Status; 00131 BOOLEAN Deleted = FALSE; 00132 PAGED_CODE(); 00133 00134 /* Make sure we can clean up */ 00135 Status = KeWaitForSingleObject(&Vcb->Mutex, 00136 Executive, 00137 KernelMode, 00138 FALSE, 00139 NULL); 00140 ASSERT(NT_SUCCESS(Status)); 00141 00142 /* Decrease the open count and check if this is a dismount */ 00143 Vcb->OpenCount--; 00144 if (!Vcb->OpenCount) Deleted = RawCheckForDismount(Vcb, FALSE); 00145 00146 /* Check if we should delete the device */ 00147 KeReleaseMutex(&Vcb->Mutex, FALSE); 00148 if (Deleted) 00149 { 00150 /* Delete it */ 00151 IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb, 00152 VOLUME_DEVICE_OBJECT, 00153 Vcb)); 00154 } 00155 00156 /* Complete the request */ 00157 Irp->IoStatus.Status = STATUS_SUCCESS; 00158 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00159 return STATUS_SUCCESS; 00160 } 00161 00162 NTSTATUS 00163 NTAPI 00164 RawCreate(IN PVCB Vcb, 00165 IN PIRP Irp, 00166 IN PIO_STACK_LOCATION IoStackLocation) 00167 { 00168 NTSTATUS Status; 00169 BOOLEAN Deleted = FALSE; 00170 USHORT ShareAccess; 00171 ACCESS_MASK DesiredAccess; 00172 PAGED_CODE(); 00173 00174 /* Make sure we can clean up */ 00175 Status = KeWaitForSingleObject(&Vcb->Mutex, 00176 Executive, 00177 KernelMode, 00178 FALSE, 00179 NULL); 00180 ASSERT(NT_SUCCESS(Status)); 00181 00182 /* Check if this is a valid non-directory file open */ 00183 if ((!(IoStackLocation->FileObject) || 00184 !(IoStackLocation->FileObject->FileName.Length)) && 00185 ((IoStackLocation->Parameters.Create.Options >> 24) == FILE_OPEN) && 00186 (!(IoStackLocation->Parameters.Create.Options & FILE_DIRECTORY_FILE))) 00187 { 00188 /* Make sure the VCB isn't locked */ 00189 if (Vcb->VcbState & 1) 00190 { 00191 /* Refuse the operation */ 00192 Status = STATUS_ACCESS_DENIED; 00193 Irp->IoStatus.Information = 0; 00194 } 00195 else 00196 { 00197 /* Setup share access */ 00198 ShareAccess = IoStackLocation->Parameters.Create.ShareAccess; 00199 DesiredAccess = IoStackLocation->Parameters.Create. 00200 SecurityContext->DesiredAccess; 00201 00202 /* Check if this VCB was already opened */ 00203 if (Vcb->OpenCount > 0) 00204 { 00205 /* Try to see if we have access to it */ 00206 Status = IoCheckShareAccess(DesiredAccess, 00207 ShareAccess, 00208 IoStackLocation->FileObject, 00209 &Vcb->ShareAccess, 00210 TRUE); 00211 if (!NT_SUCCESS(Status)) Irp->IoStatus.Information = 0; 00212 } 00213 00214 /* Make sure we have access */ 00215 if (NT_SUCCESS(Status)) 00216 { 00217 /* Check if this is the first open */ 00218 if (!Vcb->OpenCount) 00219 { 00220 /* Set the share access */ 00221 IoSetShareAccess(DesiredAccess, 00222 ShareAccess, 00223 IoStackLocation->FileObject, 00224 &Vcb->ShareAccess); 00225 } 00226 00227 /* Increase the open count and set the VPB */ 00228 Vcb->OpenCount += 1; 00229 IoStackLocation->FileObject->Vpb = Vcb->Vpb; 00230 00231 /* Set IRP status and disable intermediate buffering */ 00232 Status = STATUS_SUCCESS; 00233 Irp->IoStatus.Information = FILE_OPENED; 00234 IoStackLocation->FileObject->Flags |= 00235 FO_NO_INTERMEDIATE_BUFFERING; 00236 } 00237 } 00238 } 00239 else 00240 { 00241 /* Invalid create request */ 00242 Status = STATUS_INVALID_PARAMETER; 00243 Irp->IoStatus.Information = 0; 00244 } 00245 00246 /* Check if the request failed */ 00247 if (!(NT_SUCCESS(Status)) && !(Vcb->OpenCount)) 00248 { 00249 /* Check if we can dismount the device */ 00250 Deleted = RawCheckForDismount(Vcb, FALSE); 00251 } 00252 00253 /* Check if we should delete the device */ 00254 KeReleaseMutex(&Vcb->Mutex, FALSE); 00255 if (Deleted) 00256 { 00257 /* Delete it */ 00258 IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb, 00259 VOLUME_DEVICE_OBJECT, 00260 Vcb)); 00261 } 00262 00263 /* Complete the request */ 00264 Irp->IoStatus.Status = STATUS_SUCCESS; 00265 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00266 return STATUS_SUCCESS; 00267 } 00268 00269 NTSTATUS 00270 NTAPI 00271 RawReadWriteDeviceControl(IN PVCB Vcb, 00272 IN PIRP Irp, 00273 IN PIO_STACK_LOCATION IoStackLocation) 00274 { 00275 NTSTATUS Status; 00276 PAGED_CODE(); 00277 00278 /* Don't do anything if the request was 0 bytes */ 00279 if (((IoStackLocation->MajorFunction == IRP_MJ_READ) || 00280 (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) && 00281 !(IoStackLocation->Parameters.Read.Length)) 00282 { 00283 /* Complete it */ 00284 Irp->IoStatus.Status = STATUS_SUCCESS; 00285 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00286 return STATUS_SUCCESS; 00287 } 00288 00289 /* Copy the IRP stack location */ 00290 IoCopyCurrentIrpStackLocationToNext(Irp); 00291 00292 /* Disable verifies */ 00293 IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 00294 00295 /* Setup a completion routine */ 00296 IoSetCompletionRoutine(Irp, 00297 RawCompletionRoutine, 00298 NULL, 00299 TRUE, 00300 TRUE, 00301 TRUE); 00302 00303 /* Call the next driver and exit */ 00304 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); 00305 return Status; 00306 } 00307 00308 NTSTATUS 00309 NTAPI 00310 RawMountVolume(IN PIO_STACK_LOCATION IoStackLocation) 00311 { 00312 NTSTATUS Status; 00313 PDEVICE_OBJECT DeviceObject; 00314 PVOLUME_DEVICE_OBJECT Volume; 00315 PFILE_OBJECT FileObject = NULL; 00316 PAGED_CODE(); 00317 00318 /* Remember our owner */ 00319 DeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject; 00320 00321 /* Create the volume */ 00322 Status = IoCreateDevice(RawDiskDeviceObject->DriverObject, 00323 sizeof(VOLUME_DEVICE_OBJECT) - 00324 sizeof(DEVICE_OBJECT), 00325 NULL, 00326 FILE_DEVICE_DISK_FILE_SYSTEM, 00327 0, 00328 FALSE, 00329 (PDEVICE_OBJECT*)&Volume); 00330 if (!NT_SUCCESS(Status)) return Status; 00331 00332 /* Use highest alignment requirement */ 00333 Volume->DeviceObject.AlignmentRequirement = max(DeviceObject-> 00334 AlignmentRequirement, 00335 Volume->DeviceObject. 00336 AlignmentRequirement); 00337 00338 /* Setup the VCB */ 00339 RawInitializeVcb(&Volume->Vcb, 00340 IoStackLocation->Parameters.MountVolume.DeviceObject, 00341 IoStackLocation->Parameters.MountVolume.Vpb); 00342 00343 /* Set dummy label and serial number */ 00344 Volume->Vcb.Vpb->SerialNumber = 0xFFFFFFFF; 00345 Volume->Vcb.Vpb->VolumeLabelLength = 0; 00346 00347 /* Setup the DO */ 00348 Volume->Vcb.Vpb->DeviceObject = &Volume->DeviceObject; 00349 Volume->DeviceObject.StackSize = DeviceObject->StackSize + 1; 00350 Volume->DeviceObject.SectorSize = DeviceObject->SectorSize; 00351 Volume->DeviceObject.Flags |= DO_DIRECT_IO; 00352 Volume->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING; 00353 00354 /* Try to get associated FO (for notification) */ 00355 _SEH2_TRY 00356 { 00357 FileObject = IoCreateStreamFileObjectLite(NULL, 00358 &(Volume->DeviceObject)); 00359 } 00360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00361 { 00362 /* Get the exception code */ 00363 Status = _SEH2_GetExceptionCode(); 00364 } 00365 _SEH2_END; 00366 00367 /* If failed, delete devive */ 00368 if (!NT_SUCCESS(Status)) 00369 { 00370 IoDeleteDevice((PDEVICE_OBJECT)Volume); 00371 return Status; 00372 } 00373 00374 /* Increment OpenCount by two to avoid dismount when RawClose() will be called on ObDereferenceObject() */ 00375 Volume->Vcb.OpenCount += 2; 00376 /* Notify for sucessful mount */ 00377 FsRtlNotifyVolumeEvent(FileObject, FSRTL_VOLUME_MOUNT); 00378 /* Decrease refcount to 0 to make FileObject being released */ 00379 ObDereferenceObject(FileObject); 00380 /* It's not open anymore, go back to 0 */ 00381 Volume->Vcb.OpenCount -= 2; 00382 00383 return Status; 00384 } 00385 00386 NTSTATUS 00387 NTAPI 00388 RawUserFsCtrl(IN PIO_STACK_LOCATION IoStackLocation, 00389 IN PVCB Vcb) 00390 { 00391 NTSTATUS Status; 00392 PAGED_CODE(); 00393 00394 /* Lock the device */ 00395 Status = KeWaitForSingleObject(&Vcb->Mutex, 00396 Executive, 00397 KernelMode, 00398 FALSE, 00399 NULL); 00400 ASSERT(NT_SUCCESS(Status)); 00401 00402 /* Check what kind of request this is */ 00403 switch (IoStackLocation->Parameters.FileSystemControl.FsControlCode) 00404 { 00405 /* Oplock requests */ 00406 case FSCTL_REQUEST_OPLOCK_LEVEL_1: 00407 case FSCTL_REQUEST_OPLOCK_LEVEL_2: 00408 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: 00409 case FSCTL_OPLOCK_BREAK_NOTIFY: 00410 00411 /* We don't handle them */ 00412 Status = STATUS_NOT_IMPLEMENTED; 00413 break; 00414 00415 /* Lock request */ 00416 case FSCTL_LOCK_VOLUME: 00417 00418 /* Make sure we're not locked, and that we're alone */ 00419 if (!(Vcb->VcbState & 1) && (Vcb->OpenCount == 1)) 00420 { 00421 /* Lock the VCB */ 00422 Vcb->VcbState |= 1; 00423 Status = STATUS_SUCCESS; 00424 } 00425 else 00426 { 00427 /* Otherwise, we can't do this */ 00428 Status = STATUS_ACCESS_DENIED; 00429 } 00430 break; 00431 00432 /* Unlock request */ 00433 case FSCTL_UNLOCK_VOLUME: 00434 00435 /* Make sure we're locked */ 00436 if (!(Vcb->VcbState & 1)) 00437 { 00438 /* Let caller know we're not */ 00439 Status = STATUS_NOT_LOCKED; 00440 } 00441 else 00442 { 00443 /* Unlock the VCB */ 00444 Vcb->VcbState &= ~1; 00445 Status = STATUS_SUCCESS; 00446 } 00447 break; 00448 00449 /* Dismount request */ 00450 case FSCTL_DISMOUNT_VOLUME: 00451 00452 /* Make sure we're locked */ 00453 if (Vcb->VcbState & 1) 00454 { 00455 /* Do nothing, just return success */ 00456 Status = STATUS_SUCCESS; 00457 } 00458 else 00459 { 00460 /* We can't dismount, device not locked */ 00461 Status = STATUS_ACCESS_DENIED; 00462 } 00463 break; 00464 00465 /* Unknown request */ 00466 default: 00467 00468 /* Fail */ 00469 Status = STATUS_INVALID_PARAMETER; 00470 break; 00471 } 00472 00473 /* Unlock device */ 00474 KeReleaseMutex(&Vcb->Mutex, FALSE); 00475 00476 /* In case of status change, notify */ 00477 switch (IoStackLocation->Parameters.FileSystemControl.FsControlCode) 00478 { 00479 case FSCTL_LOCK_VOLUME: 00480 FsRtlNotifyVolumeEvent(IoStackLocation->FileObject, (NT_SUCCESS(Status) ? FSRTL_VOLUME_LOCK : FSRTL_VOLUME_LOCK_FAILED)); 00481 break; 00482 case FSCTL_UNLOCK_VOLUME: 00483 if (NT_SUCCESS(Status)) 00484 { 00485 FsRtlNotifyVolumeEvent(IoStackLocation->FileObject, FSRTL_VOLUME_UNLOCK); 00486 } 00487 break; 00488 case FSCTL_DISMOUNT_VOLUME: 00489 FsRtlNotifyVolumeEvent(IoStackLocation->FileObject, (NT_SUCCESS(Status) ? FSRTL_VOLUME_DISMOUNT : FSRTL_VOLUME_DISMOUNT_FAILED)); 00490 break; 00491 } 00492 00493 return Status; 00494 } 00495 00496 NTSTATUS 00497 NTAPI 00498 RawFileSystemControl(IN PVCB Vcb, 00499 IN PIRP Irp, 00500 IN PIO_STACK_LOCATION IoStackLocation) 00501 { 00502 NTSTATUS Status; 00503 PAGED_CODE(); 00504 00505 /* Check the kinds of FSCTLs that we support */ 00506 switch (IoStackLocation->MinorFunction) 00507 { 00508 /* User-mode request */ 00509 case IRP_MN_USER_FS_REQUEST: 00510 00511 /* Handle it */ 00512 Status = RawUserFsCtrl(IoStackLocation, Vcb); 00513 break; 00514 00515 /* Mount request */ 00516 case IRP_MN_MOUNT_VOLUME: 00517 00518 /* Mount the volume */ 00519 Status = RawMountVolume(IoStackLocation); 00520 break; 00521 00522 case IRP_MN_VERIFY_VOLUME: 00523 00524 /* We don't do verifies */ 00525 Status = STATUS_WRONG_VOLUME; 00526 Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME; 00527 00528 /* Check if we should delete the device */ 00529 if (RawCheckForDismount(Vcb, FALSE)) 00530 { 00531 /* Do it */ 00532 IoDeleteDevice((PDEVICE_OBJECT) 00533 CONTAINING_RECORD(Vcb, 00534 VOLUME_DEVICE_OBJECT, 00535 Vcb)); 00536 } 00537 00538 /* We're done */ 00539 break; 00540 00541 /* Invalid request */ 00542 default: 00543 00544 /* Fail it */ 00545 Status = STATUS_INVALID_DEVICE_REQUEST; 00546 break; 00547 } 00548 00549 /* Complete the request */ 00550 Irp->IoStatus.Status = Status; 00551 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00552 return Status; 00553 } 00554 00555 NTSTATUS 00556 NTAPI 00557 RawQueryInformation(IN PVCB Vcb, 00558 IN PIRP Irp, 00559 IN PIO_STACK_LOCATION IoStackLocation) 00560 { 00561 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; 00562 PULONG Length; 00563 PFILE_POSITION_INFORMATION Buffer; 00564 PAGED_CODE(); 00565 00566 /* Get information from the IRP */ 00567 Length = &IoStackLocation->Parameters.QueryFile.Length; 00568 Buffer = Irp->AssociatedIrp.SystemBuffer; 00569 00570 /* We only handle this request */ 00571 if (IoStackLocation->Parameters.QueryFile.FileInformationClass == 00572 FilePositionInformation) 00573 { 00574 /* Validate buffer size */ 00575 if (*Length < sizeof(FILE_POSITION_INFORMATION)) 00576 { 00577 /* Invalid, fail */ 00578 Irp->IoStatus.Information = 0; 00579 Status = STATUS_BUFFER_OVERFLOW; 00580 } 00581 else 00582 { 00583 /* Get offset and update length */ 00584 Buffer->CurrentByteOffset = IoStackLocation->FileObject-> 00585 CurrentByteOffset; 00586 *Length -= sizeof(FILE_POSITION_INFORMATION); 00587 00588 /* Set IRP Status information */ 00589 Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION); 00590 Status = STATUS_SUCCESS; 00591 } 00592 } 00593 00594 /* Complete it */ 00595 Irp->IoStatus.Status = Status; 00596 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00597 return Status; 00598 } 00599 00600 NTSTATUS 00601 NTAPI 00602 RawSetInformation(IN PVCB Vcb, 00603 IN PIRP Irp, 00604 IN PIO_STACK_LOCATION IoStackLocation) 00605 { 00606 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; 00607 PFILE_POSITION_INFORMATION Buffer; 00608 PDEVICE_OBJECT DeviceObject; 00609 PAGED_CODE(); 00610 00611 /* Get information from the IRP */ 00612 Buffer = Irp->AssociatedIrp.SystemBuffer; 00613 00614 /* We only handle this request */ 00615 if (IoStackLocation->Parameters.QueryFile.FileInformationClass == 00616 FilePositionInformation) 00617 { 00618 /* Get the DO */ 00619 DeviceObject = IoGetRelatedDeviceObject(IoStackLocation->FileObject); 00620 00621 /* Make sure the offset is aligned */ 00622 if ((Buffer->CurrentByteOffset.LowPart & 00623 DeviceObject->AlignmentRequirement)) 00624 { 00625 /* It's not, fail */ 00626 Status = STATUS_INVALID_PARAMETER; 00627 } 00628 else 00629 { 00630 /* Otherwise, set offset */ 00631 IoStackLocation->FileObject->CurrentByteOffset = Buffer-> 00632 CurrentByteOffset; 00633 00634 /* Set IRP Status information */ 00635 Status = STATUS_SUCCESS; 00636 } 00637 } 00638 00639 /* Complete it */ 00640 Irp->IoStatus.Status = Status; 00641 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00642 return Status; 00643 } 00644 00645 NTSTATUS 00646 NTAPI 00647 RawQueryFsVolumeInfo(IN PVCB Vcb, 00648 IN PFILE_FS_VOLUME_INFORMATION Buffer, 00649 IN OUT PULONG Length) 00650 { 00651 PAGED_CODE(); 00652 00653 /* Clear the buffer and stub it out */ 00654 RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION)); 00655 Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber; 00656 Buffer->SupportsObjects = FALSE; 00657 Buffer->VolumeLabelLength = 0; 00658 00659 /* Return length and success */ 00660 *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]); 00661 return STATUS_SUCCESS; 00662 } 00663 00664 NTSTATUS 00665 NTAPI 00666 RawQueryFsSizeInfo(IN PVCB Vcb, 00667 IN PFILE_FS_SIZE_INFORMATION Buffer, 00668 IN OUT PULONG Length) 00669 { 00670 PIRP Irp; 00671 KEVENT Event; 00672 NTSTATUS Status; 00673 IO_STATUS_BLOCK IoStatusBlock; 00674 PDEVICE_OBJECT RealDevice; 00675 DISK_GEOMETRY DiskGeometry; 00676 PARTITION_INFORMATION PartitionInformation; 00677 BOOLEAN DiskHasPartitions; 00678 PAGED_CODE(); 00679 00680 /* Validate the buffer */ 00681 if (*Length < sizeof(FILE_FS_SIZE_INFORMATION)) 00682 { 00683 /* Fail */ 00684 return STATUS_BUFFER_OVERFLOW; 00685 } 00686 00687 /* Clear the buffer, initialize the event and set the DO */ 00688 RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION)); 00689 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00690 RealDevice = Vcb->Vpb->RealDevice; 00691 00692 /* Build query IRP */ 00693 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 00694 RealDevice, 00695 NULL, 00696 0, 00697 &DiskGeometry, 00698 sizeof(DISK_GEOMETRY), 00699 FALSE, 00700 &Event, 00701 &IoStatusBlock); 00702 if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; 00703 00704 /* Call driver and check if we're pending */ 00705 Status = IoCallDriver(RealDevice, Irp); 00706 if (Status == STATUS_PENDING) 00707 { 00708 /* Wait on driver to finish */ 00709 KeWaitForSingleObject(&Event, 00710 Executive, 00711 KernelMode, 00712 FALSE, 00713 NULL); 00714 Status = IoStatusBlock.Status; 00715 } 00716 00717 /* Fail if we couldn't get CHS data */ 00718 if (!NT_SUCCESS(Status)) 00719 { 00720 *Length = 0; 00721 return Status; 00722 } 00723 00724 /* Check if this is a floppy */ 00725 if (FlagOn(RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) 00726 { 00727 /* Floppies don't have partitions */ 00728 DiskHasPartitions = FALSE; 00729 } 00730 else 00731 { 00732 /* Setup query IRP */ 00733 KeResetEvent(&Event); 00734 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, 00735 RealDevice, 00736 NULL, 00737 0, 00738 &PartitionInformation, 00739 sizeof(PARTITION_INFORMATION), 00740 FALSE, 00741 &Event, 00742 &IoStatusBlock); 00743 if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; 00744 00745 /* Call driver and check if we're pending */ 00746 Status = IoCallDriver(RealDevice, Irp); 00747 if (Status == STATUS_PENDING) 00748 { 00749 /* Wait on driver to finish */ 00750 KeWaitForSingleObject(&Event, 00751 Executive, 00752 KernelMode, 00753 FALSE, 00754 NULL); 00755 Status = IoStatusBlock.Status; 00756 } 00757 00758 /* If this was an invalid request, then the disk is not partitioned */ 00759 if (Status == STATUS_INVALID_DEVICE_REQUEST) 00760 { 00761 DiskHasPartitions = FALSE; 00762 } 00763 else 00764 { 00765 /* Otherwise, it must be */ 00766 ASSERT(NT_SUCCESS(Status)); 00767 DiskHasPartitions = TRUE; 00768 } 00769 } 00770 00771 /* Set sector data */ 00772 Buffer->BytesPerSector = DiskGeometry.BytesPerSector; 00773 Buffer->SectorsPerAllocationUnit = 1; 00774 00775 /* Calculate allocation units */ 00776 if (DiskHasPartitions) 00777 { 00778 /* Use partition data */ 00779 Buffer->TotalAllocationUnits = 00780 RtlExtendedLargeIntegerDivide(PartitionInformation.PartitionLength, 00781 DiskGeometry.BytesPerSector, 00782 NULL); 00783 } 00784 else 00785 { 00786 /* Use CHS */ 00787 Buffer->TotalAllocationUnits = 00788 RtlExtendedIntegerMultiply(DiskGeometry.Cylinders, 00789 DiskGeometry.TracksPerCylinder * 00790 DiskGeometry.SectorsPerTrack); 00791 } 00792 00793 /* Set available units */ 00794 Buffer->AvailableAllocationUnits = Buffer->TotalAllocationUnits; 00795 00796 /* Return length and success */ 00797 *Length -= sizeof(FILE_FS_SIZE_INFORMATION); 00798 return STATUS_SUCCESS; 00799 } 00800 00801 NTSTATUS 00802 NTAPI 00803 RawQueryFsDeviceInfo(IN PVCB Vcb, 00804 IN PFILE_FS_DEVICE_INFORMATION Buffer, 00805 IN OUT PULONG Length) 00806 { 00807 PAGED_CODE(); 00808 00809 /* Validate buffer */ 00810 if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION)) 00811 { 00812 /* Fail */ 00813 return STATUS_BUFFER_OVERFLOW; 00814 } 00815 00816 /* Clear buffer and write information */ 00817 RtlZeroMemory(Buffer, sizeof(FILE_FS_DEVICE_INFORMATION)); 00818 Buffer->DeviceType = FILE_DEVICE_DISK; 00819 Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics; 00820 00821 /* Return length and success */ 00822 *Length -= sizeof(FILE_FS_DEVICE_INFORMATION); 00823 return STATUS_SUCCESS; 00824 } 00825 00826 NTSTATUS 00827 NTAPI 00828 RawQueryFsAttributeInfo(IN PVCB Vcb, 00829 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer, 00830 IN OUT PULONG Length) 00831 { 00832 const WCHAR szRawFSName[] = L"RAW"; 00833 ULONG ReturnLength; 00834 PAGED_CODE(); 00835 00836 /* Check if the buffer is large enough for our name ("RAW") */ 00837 ReturnLength = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, 00838 FileSystemName[sizeof(szRawFSName) / sizeof(szRawFSName[0])]); 00839 if (*Length < ReturnLength) return STATUS_BUFFER_OVERFLOW; 00840 00841 /* Output the data */ 00842 Buffer->FileSystemAttributes = 0; 00843 Buffer->MaximumComponentNameLength = 0; 00844 Buffer->FileSystemNameLength = 6; 00845 RtlCopyMemory(&Buffer->FileSystemName[0], szRawFSName, sizeof(szRawFSName)); 00846 00847 /* Return length and success */ 00848 *Length -= ReturnLength; 00849 return STATUS_SUCCESS; 00850 } 00851 00852 NTSTATUS 00853 NTAPI 00854 RawQueryVolumeInformation(IN PVCB Vcb, 00855 IN PIRP Irp, 00856 IN PIO_STACK_LOCATION IoStackLocation) 00857 { 00858 NTSTATUS Status; 00859 ULONG Length; 00860 PVOID Buffer; 00861 PAGED_CODE(); 00862 00863 /* Get IRP Data */ 00864 Length = IoStackLocation->Parameters.QueryVolume.Length; 00865 Buffer = Irp->AssociatedIrp.SystemBuffer; 00866 00867 /* Check the kind of request */ 00868 switch (IoStackLocation->Parameters.QueryVolume.FsInformationClass) 00869 { 00870 /* Volume information request */ 00871 case FileFsVolumeInformation: 00872 00873 Status = RawQueryFsVolumeInfo(Vcb, Buffer, &Length); 00874 break; 00875 00876 /* File system size invormation */ 00877 case FileFsSizeInformation: 00878 00879 Status = RawQueryFsSizeInfo(Vcb, Buffer, &Length); 00880 break; 00881 00882 /* Device information */ 00883 case FileFsDeviceInformation: 00884 00885 Status = RawQueryFsDeviceInfo(Vcb, Buffer, &Length); 00886 break; 00887 00888 /* Attribute information */ 00889 case FileFsAttributeInformation: 00890 00891 Status = RawQueryFsAttributeInfo(Vcb, Buffer, &Length); 00892 break; 00893 00894 /* Invalid request */ 00895 default: 00896 00897 /* Fail it */ 00898 Status = STATUS_INVALID_PARAMETER; 00899 break; 00900 } 00901 00902 /* Set status and complete the request */ 00903 Irp->IoStatus.Information = IoStackLocation-> 00904 Parameters.QueryVolume.Length - Length; 00905 Irp->IoStatus.Status = Status; 00906 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00907 return Status; 00908 } 00909 00910 NTSTATUS 00911 NTAPI 00912 RawCleanup(IN PVCB Vcb, 00913 IN PIRP Irp, 00914 IN PIO_STACK_LOCATION IoStackLocation) 00915 { 00916 NTSTATUS Status; 00917 PAGED_CODE(); 00918 00919 /* Make sure we can clean up */ 00920 Status = KeWaitForSingleObject(&Vcb->Mutex, 00921 Executive, 00922 KernelMode, 00923 FALSE, 00924 NULL); 00925 ASSERT(NT_SUCCESS(Status)); 00926 00927 /* Remove shared access and complete the request */ 00928 IoRemoveShareAccess(IoStackLocation->FileObject, &Vcb->ShareAccess); 00929 KeReleaseMutex(&Vcb->Mutex, FALSE); 00930 Irp->IoStatus.Status = STATUS_SUCCESS; 00931 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00932 return STATUS_SUCCESS; 00933 } 00934 00935 NTSTATUS 00936 NTAPI 00937 RawDispatch(IN PVOLUME_DEVICE_OBJECT DeviceObject, 00938 IN PIRP Irp) 00939 { 00940 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; 00941 PIO_STACK_LOCATION IoStackLocation; 00942 PVCB Vcb; 00943 PAGED_CODE(); 00944 00945 /* Get the stack location */ 00946 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 00947 00948 /* Differentiate between Volume DO and FS DO */ 00949 if ((((PDEVICE_OBJECT)DeviceObject)->Size == sizeof(DEVICE_OBJECT)) && 00950 !((IoStackLocation->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && 00951 (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME))) 00952 { 00953 /* This is an FS DO. Stub out the common calls */ 00954 if ((IoStackLocation->MajorFunction == IRP_MJ_CREATE) || 00955 (IoStackLocation->MajorFunction == IRP_MJ_CLEANUP) || 00956 (IoStackLocation->MajorFunction == IRP_MJ_CLOSE)) 00957 { 00958 /* Return success for them */ 00959 Status = STATUS_SUCCESS; 00960 } 00961 else 00962 { 00963 /* Anything else, we don't support */ 00964 Status = STATUS_INVALID_DEVICE_REQUEST; 00965 } 00966 00967 /* Complete the request */ 00968 Irp->IoStatus.Status = Status; 00969 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00970 return Status; 00971 } 00972 00973 /* Otherwise, get our VCB and start handling the IRP */ 00974 FsRtlEnterFileSystem(); 00975 Vcb = &DeviceObject->Vcb; 00976 00977 /* Check what kind of IRP this is */ 00978 switch (IoStackLocation->MajorFunction) 00979 { 00980 /* Cleanup request */ 00981 case IRP_MJ_CLEANUP: 00982 00983 Status = RawCleanup(Vcb, Irp, IoStackLocation); 00984 break; 00985 00986 /* Close request */ 00987 case IRP_MJ_CLOSE: 00988 00989 Status = RawClose(Vcb, Irp, IoStackLocation); 00990 break; 00991 00992 /* Create request */ 00993 case IRP_MJ_CREATE: 00994 00995 Status = RawCreate(Vcb, Irp, IoStackLocation); 00996 break; 00997 00998 /* FSCTL request */ 00999 case IRP_MJ_FILE_SYSTEM_CONTROL: 01000 01001 Status = RawFileSystemControl(Vcb, Irp, IoStackLocation); 01002 break; 01003 01004 /* R/W or IOCTL request */ 01005 case IRP_MJ_READ: 01006 case IRP_MJ_WRITE: 01007 case IRP_MJ_DEVICE_CONTROL: 01008 01009 Status = RawReadWriteDeviceControl(Vcb, Irp, IoStackLocation); 01010 break; 01011 01012 /* Information query request */ 01013 case IRP_MJ_QUERY_INFORMATION: 01014 01015 Status = RawQueryInformation(Vcb, Irp, IoStackLocation); 01016 break; 01017 01018 /* Information set request */ 01019 case IRP_MJ_SET_INFORMATION: 01020 01021 Status = RawSetInformation(Vcb, Irp, IoStackLocation); 01022 break; 01023 01024 /* Volume information request */ 01025 case IRP_MJ_QUERY_VOLUME_INFORMATION: 01026 01027 Status = RawQueryVolumeInformation(Vcb, Irp, IoStackLocation); 01028 break; 01029 01030 /* Unexpected request */ 01031 default: 01032 01033 /* Anything else is pretty bad */ 01034 KeBugCheck(FILE_SYSTEM); 01035 } 01036 01037 /* Return the status */ 01038 FsRtlExitFileSystem(); 01039 return Status; 01040 } 01041 01042 NTSTATUS 01043 NTAPI 01044 RawShutdown(IN PDEVICE_OBJECT DeviceObject, 01045 IN PIRP Irp) 01046 { 01047 /* Unregister file systems */ 01048 #if 0 // FIXME: This freezes ROS at shutdown. PnP Problem? 01049 IoUnregisterFileSystem(RawDiskDeviceObject); 01050 IoUnregisterFileSystem(RawCdromDeviceObject); 01051 IoUnregisterFileSystem(RawTapeDeviceObject); 01052 01053 /* Delete the devices */ 01054 IoDeleteDevice(RawDiskDeviceObject); 01055 IoDeleteDevice(RawCdromDeviceObject); 01056 IoDeleteDevice(RawTapeDeviceObject); 01057 #endif 01058 01059 /* Complete the request */ 01060 Irp->IoStatus.Status = STATUS_SUCCESS; 01061 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 01062 return STATUS_SUCCESS; 01063 } 01064 01065 VOID 01066 NTAPI 01067 RawUnload(IN PDRIVER_OBJECT DriverObject) 01068 { 01069 #if 0 // FIXME: DriverUnload is never called 01070 /* Dereference device objects */ 01071 ObDereferenceObject(RawDiskDeviceObject); 01072 ObDereferenceObject(RawCdromDeviceObject); 01073 ObDereferenceObject(RawTapeDeviceObject); 01074 #endif 01075 } 01076 01077 NTSTATUS 01078 NTAPI 01079 INIT_FUNCTION 01080 RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject, 01081 IN PUNICODE_STRING RegistryPath) 01082 { 01083 UNICODE_STRING DeviceName; 01084 NTSTATUS Status; 01085 01086 /* Create the raw disk device */ 01087 RtlInitUnicodeString(&DeviceName, L"\\Device\\RawDisk"); 01088 Status = IoCreateDevice(DriverObject, 01089 0, 01090 NULL, 01091 FILE_DEVICE_DISK_FILE_SYSTEM, 01092 0, 01093 FALSE, 01094 &RawDiskDeviceObject); 01095 if (!NT_SUCCESS(Status)) return Status; 01096 01097 /* Create the raw CDROM device */ 01098 RtlInitUnicodeString(&DeviceName, L"\\Device\\RawCdRom"); 01099 Status = IoCreateDevice(DriverObject, 01100 0, 01101 NULL, 01102 FILE_DEVICE_CD_ROM_FILE_SYSTEM, 01103 0, 01104 FALSE, 01105 &RawCdromDeviceObject); 01106 if (!NT_SUCCESS(Status)) return Status; 01107 01108 /* Create the raw tape device */ 01109 RtlInitUnicodeString(&DeviceName, L"\\Device\\RawTape"); 01110 Status = IoCreateDevice(DriverObject, 01111 0, 01112 NULL, 01113 FILE_DEVICE_TAPE_FILE_SYSTEM, 01114 0, 01115 FALSE, 01116 &RawTapeDeviceObject); 01117 if (!NT_SUCCESS(Status)) return Status; 01118 01119 /* Set Direct I/O for all devices */ 01120 RawDiskDeviceObject->Flags |= DO_DIRECT_IO; 01121 RawCdromDeviceObject->Flags |= DO_DIRECT_IO; 01122 RawTapeDeviceObject->Flags |= DO_DIRECT_IO; 01123 01124 /* Set generic stubs */ 01125 DriverObject->MajorFunction[IRP_MJ_CREATE] = 01126 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = 01127 DriverObject->MajorFunction[IRP_MJ_CLOSE] = 01128 DriverObject->MajorFunction[IRP_MJ_READ] = 01129 DriverObject->MajorFunction[IRP_MJ_WRITE] = 01130 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = 01131 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = 01132 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = 01133 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = 01134 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)RawDispatch; 01135 01136 /* Shutdown and unload */ 01137 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = RawShutdown; 01138 DriverObject->DriverUnload = RawUnload; 01139 01140 /* Register the file systems */ 01141 IoRegisterFileSystem(RawDiskDeviceObject); 01142 IoRegisterFileSystem(RawCdromDeviceObject); 01143 IoRegisterFileSystem(RawTapeDeviceObject); 01144 01145 #if 0 // FIXME: DriverUnload is never called 01146 /* Reference device objects */ 01147 ObReferenceObject(RawDiskDeviceObject); 01148 ObReferenceObject(RawCdromDeviceObject); 01149 ObReferenceObject(RawTapeDeviceObject); 01150 #endif 01151 return STATUS_SUCCESS; 01152 } 01153 01154 /* EOF */ Generated on Sat May 26 2012 04:36:10 for ReactOS by
1.7.6.1
|