static BT_HANDLE fullfat_mount(BT_HANDLE hFS, BT_HANDLE hVolume, BT_ERROR *pError) { FF_ERROR ffError; BT_ERROR Error = BT_ERR_GENERIC; BT_FF_MOUNT *pMount = (BT_FF_MOUNT *) BT_CreateHandle(&oHandleInterface, sizeof(BT_FF_MOUNT), pError); if(!pMount) { return NULL; } pMount->pBlockCache = BT_kMalloc(8192); pMount->hVolume = hVolume; pMount->pIoman = FF_CreateIOMAN(pMount->pBlockCache, 8192, 512, &ffError); if(!pMount->pIoman) { Error = BT_ERR_GENERIC; goto err_free_out; } ffError = FF_RegisterBlkDevice(pMount->pIoman, 512, fullfat_writeblocks, fullfat_readblocks, pMount); ffError = FF_MountPartition(pMount->pIoman, 0); return (BT_HANDLE) pMount; err_free_out: BT_kFree(pMount->pBlockCache); BT_DestroyHandle((BT_HANDLE)pMount); *pError = Error; return NULL; }
/** * @public * @brief Mounts and Image with FullFAT. * * **/ DLL_EXPORT int FFC_MountImage(char *szFilename, unsigned long ulBlockSize, unsigned long ulPartitionNumber) { FF_ERROR Error = FF_ERR_NONE; if(g_pIoman || g_hDisk) { return FFD_ERR_IMAGE_ALREADY_MOUNTED; } g_hDisk = fnOpen(szFilename, ulBlockSize); if(!g_hDisk) { return FFD_ERR_COULD_NOT_OPEN_IMAGE; } g_pIoman = FF_CreateIOMAN(NULL, 8192, GetBlockSize(g_hDisk), &Error); // Using the BlockSize from the Device Driver (see blkdev_win32.c) if(!g_pIoman) { return FFD_ERR_COULD_NOT_INITIALISE_FULLFAT; } else { Error = FF_RegisterBlkDevice(g_pIoman, GetBlockSize(g_hDisk), (FF_WRITE_BLOCKS) fnWrite, (FF_READ_BLOCKS) fnRead, g_hDisk); if(Error) { printError(Error); FF_DestroyIOMAN(g_pIoman); fnClose(g_hDisk); return -1; } // Attempt to mount! Error = FF_MountPartition(g_pIoman, (FF_T_UINT8) ulPartitionNumber); if(Error) { if(g_hDisk) { fnClose(g_hDisk); } FF_DestroyIOMAN(g_pIoman); g_pIoman = NULL; return -1; } g_Env.pIoman = g_pIoman; strcpy(g_Env.WorkingDir, "\\"); // Reset working dir! } return FFD_ERR_NONE; }
NTSTATUS NTAPI FatMountVolume(PFAT_IRP_CONTEXT IrpContext, PDEVICE_OBJECT TargetDeviceObject, PVPB Vpb, PDEVICE_OBJECT FsDeviceObject) { NTSTATUS Status; DISK_GEOMETRY DiskGeometry; ULONG MediaChangeCount = 0; PVOLUME_DEVICE_OBJECT VolumeDevice; VCB *Vcb; FF_ERROR Error; PBCB BootBcb; PPACKED_BOOT_SECTOR BootSector; DPRINT1("FatMountVolume()\n"); /* Make sure this IRP is waitable */ ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT); /* Request media changes count, mostly useful for removable devices */ Status = FatPerformDevIoCtrl(TargetDeviceObject, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &MediaChangeCount, sizeof(ULONG), TRUE); if (!NT_SUCCESS(Status)) return Status; /* TODO: Check if data-track present in case of a CD drive */ /* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */ /* Remove unmounted VCBs */ FatiCleanVcbs(IrpContext); /* Acquire the global exclusive lock */ FatAcquireExclusiveGlobal(IrpContext); /* Create a new volume device object */ Status = IoCreateDevice(FatGlobalData.DriverObject, sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, (PDEVICE_OBJECT *)&VolumeDevice); if (!NT_SUCCESS(Status)) { /* Release the global lock */ FatReleaseGlobal(IrpContext); return Status; } /* Match alignment requirements */ if (TargetDeviceObject->AlignmentRequirement > VolumeDevice->DeviceObject.AlignmentRequirement) { VolumeDevice->DeviceObject.AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } /* Init stack size */ VolumeDevice->DeviceObject.StackSize = TargetDeviceObject->StackSize + 1; /* Get sector size */ Status = FatPerformDevIoCtrl(TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, sizeof(DISK_GEOMETRY), TRUE); if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup; VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector; /* Signal we're done with initializing */ VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING; /* Save device object in a VPB */ Vpb->DeviceObject = (PDEVICE_OBJECT)VolumeDevice; /* Initialize VCB for this volume */ Status = FatInitializeVcb(IrpContext, &VolumeDevice->Vcb, TargetDeviceObject, Vpb); if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup; Vcb = &VolumeDevice->Vcb; /* Initialize FullFAT library */ Vcb->Ioman = FF_CreateIOMAN(NULL, 8192, VolumeDevice->DeviceObject.SectorSize, &Error); ASSERT(Vcb->Ioman); /* Register block device read/write functions */ Error = FF_RegisterBlkDevice(Vcb->Ioman, VolumeDevice->DeviceObject.SectorSize, (FF_WRITE_BLOCKS)FatWriteBlocks, (FF_READ_BLOCKS)FatReadBlocks, Vcb); if (Error) { DPRINT1("Registering block device with FullFAT failed with error %d\n", Error); FF_DestroyIOMAN(Vcb->Ioman); goto FatMountVolumeCleanup; } /* Mount the volume using FullFAT */ if(FF_MountPartition(Vcb->Ioman, 0)) { DPRINT1("Partition mounting failed\n"); FF_DestroyIOMAN(Vcb->Ioman); goto FatMountVolumeCleanup; } /* Read the boot sector */ FatReadStreamFile(Vcb, 0, sizeof(PACKED_BOOT_SECTOR), &BootBcb, (PVOID)&BootSector); /* Check if it's successful */ if (!BootBcb) { Status = STATUS_UNRECOGNIZED_VOLUME; goto FatMountVolumeCleanup; } /* Unpack data */ FatiUnpackBpb(&Vcb->Bpb, &BootSector->PackedBpb); /* Verify if sector size matches */ if (DiskGeometry.BytesPerSector != Vcb->Bpb.BytesPerSector) { DPRINT1("Disk geometry BPS %d and bios BPS %d don't match!\n", DiskGeometry.BytesPerSector, Vcb->Bpb.BytesPerSector); /* Fail */ Status = STATUS_UNRECOGNIZED_VOLUME; goto FatMountVolumeCleanup; } /* If Sectors value is set, discard the LargeSectors value */ if (Vcb->Bpb.Sectors) Vcb->Bpb.LargeSectors = 0; /* Copy serial number */ if (FatiBpbFat32(&BootSector->PackedBpb)) { CopyUchar4(&Vpb->SerialNumber, ((PPACKED_BOOT_SECTOR_EX)BootSector)->Id); } else { /* This is FAT12/16 */ CopyUchar4(&Vpb->SerialNumber, BootSector->Id); } /* Unpin the BCB */ CcUnpinData(BootBcb); /* Create root DCB for it */ FatCreateRootDcb(IrpContext, &VolumeDevice->Vcb); /* Keep trace of media changes */ VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount; //ObDereferenceObject(TargetDeviceObject); /* Release the global lock */ FatReleaseGlobal(IrpContext); /* Notify about volume mount */ //FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT); /* Return success */ return STATUS_SUCCESS; FatMountVolumeCleanup: /* Unwind the routine actions */ IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice); /* Release the global lock */ FatReleaseGlobal(IrpContext); return Status; }