helper.cpp

来自「WinCE5.0部分核心源码」· C++ 代码 · 共 1,836 行 · 第 1/5 页

CPP
1,836
字号
    DWORD   *tmpbuffer;
    int     numEntries = 0;

    if (pChecksum)
        *pChecksum = 0;

    tmpbuffer = (DWORD *)(buffer + STORESTART);

    numEntries = ((DriverState *)tmpbuffer)->dwNumParts;

    if (!numEntries)
        return TRUE;

    // this is the max # of partitions we'll hold, if the count is larger, the sector is hosed
    if (numEntries > HIDDEN_PART_SEC_COUNT*3)
        return FALSE;

    numEntries *= sizeof(OnDiskPartState);

    // # DWORDS to checksum
    numEntries >>= 2;

    tmpbuffer = (DWORD *)(buffer + STORESTART + offsetof(DriverState, hDsk));

    // simple DWORD checksum - don't worry about overflow
    while (numEntries)
    {
        dwChecksum += tmpbuffer[numEntries];
        numEntries --;
    }
    
    if (pChecksum)
        *pChecksum = dwChecksum;

    tmpbuffer = (DWORD *)(buffer + STORESTART);

    if (((DriverState *)tmpbuffer)->dwChecksum == dwChecksum)
        return TRUE;
    else
        return FALSE;

}

/*****************************************************************************
 *  CreatePBR - creates a partition boot record within the extended partition
 *  and links it to the previous and next partition if they apply.
 *
 *  Input:  state - structure for this store
 *          snLastPBRSec - LBA of the PBR that points to this PBR
 *          snNextPBRSec - LBA of the PBR that this PBR will point to
 *          snPBRSector - LBA of this PBR
 *          snNumSectors - number of sectors for this partition
 *          fileSysType -  partition type of this partition
 *
 *  Output: none
 *
 *  Return: TRUE if PBR created successfully, FALSE if not
 *
 *****************************************************************************/
BOOL CreatePBR(DriverState *state, SECTORNUM snLastPBRSec, SECTORNUM snNextPBRSec, SECTORNUM snPBRSector, SECTORNUM snNumSectors, BYTE fileSysType)
{

    BOOL        bResult;
    PBYTE       buffer=NULL, buffer1=NULL;
    PPARTENTRY  tmpbuffer, tmpbuffer1;
    SECTORNUM   snDataStart;

    // the partition data starts at the next head location
    if (state->diskInfo.di_heads > 1)
        snDataStart = snPBRSector + state->diskInfo.di_sectors;
    else
        snDataStart = snPBRSector + 1;

    buffer = (PBYTE)LocalAlloc(LMEM_ZEROINIT, state->diskInfo.di_bytes_per_sect);
    if (!buffer)
        return FALSE;

    // set the trailer signature for the EBR
    *(WORD *)(buffer + BOOT_SIGNATURE) = BOOTSECTRAILSIGH;
    tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET);

    // build up the entry for the new PBR first
    bResult = ConvertLBAtoCHS (state, snDataStart, &tmpbuffer->Part_FirstTrack, &tmpbuffer->Part_FirstHead, &tmpbuffer->Part_FirstSector);
    bResult = ConvertLBAtoCHS (state, snPBRSector + snNumSectors -1, &tmpbuffer->Part_LastTrack, &tmpbuffer->Part_LastHead, &tmpbuffer->Part_LastSector);
    tmpbuffer->Part_FileSystem = fileSysType;

    // start sector of the data area is relative to the beginning of the logical drive
    if (state->diskInfo.di_heads > 1)
        tmpbuffer->Part_StartSector = state->diskInfo.di_sectors;
    else
        tmpbuffer->Part_StartSector = 1;

    // sector count does not include the PBR sector(s)
    tmpbuffer->Part_TotalSectors =(DWORD)snNumSectors - tmpbuffer->Part_StartSector;

    if (snNextPBRSec)
    {
        buffer1 = NULL;
        bResult = ReadSectors (state, snNextPBRSec, 1, &buffer1);
        if (!bResult)
        {
            LocalFree(buffer);
            return FALSE;
        }

        tmpbuffer1 = (PPARTENTRY)(buffer + PARTTABLE_OFFSET);

        // if we're hooking in between two logical drives, we need an entry in this PBR to point to the next one
        tmpbuffer++;

        // start sector of the data area is relative to the beginning of the logical drive
        tmpbuffer->Part_StartSector = (DWORD)(snNextPBRSec - state->snExtPartSector);

        // sector count comes from the length of the next logical drive
        tmpbuffer->Part_TotalSectors = tmpbuffer1->Part_StartSector + tmpbuffer1->Part_TotalSectors;

        bResult = ConvertLBAtoCHS (state, snNextPBRSec, &tmpbuffer->Part_FirstTrack, &tmpbuffer->Part_FirstHead, &tmpbuffer->Part_FirstSector);
        bResult = ConvertLBAtoCHS (state, snNextPBRSec + tmpbuffer->Part_TotalSectors -1, &tmpbuffer->Part_LastTrack, &tmpbuffer->Part_LastHead, &tmpbuffer->Part_LastSector);

        // the file system type for the next logical drive is always the extended partition type, not the actual FS type
        tmpbuffer->Part_FileSystem = PART_EXTENDED;

        LocalFree(buffer1);
    }

    bResult = WriteSectors(state, snPBRSector, 1, buffer);
    LocalFree(buffer);

    if (!bResult)
        return FALSE;

    // We have successfully written out the new PBR and (possibly) linked it to the next one in the chain
    // The last thing that needs to be done is hook this into the previous PBR if it exists

    if (!snLastPBRSec)
        return TRUE;

    buffer = NULL;
    bResult = ReadSectors (state, snLastPBRSec, 1, &buffer);
    if (!bResult)
        return FALSE;

    tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET + sizeof(PARTENTRY));

    bResult = ConvertLBAtoCHS (state, snPBRSector, &tmpbuffer->Part_FirstTrack, &tmpbuffer->Part_FirstHead, &tmpbuffer->Part_FirstSector);
    bResult = ConvertLBAtoCHS (state, snPBRSector + snNumSectors -1, &tmpbuffer->Part_LastTrack, &tmpbuffer->Part_LastHead, &tmpbuffer->Part_LastSector);
    tmpbuffer->Part_FileSystem = PART_EXTENDED;

    // start sector of the data area is relative to the beginning of the logical drive
    tmpbuffer->Part_StartSector = (DWORD)(snPBRSector - state->snExtPartSector);

    // sector count comes from the length of the next logical drive and includes the PBR track
    tmpbuffer->Part_TotalSectors = (DWORD)snNumSectors;

    bResult = WriteSectors(state, snLastPBRSec, 1, buffer);
    LocalFree(buffer);

    if (!bResult)
        return FALSE;

    return TRUE;

}

