598 lines
11 KiB
C++
598 lines
11 KiB
C++
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
codepage.hxx
|
|
|
|
Abstract:
|
|
|
|
Container for HPFS Volume Codepage information
|
|
|
|
Author:
|
|
Mark Shavlik (marks) Nov-90
|
|
|
|
Environment:
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#if ! defined( UHPFS_CODEPAGE_DFN )
|
|
|
|
#define UHPFS_CODEPAGE_DFN
|
|
|
|
|
|
#include "hmem.hxx"
|
|
#include "secrun.hxx"
|
|
#include "verify.hxx"
|
|
|
|
//
|
|
// Forward references
|
|
//
|
|
|
|
DECLARE_CLASS( UHPFS_CODEPAGE );
|
|
DECLARE_CLASS( CPDATA );
|
|
DECLARE_CLASS( CODEPAGE_INFO );
|
|
DECLARE_CLASS( CASEMAP );
|
|
DECLARE_CLASS( HOTFIXLIST );
|
|
DECLARE_CLASS( HPFS_BITMAP );
|
|
DECLARE_CLASS( HPFS_MAIN_BITMAP );
|
|
DECLARE_CLASS( LOG_IO_DP_DRIVE );
|
|
|
|
//
|
|
// Codepage constants:
|
|
|
|
#define CCS_ROT 7
|
|
|
|
CONST EntriesPerCPInfoSector = 31;
|
|
CONST EntriesPerCPDataSector = 3;
|
|
CONST MaximumCodepagesOnVol = 128;
|
|
|
|
CONST InvalidCountryCode = 0xffff;
|
|
CONST InvalidCodepageID = 0xffff;
|
|
|
|
CONST CaseTableSize = 256;
|
|
|
|
CONST CharsInCasemap = 128;
|
|
|
|
class UHPFS_CODEPAGE : public OBJECT {
|
|
|
|
public:
|
|
|
|
DECLARE_CONSTRUCTOR( UHPFS_CODEPAGE );
|
|
|
|
VIRTUAL
|
|
~UHPFS_CODEPAGE();
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Initialize(
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Create(
|
|
IN OUT PLOG_IO_DP_DRIVE Drive,
|
|
IN LBN FirstInfoSectorLbn,
|
|
IN LBN DataSectorLbn
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VERIFY_RETURN_CODE
|
|
VerifyAndFix (
|
|
IN PLOG_IO_DP_DRIVE LogicalDrive,
|
|
IN PHOTFIXLIST HotfixList,
|
|
IN PHPFS_BITMAP Bitmap,
|
|
IN LBN FirstInfoSectorLbn,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Read(
|
|
IN PLOG_IO_DP_DRIVE LogicalDrive,
|
|
IN LBN FirstInfoSectorLbn
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
TakeCensus(
|
|
IN PLOG_IO_DP_DRIVE LogicalDrive,
|
|
IN LBN FirstInfoSectorLbn,
|
|
IN OUT PHPFS_MAIN_BITMAP HpfsOnlyBitmap
|
|
);
|
|
|
|
UHPFS_EXPORT
|
|
NONVIRTUAL
|
|
PCASEMAP
|
|
GetCasemap(
|
|
);
|
|
|
|
NONVIRTUAL
|
|
USHORT
|
|
QueryNumberOfCodepages (
|
|
);
|
|
|
|
VOID
|
|
Print (
|
|
);
|
|
|
|
|
|
private:
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Construct (
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Destroy(
|
|
);
|
|
|
|
// The CodePage object creates and maintains a _Casemap
|
|
// object; it is also responsible for destroying it.
|
|
|
|
PCASEMAP _Casemap;
|
|
|
|
USHORT mNumberOfCodepages;
|
|
USHORT mNumberOfValidCodepages;
|
|
|
|
BOOLEAN IsEntryValid[MaximumCodepagesOnVol];
|
|
USHORT CountryCodes[MaximumCodepagesOnVol];
|
|
USHORT CodepageIDs[MaximumCodepagesOnVol];
|
|
|
|
|
|
};
|
|
|
|
/*** Code Page - disk image
|
|
*
|
|
* Each volume has one or more sectors which contain information about
|
|
* the code pages stored on the volume. This information contains the
|
|
* ordering (index) of each code page, the country code, the code page
|
|
* id, lbn and offset of the code page information.
|
|
*
|
|
* Each Code Page Info sector contains up to 31 code page descriptions
|
|
* (including the locations of the code page data).
|
|
*
|
|
* Each Code Page Data sector contains up to 3 entries of code page data.
|
|
*
|
|
* Since all code pages case conversion is identical for character
|
|
* values 0-127, only 128 bytes are necessary for code page case
|
|
* conversion information.
|
|
*
|
|
* DBCS pairs are packed, with a trailing 0,0 pair terminating the list.
|
|
* No DBCS is indicated by a 0,0 pair.
|
|
*
|
|
* Currently no DBCS Code Page has more than 2 byte pairs, but we don't
|
|
* want to limit it to that.
|
|
*
|
|
* Code Page 850 is only stored once, since the case table is the same for
|
|
* ALL countries, and there is never DBCS support. It is stored with a
|
|
* 0 country code for easy matching.
|
|
*
|
|
*/
|
|
|
|
|
|
DEFINE_TYPE( ULONG, CHECKSUM );
|
|
|
|
|
|
/** DBCS_Range - DBCS range byte pairs **/
|
|
|
|
typedef struct _DBCS_Range {
|
|
|
|
UCHAR CDIB_DBCS_start;
|
|
UCHAR CDIB_DBCS_end;
|
|
} DBCS_Range;
|
|
|
|
|
|
typedef struct CPINFOENTRY { // cpinfoent
|
|
USHORT CountryCode; /* country code */
|
|
USHORT CodePageID; /* code page id */
|
|
CHECKSUM cksCP; /* checksum of code page data */
|
|
LBN lbnCPData; /* lbn containing code page data */
|
|
USHORT iCmphpfs; /* index of code page (on volume) */
|
|
USHORT cDBCSrange; /* # of DBCS ranges (0 -> no DBCS) */
|
|
} *PCPINFOENTRY;
|
|
|
|
|
|
typedef struct CPINFOSECTORD { // cpinfosecd
|
|
|
|
ULONG sig; // Data Sector Signature
|
|
ULONG cCodePage; // # of info entries in this sector
|
|
ULONG iFirstCP; // index on vol. of 1st entry in sector
|
|
LBN lbnNext; // lbn of next info sector
|
|
CPINFOENTRY cpinfoent[EntriesPerCPInfoSector]; // info entries
|
|
|
|
} *PCPINFOSECTORD;
|
|
|
|
|
|
/** CPDATAENTRY - Code Page Data entry
|
|
*
|
|
* For each code page, there is one of these structures. It contains
|
|
* the case conversion table for the upper half of the single-byte
|
|
* characters (the lower half is always translated using a fixed rule).
|
|
*/
|
|
|
|
typedef struct CPDATAENTRY { // cpdataent
|
|
USHORT CountryCode; /* country code */
|
|
USHORT CodePageID; /* code page id */
|
|
USHORT cDBCSrange; /* # of DBCS ranges */
|
|
BYTE bCaseMapTable [CharsInCasemap]; /* case conversion table for byte values
|
|
* greater than 127 */
|
|
DBCS_Range DBCS_RangeTable [1]; /* variable array of byte pairs
|
|
* (cDBCSrange + 1, with trailing 0,0)
|
|
*/
|
|
} *PCPDATAENTRY;
|
|
|
|
typedef struct CPDATASECTOR { // cpdatasec
|
|
|
|
ULONG sig;
|
|
USHORT cCodePage;
|
|
USHORT iFirstCP;
|
|
CHECKSUM cksCP[EntriesPerCPDataSector];
|
|
USHORT offCPData[EntriesPerCPDataSector];
|
|
BYTE pData[1]; // pointer to first data
|
|
|
|
} *PCPDATASECTOR;
|
|
|
|
/***************************************************************************\
|
|
|
|
CLASS: CPDATA
|
|
|
|
PURPOSE: Define data used to describe code pages.
|
|
|
|
INTERFACE: CPDATA Setup for creation or getting
|
|
|
|
NOTES:
|
|
|
|
HISTORY: 27-Mar-90 marks
|
|
define protocol
|
|
|
|
KEYWORDS:
|
|
|
|
SEEALSO:
|
|
|
|
\***************************************************************************/
|
|
|
|
class CPDATA : public SECRUN {
|
|
|
|
public:
|
|
|
|
DECLARE_CONSTRUCTOR( CPDATA );
|
|
|
|
BOOLEAN
|
|
Initialize(
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv
|
|
);
|
|
|
|
BOOLEAN
|
|
Create(
|
|
OUT PCHECKSUM CheckSum
|
|
);
|
|
|
|
VOID
|
|
Flush (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN USHORT Entries,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
BOOLEAN
|
|
NextEntryToCheck (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN LBN lbn,
|
|
IN PHPFS_BITMAP Bitmap,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
BOOLEAN
|
|
ReadNextEntry (
|
|
IN LBN lbn
|
|
);
|
|
|
|
CHECKSUM
|
|
ComputeChecksum (
|
|
);
|
|
|
|
BOOLEAN
|
|
VerifyAndFix (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN PCODEPAGE_INFO CurrentInfoEntry,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
BOOLEAN
|
|
IsValid ( );
|
|
|
|
PCPDATAENTRY
|
|
GetEntry(
|
|
) CONST;
|
|
|
|
private:
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Construct(
|
|
);
|
|
|
|
CHECKSUM ComputeChkSum ( ) CONST;
|
|
|
|
PCPDATASECTOR pcpdatasecd;
|
|
|
|
BOOLEAN mIsModified;
|
|
BOOLEAN mIsInitialized;
|
|
BOOLEAN mValidEntry;
|
|
BOOLEAN mSectorIsValid;
|
|
|
|
LBN mCurrentLbn;
|
|
USHORT mCurrentIndexInSector;
|
|
USHORT mExpectedOffset;
|
|
|
|
HMEM _hmem;
|
|
|
|
|
|
};
|
|
|
|
|
|
/***************************************************************************\
|
|
|
|
CLASS: CODEPAGE_INFO
|
|
|
|
PURPOSE: Store information about CPs and LBN pointers to CP data. CP
|
|
data is described by the CPDATA class.
|
|
|
|
INTERFACE: CODEPAGE_INFO Setup for creation or getting
|
|
|
|
|
|
NOTES:
|
|
|
|
HISTORY: 27-Mar-90 marks
|
|
define protocol
|
|
|
|
KEYWORDS:
|
|
|
|
SEEALSO:
|
|
|
|
\***************************************************************************/
|
|
|
|
|
|
class CODEPAGE_INFO : public SECRUN {
|
|
|
|
public:
|
|
|
|
DECLARE_CONSTRUCTOR( CODEPAGE_INFO );
|
|
|
|
BOOLEAN
|
|
Initialize(
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN LBN lbn
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Create(
|
|
IN LBN DataSectorLbn,
|
|
IN CHECKSUM CheckSum
|
|
);
|
|
|
|
VOID
|
|
Flush (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN USHORT Entries,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
BOOLEAN
|
|
NextEntryToCheck (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN PHOTFIXLIST HotfixList,
|
|
IN PHPFS_BITMAP Bitmap,
|
|
IN USHORT ExpectedIndex,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
BOOLEAN
|
|
ReadNextEntry (
|
|
);
|
|
|
|
VERIFY_RETURN_CODE
|
|
VerifyAndFix (
|
|
IN PHOTFIXLIST HotfixList,
|
|
IN USHORT ExpectedIndex,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
VOID
|
|
MarkEntryBad(
|
|
);
|
|
|
|
LBN
|
|
QueryDataLbn (
|
|
);
|
|
|
|
LBN
|
|
QueryCurrentLbn (
|
|
) CONST;
|
|
|
|
friend
|
|
BOOLEAN
|
|
CPDATA::VerifyAndFix (
|
|
IN PLOG_IO_DP_DRIVE pliodpdrv,
|
|
IN PCODEPAGE_INFO CurrentInfoEntry,
|
|
IN BOOLEAN UpdateAllowed,
|
|
OUT PBOOLEAN ErrorsDetected
|
|
);
|
|
|
|
USHORT
|
|
QueryCountry(
|
|
);
|
|
|
|
USHORT
|
|
QueryCPID (
|
|
);
|
|
|
|
NONVIRTUAL VOID
|
|
Print ( ) CONST;
|
|
|
|
|
|
private:
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Construct(
|
|
);
|
|
|
|
PCPINFOSECTORD pcpinfosecd;
|
|
|
|
BOOLEAN mIsInitialized;
|
|
BOOLEAN mSectorIsValid;
|
|
BOOLEAN mIsModified;
|
|
BOOLEAN mFirstEntry;
|
|
|
|
LBN mCurrentLbn;
|
|
USHORT mCurrentIndexInSector;
|
|
|
|
HMEM _hmem;
|
|
|
|
};
|
|
|
|
INLINE
|
|
LBN
|
|
CODEPAGE_INFO::QueryCurrentLbn(
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method returns the LBN that contains the current information
|
|
entry.
|
|
|
|
Arguments
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The LBN that contains the current information entry. Zero indicates
|
|
failure.
|
|
|
|
--*/
|
|
{
|
|
return mCurrentLbn;
|
|
}
|
|
|
|
|
|
class CASEMAP : public OBJECT {
|
|
|
|
public:
|
|
|
|
DECLARE_CONSTRUCTOR( CASEMAP );
|
|
|
|
VIRTUAL
|
|
~CASEMAP (
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Initialize (
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
HasDBCS(
|
|
IN ULONG CodePageIndex
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsDBCS(
|
|
ULONG CodePageIndex,
|
|
UCHAR Char
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UCHAR
|
|
UpperCase(
|
|
UCHAR Char,
|
|
ULONG CodePageIndex
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
AddCodepage (
|
|
ULONG CodepageIndex,
|
|
PCPDATAENTRY pcpdataent
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsCodpageIndexValid(
|
|
ULONG CodepageIndex
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
USHORT
|
|
QueryCodepageId(
|
|
IN ULONG CodepageIndex
|
|
);
|
|
|
|
private:
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Construct (
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Destroy(
|
|
);
|
|
|
|
PUCHAR _CaseTable[ MaximumCodepagesOnVol ];
|
|
PBOOLEAN _IsDBCS [ MaximumCodepagesOnVol ];
|
|
USHORT _CodepageId[ MaximumCodepagesOnVol ];
|
|
BOOLEAN _IsValid[ MaximumCodepagesOnVol ];
|
|
BOOLEAN _HasDBCS[ MaximumCodepagesOnVol ];
|
|
|
|
};
|
|
|
|
INLINE
|
|
USHORT
|
|
CASEMAP::QueryCodepageId(
|
|
IN ULONG CodepageIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This method returns the code page id for the specified
|
|
volume codepage.
|
|
|
|
Arguments:
|
|
|
|
CodepageIndex -- Supplies the index on the volume of the
|
|
desired codepage.
|
|
|
|
Return Value:
|
|
|
|
The codepage ID for the specified codepage.
|
|
|
|
--*/
|
|
{
|
|
return _CodepageId[CodepageIndex];
|
|
}
|
|
|
|
#endif
|