/** * @brief Opens a HANDLE to a Windows Blockdevice or File. * **/ HANDLE fnOpen(char *strDevName, int nBlockSize) { struct _DEV_INFO *ptDevInfo; DISK_GEOMETRY_EX DiskGeo; LARGE_INTEGER li, address; BOOL IOError; DWORD BytesReturned; HANDLE hDisk; WCHAR pWide[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, strDevName, -1, pWide, MAX_PATH); hDisk = CreateFile(pWide, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL); IOError = GetLastError(); if(hDisk != INVALID_HANDLE_VALUE) { // Dismount volume (allow Vista and Seven write access!) IOError = DeviceIoControl(hDisk, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL); // if(IOError) { // Continue on error! This may be an image file! ptDevInfo = (struct _DEV_INFO *) malloc(sizeof(struct _DEV_INFO)); if(GetDriveGeometry(&DiskGeo, hDisk)) { ptDevInfo->BlockSize = DiskGeo.Geometry.BytesPerSector; ptDevInfo->DiskSize = DiskGeo.DiskSize.QuadPart; ptDevInfo->hDev = hDisk; ptDevInfo->AccessSem = FF_CreateSemaphore(); return (HANDLE) ptDevInfo; } else { GetFileSizeEx(hDisk, &li); address.QuadPart = 0; if(!nBlockSize) { ptDevInfo->BlockSize = 512; // Try to assume the most likely setting! } else { ptDevInfo->BlockSize = nBlockSize; } ptDevInfo->DiskSize = li.QuadPart; ptDevInfo->hDev = hDisk; ptDevInfo->AccessSem = FF_CreateSemaphore(); return (HANDLE) ptDevInfo; } //} } return (HANDLE) NULL; }
HANDLE fnOpen(char *strDevName, int nBlockSize) { struct _DEV_INFO *ptDevInfo; DISK_GEOMETRY_EX DiskGeo; LARGE_INTEGER li, address; HANDLE hDisk; hDisk = CreateFile(strDevName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL); if(hDisk) { ptDevInfo = (struct _DEV_INFO *) malloc(sizeof(struct _DEV_INFO)); if(GetDriveGeometry(&DiskGeo, hDisk)) { ptDevInfo->BlockSize = DiskGeo.Geometry.BytesPerSector; ptDevInfo->DiskSize = DiskGeo.DiskSize.QuadPart; ptDevInfo->hDev = hDisk; ptDevInfo->AccessSem = FF_CreateSemaphore(); return (HANDLE) ptDevInfo; } else { //GetFileSizeEx(hDisk, &li); address.QuadPart = 0; if(!nBlockSize) { ptDevInfo->BlockSize = 512; } else { ptDevInfo->BlockSize = nBlockSize; } ptDevInfo->DiskSize = li.QuadPart; ptDevInfo->hDev = hDisk; ptDevInfo->AccessSem = FF_CreateSemaphore(); return (HANDLE) ptDevInfo; } } return (HANDLE) NULL; }
BLK_DEV_LINUX fnOpen(char *szDeviceName, int nBlockSize) { BLK_DEV_LINUX ptDevInfo; FILE *pDevice; pDevice = fopen(szDeviceName, "rb+"); if(pDevice) { ptDevInfo = (struct _DEV_INFO *) malloc(sizeof(struct _DEV_INFO)); if(ptDevInfo) { ptDevInfo->BlockSize = nBlockSize; //ptDevInfo->DiskSize ptDevInfo->pDevice = pDevice; ptDevInfo->AccessSem = FF_CreateSemaphore(); return (BLK_DEV_LINUX) ptDevInfo; } } return NULL; }
/** * @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. }