ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rawfs.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.