/*****************************************************************************
 *  Delete PBR - deletes the partition boot record for the partition and updates
 *  the previous PBR if one exists.
 *
 *  Input:  state - structure for this store
 *          pPartState - partition structure for the PBR to delete
 *          pPrevPartState - partition structure for the partition that preceeds
 *                           the partition being deleted
 *
 *  Output: none
 *
 *
 *  Return: TRUE if PBR successfully deleted, FALSE if not
 *
 *****************************************************************************/
BOOL DeletePBR(DriverState *state, PartState *pPartState, PartState *pPrevPartState)
{

    
    BOOL        bResult;
    PBYTE       buffer = NULL, buffer1 = NULL;
    PPARTENTRY  tmpbuffer, tmpbuffer1;

    // first get the PBR sector for the logical drive that's being deleted
    bResult = ReadSectors (state, pPartState->snPBRSector, 1, &buffer);
    if (!bResult)
    {
        LocalFree(buffer);
        return FALSE;
    }

    // if this logical drive follows another logical drive, the previous PBR needs to be updated
    if (pPrevPartState && pPrevPartState->snPBRSector)
    {
        buffer1 = NULL;
        bResult = ReadSectors (state, pPrevPartState->snPBRSector, 1, &buffer1);
        if (!bResult)
        {
            LocalFree(buffer);
            return FALSE;
        }

        // copy the partition entry that points to the next logical drive (from the PBR being deleted)
        //  and update the previous PBR to point to it
        tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET + sizeof(PARTENTRY));
        tmpbuffer1 = (PPARTENTRY)(buffer1 + PARTTABLE_OFFSET + sizeof(PARTENTRY));
        memcpy(tmpbuffer1, tmpbuffer, sizeof(PARTENTRY));

        // update the previous PBR - which removes the link to the part being deleted
        bResult = WriteSectors(state, pPrevPartState->snPBRSector, 1, buffer1);
        LocalFree(buffer1);

        if (!bResult)
        {
            LocalFree(buffer);
            return FALSE;
        }

        // zero out the old PBR so it isn't mistakenly used as a PBR anymore by some ill behaved code
        memset(buffer, 0, state->diskInfo.di_bytes_per_sect);
        bResult = WriteSectors(state, pPartState->snPBRSector, 1, buffer);

    }
    else
    {
        // this is the first logical drive in the extended partition - all that needs to be done is zero
        //  the entry for this logical drive, the pointer to the next logical drive remains in tact
        //  at part entry 2

        tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET);
        memset(tmpbuffer, 0, sizeof(PARTENTRY));

        bResult = WriteSectors(state, pPartState->snPBRSector, 1, buffer);
    }
    

    LocalFree(buffer);
    return bResult;
}

