helper.cpp
来自「WinCE5.0部分核心源码」· C++ 代码 · 共 1,836 行 · 第 1/5 页
CPP
1,836 行
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include <windows.h>
#include <diskio.h>
#include <partdrv.h>
#include "part.h"
#include "bpb.h"
#include "bootsec.h"
#include "drvdbg.h"
#ifndef UNDER_CE
#include <stddef.h>
#endif // UNDER_CE
/*****************************************************************************
* ClearPartitionList - frees all existing partition structures
*
* Input: state - structure for this store
*
* Output: state - updated to remove all references to PartState structures
* and associated partition information
*
* Return: none
*
*****************************************************************************/
void ClearPartitionList(DriverState *state)
{
PartState * pNextPartState;
PartState * pPartState;
pNextPartState = state->pPartState;
// deallocate the list of partition structures
while (pNextPartState)
{
pPartState = pNextPartState;
pNextPartState = pPartState->pNextPartState;
LocalFree(pPartState);
}
state->pPartState = NULL;
state->pHiddenPartState = NULL;
state->snExtPartSector = 0;
state->snExtPartEndSec = 0;
state->dwNumParts = 0;
}
/*****************************************************************************
* CalculatePartitionSpace - calculates the amount of free space on the store
* and the largest contiguous section available for a partition.
*
* Input: state - structure for this store
*
* Output: pFreeSpace - available space on the store
* pLargestPart - largest partition that can be created
*
* Return: none
*
*****************************************************************************/
BOOL CalculatePartitionSpace(DriverState *state, SECTORNUM *pFreeSpace, SECTORNUM *pLargestPart)
{
PartState *pPartState;
SECTORNUM snLastPart;
SECTORNUM snFreeSpace;
PBYTE buffer = NULL;
PPARTENTRY tmpbuffer, tmpbuffer1;
int i;
BOOL bResult;
*pLargestPart = (SECTORNUM)0;
*pFreeSpace = (SECTORNUM)0;
// first see if there's room in the extended partition
if (state->snExtPartSector)
{
snLastPart = state->snExtPartSector;
pPartState = state->pPartState;
// find the first partition within the extended partition
for (;pPartState != NULL; pPartState = pPartState->pNextPartState)
{
if (pPartState->snPBRSector == 0)
continue;
break;
}
if (pPartState)
{
while (pPartState)
{
// only traverse the partitions within the extended partition
if (pPartState->snPBRSector == 0)
break;
snFreeSpace = pPartState->snPBRSector - snLastPart;
*pFreeSpace += snFreeSpace;
// add the overhead for an extended partition before calculating the available size for a partition
if (snFreeSpace)
{
if (state->diskInfo.di_heads > 1)
snFreeSpace -= state->diskInfo.di_sectors;
else
snFreeSpace--;
}
if (snFreeSpace > *pLargestPart)
*pLargestPart = snFreeSpace;
snLastPart = pPartState->snStartSector + pPartState->snNumSectors;
pPartState = pPartState->pNextPartState;
}
// add in any of the extended partition that's not used
if (state->snExtPartEndSec > snLastPart) {
snFreeSpace = state->snExtPartEndSec - snLastPart +1;
*pFreeSpace += snFreeSpace;
}
// add the overhead for an extended partition before calculating the available size for a partition
if (snFreeSpace)
{
if ((state->diskInfo.di_heads > 1) && (snFreeSpace >= state->diskInfo.di_sectors))
snFreeSpace -= state->diskInfo.di_sectors;
else
snFreeSpace--;
}
if (snFreeSpace > *pLargestPart)
*pLargestPart = snFreeSpace;
}
else
{
// the hidden partition is empty
*pFreeSpace = state->snExtPartEndSec - state->snExtPartSector +1;
if (state->diskInfo.di_heads > 1)
*pLargestPart = *pFreeSpace - state->diskInfo.di_sectors;
else
*pLargestPart = *pFreeSpace - 1;
}
}
// now check for room in the main partition table
buffer = NULL;
bResult = ReadSectors (state, 0, 1, &buffer);
if (!bResult)
return FALSE;
tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET);
tmpbuffer1 = (PPARTENTRY)(buffer + PARTTABLE_OFFSET + sizeof(PARTENTRY));
// the MBR is full can't add anything outside of the extended partition anyway
if (tmpbuffer[3].Part_TotalSectors)
{
LocalFree(buffer);
return TRUE;
}
// check for a gap at the beginning of the table
if (tmpbuffer->Part_FirstTrack > 1)
{
if (state->diskInfo.di_heads > 1)
{
// adjust for the reserved MBR track
snFreeSpace = tmpbuffer->Part_StartSector - state->diskInfo.di_sectors;
// adjust in case the partition doesn't start at head 0
snFreeSpace -= tmpbuffer->Part_FirstHead * state->diskInfo.di_sectors;
}
else
snFreeSpace = tmpbuffer->Part_StartSector - 1;
*pFreeSpace += snFreeSpace;
if (snFreeSpace > *pLargestPart)
*pLargestPart = snFreeSpace;
}
for (i=0; i<4; i++, tmpbuffer++, tmpbuffer1++)
{
if (tmpbuffer->Part_TotalSectors == 0) {
// If we are to create primary partitions, the store is formatted, but does not
// yet have a partition defined, then the largest available partition is all the
// space on the store minus the MBR or reserved sectors for track alignment.
if ((state->dwFlags & MSPART_CREATE_PRIMARY) && i == 0 && state->bFormatState)
{
if (state->diskInfo.di_heads > 1)
*pLargestPart = *pFreeSpace = state->diskInfo.di_total_sectors - state->diskInfo.di_sectors;
else
*pLargestPart = *pFreeSpace = state->diskInfo.di_total_sectors - 1;
}
break;
}
// calculate the space between two partitions
if (tmpbuffer->Part_TotalSectors && tmpbuffer1->Part_TotalSectors)
snFreeSpace = tmpbuffer1->Part_StartSector - (tmpbuffer->Part_StartSector + tmpbuffer->Part_TotalSectors);
else if (state->diskInfo.di_total_sectors > (tmpbuffer->Part_StartSector + tmpbuffer->Part_TotalSectors))
// calculate space from the last partition to the end of the drive
snFreeSpace = state->diskInfo.di_total_sectors - (tmpbuffer->Part_StartSector + tmpbuffer->Part_TotalSectors);
else
snFreeSpace = 0;
*pFreeSpace += snFreeSpace;
if (snFreeSpace > *pLargestPart)
*pLargestPart = snFreeSpace;
}
LocalFree(buffer);
return TRUE;
}
/*****************************************************************************
* GenerateFATFSType - generates a FATxx partition type based upon the size
* of the partition. This algorithm is a duplicate of the code found in
* FATFS.
*
* Input: state - structure for this store
* snNumSectors - size of the partition
* pFileSys - pointer to the partition type
*
* Output: pFileSys is updated with the partition type
*
* Return: none
*
*****************************************************************************/
void GenerateFATFSType(DriverState *state, SECTORNUM snNumSectors, PBYTE pFileSys)
{
// TODO: Verify that we support the LBA modes correctly
DWORD dwSectorCount;
DWORD dwBytesPerSector;
int cLoops;
DWORD csecReserved, csecClus;
DWORD csecFATs, csecFATsLast;
DWORD csecRoot, csecData, cclusData;
DWORD cRootEntries, cbitsClus;
dwBytesPerSector = state->diskInfo.di_bytes_per_sect;
dwSectorCount = (DWORD)snNumSectors;
// assumptions for FAT layout
csecClus = 1;
cRootEntries = 256;
csecReserved = 1;
// this algorithm was lifted out of format.c in the fatfs code - we need to generate partition types
// the same way FATFS does
restart:
do
{
cLoops = 4;
csecFATs = csecRoot = 0;
do
{
csecData = dwSectorCount - csecReserved - csecFATs - csecRoot;
do
{
cclusData = csecData / csecClus;
if (csecClus > (DWORD)(MAX_CLUS_SIZE/dwBytesPerSector)) {
dwSectorCount = (FAT32_BAD-1)*(MAX_CLUS_SIZE/dwBytesPerSector);
goto restart;
}
if (cclusData < FAT1216_THRESHOLD)
{
cbitsClus = 12; // Should use a 12-bit FAT
break;
}
if (cclusData < FAT1632_THRESHOLD)
{
cbitsClus = 16; // Should use a 16-bit FAT
break;
}
// So, at the current cluster size, a 32-bit FAT is the only answer;
// however, we won't settle on that as long as the cluster size is still small
// (less than 4K).
if (csecClus < (DWORD)(4096/dwBytesPerSector))
{
csecClus *= 2; // grow the cluster size
}
else
{
cbitsClus = 32;
csecReserved = 2; // why only 2? see "minimalist" comments below...
break;
}
} while (TRUE);
// NOTE: when computing csecFATs, we must add DATA_CLUSTER (2) to cclusData, because
// the first two entries in a FAT aren't real entries, but we must still account for them.
csecFATsLast = csecFATs;
csecFATs = (((cclusData+DATA_CLUSTER) * cbitsClus + 7)/8 + dwBytesPerSector-1) / dwBytesPerSector;
if (cbitsClus == 32) // csecRoot comes into play only on non-FAT32 volumes
csecRoot = 0;
else
csecRoot = (sizeof(DIRENTRY) * cRootEntries + dwBytesPerSector-1) / dwBytesPerSector;
} while (csecFATs != csecFATsLast && --cLoops);
if (cLoops)
break;
// We couldn't get a consistent answer, so chop off one cluster
dwSectorCount -= csecClus;
} while (TRUE);
if (cbitsClus == 12)
*pFileSys = PART_DOS2_FAT;
else if (cbitsClus == 32)
*pFileSys = PART_DOS32;
else if (dwSectorCount < 65536)
*pFileSys = PART_DOS3_FAT;
else
*pFileSys = PART_DOS4_FAT;
}
/*****************************************************************************
* GeneratePartitionChecksum - generates the checksum for the OnDiskPartState
* structures contained in the buffer. The number of partitions to checksum
* is contained within the buffer as well as the existing checksum.
*
* Input: state - structure for this store
* buffer - pointer to the buffer containing the partition data
* pChecksum - pointer to the checksum
*
* Output: pChecksum is updated with the new checksum
*
*
* Return: TRUE if the checksum agrees with the on media checksum, FALSE if not
*
*****************************************************************************/
BOOL GeneratePartitionChecksum(DriverState *state, PBYTE buffer, DWORD *pChecksum)
{
DWORD dwChecksum = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?