예제 #1
0
/**
 * @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;
}
예제 #2
0
파일: ff_ioman.c 프로젝트: BigEd/pyldin
/**
 *	@public
 *	@brief	Creates an FF_IOMAN object, to initialise FullFAT
 *
 *	@param	pCacheMem		Pointer to a buffer for the cache. (NULL if ok to Malloc).
 *	@param	Size			The size of the provided buffer, or size of the cache to be created. (Must be atleast 2 * BlkSize). Always a multiple of BlkSize.
 *	@param	BlkSize			The block size of devices to be attached. If in doubt use 512.
 *	@param	pError			Pointer to a signed byte for error checking. Can be NULL if not required.
 *	@param	pError			To be checked when a NULL pointer is returned.
 *
 *	@return	Returns a pointer to an FF_IOMAN type object. NULL on Error, check the contents of
 *	@return pError
 **/
FF_IOMAN *FF_CreateIOMAN(FF_T_UINT8 *pCacheMem, FF_T_UINT32 Size, FF_T_UINT16 BlkSize, FF_ERROR *pError) {

	FF_IOMAN	*pIoman = NULL;
	FF_T_UINT32 *pLong	= NULL;	// Force malloc to malloc memory on a 32-bit boundary.
#ifdef FF_PATH_CACHE
	FF_T_UINT32	i;
#endif

	if(pError) {
		*pError = FF_ERR_NONE;
	}

	if((BlkSize % 512) != 0 || BlkSize == 0) {
		if(pError) {
			*pError = FF_ERR_IOMAN_BAD_BLKSIZE | FF_CREATEIOMAN;
		}
		return NULL;	// BlkSize Size not a multiple of 512 > 0
	}

	if((Size % BlkSize) != 0 || Size == 0 || Size == BlkSize) {  // Size must now be atleast 2 * BlkSize (or a deadlock will occur).
		if(pError) {
			*pError = FF_ERR_IOMAN_BAD_MEMSIZE | FF_CREATEIOMAN;
		}
		return NULL;	// Memory Size not a multiple of BlkSize > 0
	}

	pIoman = (FF_IOMAN *) FF_MALLOC(sizeof(FF_IOMAN));

	if(!pIoman) {		// Ensure malloc() succeeded.
		if(pError) {
			*pError = FF_ERR_NOT_ENOUGH_MEMORY | FF_CREATEIOMAN;
		}
		return NULL;
	}

	memset (pIoman, '\0', sizeof(FF_IOMAN));

	// This is just a bit-mask, to use a byte to keep track of memory.
	// pIoman->MemAllocation = 0x00;	// Unset all allocation identifiers.
	pIoman->pPartition	= (FF_PARTITION  *) FF_MALLOC(sizeof(FF_PARTITION));
	if(!pIoman->pPartition) {
		if(pError) {
			*pError = FF_ERR_NOT_ENOUGH_MEMORY | FF_CREATEIOMAN;
		}
		FF_DestroyIOMAN(pIoman);
		return NULL;
	}
	memset (pIoman->pPartition, '\0', sizeof(FF_PARTITION));

	pIoman->MemAllocation |= FF_IOMAN_ALLOC_PART;	// If succeeded, flag that allocation.
	pIoman->pPartition->LastFreeCluster = 0;
	pIoman->pPartition->PartitionMounted = FF_FALSE;	// This should be checked by FF_Open();
#ifdef FF_PATH_CACHE
	pIoman->pPartition->PCIndex = 0;
	for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) {
		pIoman->pPartition->PathCache[i].DirCluster = 0;
		pIoman->pPartition->PathCache[i].Path[0] = '\0';
/*#ifdef FF_HASH_TABLE_SUPPORT
		pIoman->pPartition->PathCache[i].pHashTable = FF_CreateHashTable();
		pIoman->pPartition->PathCache[i].bHashed = FF_FALSE;
#endif*/
	}
#endif

#ifdef FF_HASH_CACHE
	for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
		pIoman->HashCache[i].pHashTable 	= FF_CreateHashTable();
		pIoman->HashCache[i].ulDirCluster 	= 0;
		pIoman->HashCache[i].ulMisses		= 100;
	}
#endif

	pIoman->pBlkDevice	= (FF_BLK_DEVICE *) FF_MALLOC(sizeof(FF_BLK_DEVICE));
	if(!pIoman->pBlkDevice) {	// If succeeded, flag that allocation.
		if(pError) {
			*pError = FF_ERR_NOT_ENOUGH_MEMORY | FF_CREATEIOMAN;
		}
		FF_DestroyIOMAN(pIoman);
		return NULL;
	}
	memset (pIoman->pBlkDevice, '\0', sizeof(FF_BLK_DEVICE));
	pIoman->MemAllocation |= FF_IOMAN_ALLOC_BLKDEV;

	// Make sure all pointers are NULL
	pIoman->pBlkDevice->fnpReadBlocks = NULL;
	pIoman->pBlkDevice->fnpWriteBlocks = NULL;
	pIoman->pBlkDevice->pParam = NULL;

	// Organise the memory provided, or create our own!
	if(pCacheMem) {
		pIoman->pCacheMem = pCacheMem;
	}else {	// No-Cache buffer provided (malloc)
		pLong = (FF_T_UINT32 *) FF_MALLOC(Size);
		pIoman->pCacheMem = (FF_T_UINT8 *) pLong;
		if(!pIoman->pCacheMem) {
			if(pError) {
				*pError = FF_ERR_NOT_ENOUGH_MEMORY | FF_CREATEIOMAN;
			}
			FF_DestroyIOMAN(pIoman);
			return NULL;
		}
		pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFFERS;

	}
	memset (pIoman->pCacheMem, '\0', Size);

	pIoman->BlkSize		 = BlkSize;
	pIoman->CacheSize	 = (FF_T_UINT16) (Size / BlkSize);
	pIoman->FirstFile	 = NULL;
	pIoman->Locks		 = 0;

	/*	Malloc() memory for buffer objects. (FullFAT never refers to a buffer directly
		but uses buffer objects instead. Allows us to provide thread safety.
	*/
	pIoman->pBuffers = (FF_BUFFER *) FF_MALLOC(sizeof(FF_BUFFER) * pIoman->CacheSize);

	if(!pIoman->pBuffers) {
		if(pError) {
			*pError = FF_ERR_NOT_ENOUGH_MEMORY | FF_CREATEIOMAN;
		}
		FF_DestroyIOMAN(pIoman);
		return NULL;	// HT added
	}
	memset (pIoman->pBuffers, '\0', sizeof(FF_BUFFER) * pIoman->CacheSize);

	pIoman->MemAllocation |= FF_IOMAN_ALLOC_BUFDESCR;
	FF_IOMAN_InitBufferDescriptors(pIoman);

	// Finally create a Semaphore for Buffer Description modifications.
	pIoman->pSemaphore = FF_CreateSemaphore();

#ifdef FF_BLKDEV_USES_SEM
	pIoman->pBlkDevSemaphore = FF_CreateSemaphore();
#endif

	return pIoman;	// Sucess, return the created object.
}
예제 #3
0
파일: fsctl.c 프로젝트: hoangduit/reactos
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;
}