/*****************************************************************************
 *  UpdateMBR - updates the size of an entry in the MBR.
 *
 *  Input:  state - structure for this store
 *          pPartState - partition structure for the partition to update
 *
 *  Output: none
 *
 *
 *  Return: TRUE if MBR updated successfully, FALSE if not
 *
 *****************************************************************************/
BOOL UpdateMBR(DriverState *state, PartState *pPartState)
{
    PBYTE       buffer = NULL;
    PPARTENTRY  tmpbuffer;
    BOOL        bResult;
    int         i;

    bResult = ReadSectors (state, 0, 1, &buffer);
    if (!bResult)
        return FALSE;

    for (i = 0, tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET); i < 4; i++, tmpbuffer++) {
        if (tmpbuffer->Part_StartSector == pPartState->snStartSector)
            break;
    }

    if (i >= 4)
    {
        // for some reason we didn't find the partition we're trying to delete - this should never happen
        LocalFree(buffer);
        SetLastError(ERROR_GEN_FAILURE);
        return FALSE;
    }

    // update the partition info
    bResult = ConvertLBAtoCHS (state, (DWORD)pPartState->snStartSector, &tmpbuffer->Part_FirstTrack, &tmpbuffer->Part_FirstHead, &tmpbuffer->Part_FirstSector);

    tmpbuffer->Part_FileSystem = pPartState->partType;
    tmpbuffer->Part_StartSector = (DWORD)pPartState->snStartSector;
    tmpbuffer->Part_TotalSectors = (DWORD)pPartState->snNumSectors;
    bResult = ConvertLBAtoCHS (state, tmpbuffer->Part_StartSector + tmpbuffer->Part_TotalSectors -1, &tmpbuffer->Part_LastTrack, &tmpbuffer->Part_LastHead, &tmpbuffer->Part_LastSector);

    bResult = WriteSectors(state, 0, 1, buffer);
    LocalFree(buffer);

    return bResult;
}

/*****************************************************************************
 *  DeleteMBR - deletes a partition entry in the master boot record - all
 *  partition records that follow the one to be deleted are shifted back 1
 *  entry so no holes exist in the MBR.
 *
 *  Input:  state - structure for this store
 *          pPartState - partition structure for the partition to delete
 *
 *  Output: none
 *
 *
 *  Return: TRUE if MBR updated successfully, FALSE if not
 *
 *****************************************************************************/
BOOL DeleteMBR(DriverState *state, PartState *pPartState)
{

    PBYTE       buffer = NULL;
    PPARTENTRY  tmpbuffer, tmpbuffer1;
    BOOL        bResult;
    int         i, partNum, partIndex = -1;

    bResult = ReadSectors (state, 0, 1, &buffer);
    if (!bResult)
        return FALSE;

    for (i = 0, partNum = 3, tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET); i < 4; i++, tmpbuffer++) {
        if (tmpbuffer->Part_StartSector == pPartState->snStartSector)
            partIndex = i;

        if (tmpbuffer->Part_TotalSectors == 0)
        {
            partNum = i - 1;
            break;
        }
    }

    if ((partIndex == -1 || partNum == -1))
    {
        // for some reason we didn't find the partition we're trying to delete - this should never happen
        LocalFree(buffer);
        SetLastError(ERROR_GEN_FAILURE);
        return FALSE;
    }

    tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET + (partIndex * sizeof(PARTENTRY)));
    tmpbuffer1 = (PPARTENTRY)(buffer + PARTTABLE_OFFSET + ((partIndex +1) * sizeof(PARTENTRY)));

    // remove this partition entry by shifting all the others up in the table
    for (; partIndex < partNum; partIndex++)
    {
        memcpy(tmpbuffer, tmpbuffer1, sizeof(PARTENTRY));
        tmpbuffer++;
        tmpbuffer1++;
    }

    // set the last entry to 0's
    memset (tmpbuffer, 0, sizeof(PARTENTRY));

    bResult = WriteSectors(state, 0, 1, buffer);
    LocalFree(buffer);

    return bResult;

}

/*****************************************************************************
 *  WriteMBR - adds a partition entry to the master boot record. The partition
 *  table is traversed to find the placement for this partition.  Entries within
 *  the MBR are sorted by the start sector.
 *
 *  Input:  state - structure for this store
 *          snSectorNum - start sector number for this partition
 *          snNumSectors - number of sectors in this partition

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?