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 + -
显示快捷键?