part.cpp
来自「WinCE5.0部分核心源码」· C++ 代码 · 共 1,292 行 · 第 1/3 页
CPP
1,292 行
//
// 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 <fsdmgr.h>
#include "part.h"
#include "bpb.h"
#include "bootsec.h"
#include "drvdbg.h"
static DWORD LoadDiskInfo(PDriverState pState)
{
DWORD dummy;
// fail the open if we can't get params from the device driver
if (!FSDMGR_DiskIoControl(pState->hDsk, DISK_IOCTL_GETINFO, &pState->diskInfo, sizeof(DISK_INFO), NULL, 0, &dummy, NULL))
{
return ERROR_GEN_FAILURE;
}
// simple check to verify the device is useful
if (pState->diskInfo.di_bytes_per_sect == 0 || pState->diskInfo.di_total_sectors == 0)
{
return ERROR_GEN_FAILURE;
}
if (pState->diskInfo.di_heads == 0)
pState->diskInfo.di_heads = 1;
if (pState->diskInfo.di_cylinders == 0)
pState->diskInfo.di_cylinders = 1;
if (pState->diskInfo.di_sectors == 0)
pState->diskInfo.di_sectors = pState->diskInfo.di_total_sectors;
return ERROR_SUCCESS;
}
/*****************************************************************************/
DWORD PD_OpenStore(HANDLE hDisk, LPDWORD pdwStoreId)
{
PPARTENTRY tmpbuffer;
PartState *pPartState;
DriverState *pState;
DWORD dwError=ERROR_SUCCESS, lastUsedSector;
SECTORNUM snPartSector;
PBYTE buffer = NULL;
int i;
*pdwStoreId = NULL;
DEBUGMSG( ZONE_API, (L"MSPART!PD_OpenStore hDisk=%08X\r\n", hDisk));
pState = (PDriverState)LocalAlloc(LMEM_ZEROINIT, sizeof(DriverState));
if (!pState)
return ERROR_OUTOFMEMORY;
// convert the device handle to a store handle for FSDMGR_* helper functions
pState->hDsk = FSDMGR_DeviceHandleToHDSK(hDisk);
dwError = LoadDiskInfo(pState);
if (ERROR_SUCCESS != dwError)
{
LocalFree(pState);
return dwError;
}
// Find out if we should create primary partitions
DWORD dwRegValue;
FSDMGR_GetRegistryValue( pState->hDsk, TEXT("PrimaryPart"), (PDWORD)&dwRegValue);
if (dwRegValue)
pState->dwFlags |= MSPART_CREATE_PRIMARY;
FSDMGR_GetRegistryValue( pState->hDsk, TEXT("AlignCylinder"), (PDWORD)&dwRegValue);
if (dwRegValue)
pState->dwFlags |= MSPART_ALIGN_CYLINDER;
FSDMGR_GetRegistryValue( pState->hDsk, TEXT("SkipSector1"), (PDWORD)&dwRegValue);
if (dwRegValue)
pState->dwFlags |= MSPART_SKIP_SECTOR1;
pState->pPartState = NULL;
pState->pSearchState = NULL;
// assume this is unformatted for now
pState->bFormatState = FALSE;
if (!ReadSectors(pState, 0, 1, &buffer)) {
if (!(pState->diskInfo.di_flags & DISK_INFO_FLAG_UNFORMATTED)) {
dwError = ERROR_READ_FAULT;
}
goto Exit;
}
pPartState = NULL;
snPartSector = 0;
// process the DOS partition tables and potentially extended partition tables
dwError = GetDOSPartitions (pState, &pPartState, buffer, FALSE, &snPartSector);
if (dwError) {
// If the sector has a boot signature and it is a FAT volume, then we assume that it is a superfloppy
if (IS_VALID_BOOTSEC(buffer) &&
(((PBOOTSEC)buffer)->bsBPB.BPB_BigTotalSectors || ((PBOOTSEC)buffer)->bsBPB.BPB_TotalSectors) &&
(((PBOOTSEC)buffer)->bsBPB.BPB_BigTotalSectors != 0xffffffff))
{
dwError = ERROR_DEVICE_NOT_PARTITIONED;
goto Exit;
}
else
{
// in this case, we don't fail the call, but the store is not formatted
if (dwError == ERROR_INVALID_DATA) {
dwError = ERROR_SUCCESS;
// For primary partitions, if there is a valid bootsig, then it is formatted.
if ((pState->dwFlags & MSPART_CREATE_PRIMARY) && IS_VALID_BOOTSEC(buffer))
pState->bFormatState = TRUE;
goto Exit;
}
}
dwError = ERROR_READ_FAULT;
goto Exit;
}
// this drive has a valid partition table - do a sanity check to adjust the diskInfo structure in case this drive
// was formatted through another OS - if that's the case, our CHS geometry should match the previously used CHS
// this involves three assumptions: 1 - that all partitions in the partition table are using the same CHS geometry
// 2 - the CHS parameters fit within the legacy restrictions of 6 bits/sector 8 bits/heads and 10 bits/cylinders
// 3 - the partitions all end on a cylinder boundary
tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET);
// there's no extended partition, add one now to hold our data, and use the rest of the disk
if (pState->snExtPartSector == 0) {
lastUsedSector = 0;
for (i=0, tmpbuffer = (PPARTENTRY)(buffer + PARTTABLE_OFFSET); i < 4; i++, tmpbuffer++) {
if (tmpbuffer->Part_TotalSectors == 0)
continue;
lastUsedSector = tmpbuffer->Part_StartSector + tmpbuffer->Part_TotalSectors -1;
// the extended partition starts on the next cylinder boundary, so adjust if needed
if (pState->diskInfo.di_heads > 1)
lastUsedSector += ((pState->diskInfo.di_heads - (tmpbuffer->Part_LastHead +1)) * pState->diskInfo.di_sectors) + pState->diskInfo.di_sectors - (tmpbuffer->Part_LastSector & 0x3f);
}
// create an extended partition only if there's room on the disk and in the MBR
#if 0
BOOL bResult;
if ((lastUsedSector < (pState->diskInfo.di_total_sectors -1)) &&
((i != 3) || (!tmpbuffer->Part_TotalSectors)))
{
// if this fails, it's not because there's no room for it
bResult = WriteMBR(pState, lastUsedSector + 1, pState->diskInfo.di_total_sectors - lastUsedSector -1, PART_EXTENDED, FALSE);
if (!bResult) {
PD_CloseStore((DWORD)pState);
dwError = ERROR_WRITE_FAULT;
goto Exit;
}
// we added it successfully, update the pState structure so we know where it is
pState->snExtPartSector = lastUsedSector + 1;
pState->snExtPartEndSec = pState->diskInfo.di_total_sectors - 1;
}
#endif
}
// we have a valid format
pState->bFormatState = TRUE;
#if HIDDEN_PARTITIONS
pState->bUseHiddenPartitions = TRUE;
// process the hidden partition table to add in the extra partition data that we track
if (pState->pHiddenPartState) {
bResult = GetHiddenPartitions (pState);
GeneratePartitionNames(pState);
if (!bResult) {
UpdateFileTime(pState, NULL, TRUE, FALSE);
if (!WriteHiddenPartitionTable(pState)) {
pState->bUseHiddenPartitions = FALSE;
}
}
} else {
// no hidden partition, try to add one now
if (!AddHiddenPartition(pState)) {
pState->bUseHiddenPartitions = FALSE;
}
GeneratePartitionNames(pState);
if (pState->bUseHiddenPartitions) {
UpdateFileTime(pState, NULL, TRUE, FALSE);
if (!WriteHiddenPartitionTable(pState)) {
pState->bUseHiddenPartitions = FALSE;
}
}
}
#else
GeneratePartitionNames(pState);
#endif
Exit:
if (buffer) {
LocalFree( buffer);
}
*pdwStoreId = (DWORD)pState;
return dwError;
}
/*****************************************************************************/
DWORD PD_GetStoreInfo(DWORD dwStoreId, PPD_STOREINFO psi)
{
BOOL bResult;
DriverState *pState = (PDriverState) dwStoreId;
DEBUGMSG(ZONE_API, (L"MSPART!PD_GetStoreInfo: dwStoreId=%08X \r\n", dwStoreId));
if (psi->cbSize != sizeof(PD_STOREINFO)) {
return ERROR_INVALID_PARAMETER;
}
memset( psi, 0, sizeof(PD_STOREINFO));
psi->cbSize = sizeof(PD_STOREINFO);
psi->ftCreated = pState->ftCreate;
psi->ftLastModified = pState->ftAccess;
psi->dwBytesPerSector = pState->diskInfo.di_bytes_per_sect;
psi->snNumSectors = pState->diskInfo.di_total_sectors;
bResult = CalculatePartitionSpace(pState, &psi->snFreeSectors, &psi->snBiggestPartCreatable);
if (!bResult)
return ERROR_GEN_FAILURE;
if (!pState->bFormatState)
psi->dwAttributes |= STORE_ATTRIBUTE_UNFORMATTED;
return ERROR_SUCCESS;
}
/*****************************************************************************/
void PD_CloseStore(DWORD dwStoreId)
{
DriverState *pState = (PDriverState)dwStoreId;
ClearPartitionList(pState);
LocalFree(pState);
}
/*****************************************************************************/
DWORD PD_FormatStore(DWORD dwStoreId)
{
PBYTE buffer = NULL;
DWORD bufferSize;
DWORD dummy;
BOOL bResult;
DWORD dwError;
DriverState *pState = (PDriverState) dwStoreId;
DEBUGMSG(ZONE_API, (L"PD_FormatStore: dwStoreId=%08X\n", dwStoreId));
if (!FSDMGR_DiskIoControl(pState->hDsk, DISK_IOCTL_FORMAT_MEDIA, &(pState->diskInfo), sizeof(DISK_INFO), NULL, 0, &dummy, NULL)) {
dwError= GetLastError();
RETAILMSG(TRUE,(L"MSPART!FormatStore: Driver has failed low-level format request (%d)\n", dwError));
return dwError? dwError : ERROR_GEN_FAILURE;
}
/* update the disk information structure */
dwError = LoadDiskInfo(pState);
if (ERROR_SUCCESS != dwError) {
return dwError;
}
/* get an I/O buffer that is a multiple of the sector size */
bufferSize = pState->diskInfo.di_bytes_per_sect * 8;
buffer = (PBYTE)LocalAlloc(LMEM_ZEROINIT, bufferSize);
if (!buffer)
return ERROR_OUTOFMEMORY;
if (pState->dwFlags & MSPART_CREATE_PRIMARY) {
// add header and trailer info to the MBR. Clear partition table.
*(WORD *)(buffer + BOOT_SIGNATURE) = BOOTSECTRAILSIGH;
buffer[0] = 0xE9;
buffer[1] = 0xfd;
buffer[2] = 0xff;
memset (buffer + PARTTABLE_OFFSET, 0, MAX_PARTTABLE_ENTRIES * SIZE_PARTTABLE_ENTRIES);
}
bResult = WriteSectors(pState, 0, bufferSize / pState->diskInfo.di_bytes_per_sect, buffer);
LocalFree(buffer);
if (!bResult)
return ERROR_WRITE_FAULT;
// if we are formatted a previously formatted store, we need to clear out the existing partition structures first
if (pState->bFormatState)
ClearPartitionList(pState);
pState->dwNumParts = 0;
if (!(pState->dwFlags & MSPART_CREATE_PRIMARY)) {
// carve out the extended partition
// skip to the next cylinder boundary
if (pState->diskInfo.di_heads > 1)
pState->snExtPartSector = pState->diskInfo.di_sectors * pState->diskInfo.di_heads;
else
pState->snExtPartSector = 1;
pState->snExtPartEndSec = pState->diskInfo.di_total_sectors - 1;
bResult = WriteMBR(pState, pState->snExtPartSector, pState->diskInfo.di_total_sectors - pState->snExtPartSector, PART_EXTENDED, TRUE);
if (!bResult)
return ERROR_WRITE_FAULT;
}
#if HIDDEN_PARTITIONS
pState->bUseHiddenPartitions = TRUE;
// next create a PBR for the hidden partition
bResult = AddHiddenPartition(pState);
if (!bResult) {
pState->bUseHiddenPartitions = FALSE;
} else {
UpdateFileTime(pState, NULL, TRUE, FALSE);
WriteHiddenPartitionTable(pState);
}
#endif
if (bResult)
pState->bFormatState = TRUE;
return bResult ? ERROR_SUCCESS : ERROR_GEN_FAILURE;
}
/*****************************************************************************/
DWORD PD_IsStoreFormatted(DWORD dwStoreId)
{
PDriverState pState = (PDriverState) dwStoreId;
return pState->bFormatState ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
}
/*****************************************************************************/
DWORD PD_CreatePartition(DWORD dwStoreId, LPCTSTR szPartitionName, BYTE bPartType, SECTORNUM snNumSectors, BOOL bAuto)
{
PartState *pNewPartState;
PartState *pTmpPartState;
SearchState *pSearchState;
BOOL bResult;
SECTORNUM snStartSector = 0;
SECTORNUM snNextPBRSector;
SECTORNUM snPrevPBRSector;
SECTORNUM snSectorCount;
SECTORNUM snPBRSector;
DriverState *pState = (PDriverState) dwStoreId;
DEBUGMSG (ZONE_API,(L"MSPART!PD_CreatePartition: dwStoreId=%08X, PartName %s, PartType=%ld, NumSectors=%d Auto=%s\n", dwStoreId, szPartitionName, bPartType, (DWORD)snNumSectors, bAuto ? L"TRUE" : L"FALSE"));
if (!pState->bFormatState) {
return ERROR_BAD_FORMAT;
}
if (!wcslen(szPartitionName)) {
return ERROR_INVALID_NAME;
}
if ((!snNumSectors) || (snNumSectors > pState->diskInfo.di_total_sectors)) {
return ERROR_DISK_FULL;
}
GetPartition(pState, &pTmpPartState, NULL, szPartitionName);
// don't allow the create if the name is not unique
if (pTmpPartState) {
return ERROR_ALREADY_EXISTS;
}
// the number of partitions is historically limited to the # of drive letters available through the extended partition
if (pState->dwNumParts == 24) {
return ERROR_PARTITION_FAILURE;
}
#if HIDDEN_PARTITIONS
// if we don't have a hidden partition, we probably don't have room for this one either
// but we'll try to create the hidden partition first and then if that works create the one requested
if (pState->bUseHiddenPartitions) {
UpdateFileTime(pState, NULL, TRUE, FALSE);
if (!WriteHiddenPartitionTable(pState)) {
pState->bUseHiddenPartitions = FALSE;
}
}
#endif
bResult = GetPartLocation (pState, snNumSectors, bPartType, &pTmpPartState, &snStartSector, &snPBRSector, &snSectorCount);
if (!bResult)
return ERROR_PARTITION_FAILURE;
pNewPartState = (PPartState)LocalAlloc(LMEM_ZEROINIT, sizeof(PartState));
if (!pNewPartState)
return ERROR_OUTOFMEMORY;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?