mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
559 lines
16 KiB
559 lines
16 KiB
/*** binfmt.c - Binary Data Format services
|
|
*
|
|
* This module contains format services for converting binary data into format
|
|
* text strings according to the format record.
|
|
*
|
|
* Copyright (c) 1995,1996 Microsoft Corporation
|
|
* Author: Michael Tsang (MikeTs)
|
|
* Created 11/06/95
|
|
*
|
|
* MODIFICATION HISTORY
|
|
*/
|
|
|
|
#ifdef __UNASM
|
|
|
|
#pragma warning (disable: 4001)
|
|
#include "basedef.h"
|
|
#define USE_CRUNTIME
|
|
#include "binfmt.h"
|
|
|
|
typedef int (*PFNFMT)(char *, PFMTHDR, BYTE *, DWORD *);
|
|
|
|
//Local function prototypes
|
|
int FormatNum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
|
|
int FormatEnum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
|
|
int FormatBits(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
|
|
int FormatString(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset);
|
|
int GetData(BYTE bUnitSize, BYTE *pb, DWORD dwOffset, DWORD *pdwData);
|
|
int PrintData(char *pszBuffer, BYTE bUnitSize, DWORD dwData, BOOL fPadSpace);
|
|
|
|
char szDefSep[] = SZ_SEP_SPACE;
|
|
char szDefOffsetFmt[] = SZ_FMT_WORDOFFSET;
|
|
PFNFMT FmtFuncTable[] =
|
|
{
|
|
FormatNum, //0: FMT_NUMBER
|
|
FormatEnum, //1: FMT_ENUM
|
|
FormatBits, //2: FMT_BITS
|
|
FormatString, //3: FMT_STRING
|
|
};
|
|
#define NUM_FMT_FUNCS (sizeof(FmtFuncTable)/sizeof(PFNFMT))
|
|
|
|
#ifdef FPRINTF
|
|
/***EP BinFPrintf - Binary fprintf
|
|
*
|
|
* ENTRY
|
|
* pfile -> output file
|
|
* pszBuffer -> buffer to hold the formatted string
|
|
* (if NULL, use internal buffer)
|
|
* pfmt -> format record array
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer (if NULL, use internal)
|
|
* pszOffsetFormat -> offset format string (can be NULL)
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int BinFPrintf(FILE *pfile, char *pszBuffer, PFMT pfmt, BYTE *pb,
|
|
DWORD *pdwOffset, char *pszOffsetFormat)
|
|
{
|
|
TRACENAME("BINFPRINTF")
|
|
int rc = FERR_NONE;
|
|
DWORD dwOffset = 0, dwOldOffset;
|
|
DWORD dwData;
|
|
char szBuff[256];
|
|
char *psz = pszBuffer? pszBuffer: szBuff;
|
|
DWORD *pdw = pdwOffset? pdwOffset: &dwOffset;
|
|
|
|
ENTER(4, ("BinFPrintf(pszBuff=%lx,pfmt=%lx,pdwOffset=%lx,Offset=%lx)\n",
|
|
pszBuffer, pfmt, pdwOffset, pdwOffset? *pdwOffset: 0));
|
|
|
|
if (pfmt != NULL)
|
|
{
|
|
BYTE i, j;
|
|
|
|
for (i = 0; pfmt[i].pfmtType != NULL; ++i)
|
|
{
|
|
if (pfmt[i].pszLabel != NULL)
|
|
{
|
|
if (pszOffsetFormat != NULL)
|
|
{
|
|
FPRINTF(pfile, pszOffsetFormat,
|
|
*pdw, pfmt[i].pfmtType->bUnitSize);
|
|
if (pfmt[i].pfmtType->dwfFormat & FMTF_NO_RAW_DATA)
|
|
{
|
|
FPRINTF(pfile, " ");
|
|
}
|
|
else
|
|
{
|
|
if (GetData(pfmt[i].pfmtType->bUnitSize, pb, *pdw,
|
|
&dwData) == FERR_NONE)
|
|
{
|
|
PrintData(psz, pfmt[i].pfmtType->bUnitSize, dwData,
|
|
TRUE);
|
|
FPRINTF(pfile, psz);
|
|
}
|
|
|
|
for (j = 1; j < pfmt[i].pfmtType->bUnitCnt; ++j)
|
|
{
|
|
if (GetData(pfmt[i].pfmtType->bUnitSize, pb,
|
|
*pdw + j*pfmt[i].pfmtType->bUnitSize,
|
|
&dwData) == FERR_NONE)
|
|
{
|
|
FPRINTF(pfile, ",");
|
|
PrintData(psz, pfmt[i].pfmtType->bUnitSize,
|
|
dwData, FALSE);
|
|
FPRINTF(pfile, psz);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (pfmt[i].pszLabel[0] != '\0')
|
|
FPRINTF(pfile, ";%s", pfmt[i].pszLabel);
|
|
else
|
|
FPRINTF(pfile, "\n");
|
|
}
|
|
|
|
dwOldOffset = *pdw;
|
|
if ((pfmt[i].pszLabel != NULL) && (pfmt[i].pszLabel[0] == '\0'))
|
|
{
|
|
*pdw += pfmt[i].pfmtType->bUnitCnt*pfmt[i].pfmtType->bUnitSize;
|
|
}
|
|
else
|
|
{
|
|
if (pfmt[i].pszLabel == NULL)
|
|
FPRINTF(pfile, ",");
|
|
rc = BinSprintf(psz, pfmt[i].pfmtType, pb, pdw);
|
|
if (rc == FERR_NONE)
|
|
{
|
|
char *psz1, *psz2;
|
|
BOOL fSpace = FALSE, fInQuote = FALSE, fInString = FALSE;
|
|
|
|
for (psz1 = psz2 = psz; *psz2 != '\0'; ++psz2)
|
|
{
|
|
if (*psz2 == '"')
|
|
{
|
|
fSpace = FALSE;
|
|
fInString = ~fInString;
|
|
*psz1 = *psz2;
|
|
psz1++;
|
|
}
|
|
else if (*psz2 == '\'')
|
|
{
|
|
fSpace = FALSE;
|
|
fInQuote = ~fInQuote;
|
|
*psz1 = *psz2;
|
|
psz1++;
|
|
}
|
|
else if (*psz2 == ' ')
|
|
{
|
|
if (!fSpace && !fInString && !fInQuote &&
|
|
(psz1 != psz))
|
|
{
|
|
*psz1 = ',';
|
|
psz1++;
|
|
}
|
|
else if (fInString || fInQuote)
|
|
{
|
|
*psz1 = *psz2;
|
|
psz1++;
|
|
}
|
|
fSpace = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fSpace = FALSE;
|
|
*psz1 = *psz2;
|
|
psz1++;
|
|
}
|
|
}
|
|
|
|
|
|
if ((psz1 > psz) && (*(psz1 - 1) == ','))
|
|
*(psz1 - 1) = '\0';
|
|
else if ((psz1 > psz) && (*(psz1 - 1) == '\n') &&
|
|
(*(psz1 - 2) == ','))
|
|
{
|
|
*(psz1 - 2) = '\n';
|
|
*(psz1 - 1) = '\0';
|
|
}
|
|
else
|
|
*psz1 = '\0';
|
|
FPRINTF(pfile, psz);
|
|
}
|
|
}
|
|
|
|
if (pfmt[i].lpfn != NULL)
|
|
(*pfmt[i].lpfn)(pfile, pb, dwOldOffset);
|
|
}
|
|
}
|
|
|
|
EXIT(4, ("BinFPrintf=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //BinFPrintf
|
|
#endif //ifdef FPRINTF
|
|
|
|
/***EP BinSprintf - Binary sprintf
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold the formatted string
|
|
* pfmt -> format record
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int BinSprintf(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
|
|
{
|
|
TRACENAME("BINSPRINTF")
|
|
int rc = FERR_NONE;
|
|
|
|
ENTER(4, ("BinSprintf(fmt=%d,Offset=%lx)\n", pfmt->bFmtType, *pdwOffset));
|
|
|
|
if (pfmt->bFmtType >= NUM_FMT_FUNCS)
|
|
rc = FERR_INVALID_FORMAT;
|
|
else
|
|
{
|
|
int i;
|
|
BYTE j;
|
|
DWORD dwData;
|
|
|
|
*pszBuffer = '\0';
|
|
for (i = 0; (rc == FERR_NONE) && (i < pfmt->iRepeatCnt); ++i)
|
|
{
|
|
if (pfmt->dwfFormat & FMTF_PRINT_OFFSET)
|
|
{
|
|
SPRINTF(pszBuffer,
|
|
pfmt->pszOffsetFmt? pfmt->pszOffsetFmt: szDefOffsetFmt,
|
|
*pdwOffset);
|
|
}
|
|
|
|
if (!(pfmt->dwfFormat & FMTF_NO_PRINT_DATA) &&
|
|
(GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData) ==
|
|
FERR_NONE))
|
|
{
|
|
PrintData(pszBuffer, pfmt->bUnitSize, dwData, FALSE);
|
|
STRCAT(pszBuffer, ";");
|
|
}
|
|
|
|
if (pfmt->pszLabel)
|
|
STRCAT(pszBuffer, pfmt->pszLabel);
|
|
|
|
for (j = 0; (rc == FERR_NONE) && (j < pfmt->bUnitCnt); ++j)
|
|
{
|
|
rc = (*FmtFuncTable[pfmt->bFmtType])
|
|
(&pszBuffer[STRLEN(pszBuffer)], pfmt, pb, pdwOffset);
|
|
|
|
if (rc == FERR_NONE)
|
|
{
|
|
if (!(pfmt->dwfFormat & FMTF_NO_SEP))
|
|
{
|
|
STRCAT(pszBuffer,
|
|
pfmt->pszFieldSep? pfmt->pszFieldSep: szDefSep);
|
|
}
|
|
|
|
if (!(pfmt->dwfFormat & FMTF_NO_INC_OFFSET))
|
|
*pdwOffset += pfmt->bUnitSize;
|
|
}
|
|
}
|
|
|
|
if ((rc == FERR_NONE) && !(pfmt->dwfFormat & FMTF_NO_EOL))
|
|
{
|
|
STRCAT(pszBuffer, "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
EXIT(4, ("BinSprintf=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //BinSprintf
|
|
|
|
/***LP FormatNum - Format numbers
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold formatted string
|
|
* pfmt -> format record
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int FormatNum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
|
|
{
|
|
TRACENAME("FORMATNUM")
|
|
int rc;
|
|
PFMTNUM pfmtNum = (PFMTNUM)pfmt;
|
|
DWORD dwData;
|
|
|
|
ENTER(5, ("FormatNum(Offset=%lx)\n", *pdwOffset));
|
|
|
|
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
|
|
{
|
|
dwData &= pfmtNum->dwMask;
|
|
dwData >>= pfmtNum->bShiftCnt;
|
|
|
|
SPRINTF(&pszBuffer[STRLEN(pszBuffer)], pfmtNum->pszNumFmt, dwData);
|
|
}
|
|
|
|
EXIT(5, ("FormatNum=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //FormatNum
|
|
|
|
/***LP FormatEnum - Format enumerated values
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold formatted string
|
|
* pfmt -> format record
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int FormatEnum(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
|
|
{
|
|
TRACENAME("FORMATENUM")
|
|
int rc = FERR_NONE;
|
|
PFMTENUM pfmtEnum = (PFMTENUM)pfmt;
|
|
DWORD dwData;
|
|
|
|
ENTER(5, ("FormatEnum(Offset=%lx)\n", *pdwOffset));
|
|
|
|
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
|
|
{
|
|
dwData &= pfmtEnum->dwMask;
|
|
dwData >>= pfmtEnum->bShiftCnt;
|
|
|
|
if ((dwData < pfmtEnum->dwStartEnum) || (dwData > pfmtEnum->dwEndEnum))
|
|
STRCAT(pszBuffer, pfmtEnum->pszOutOfRange);
|
|
else
|
|
{
|
|
dwData -= pfmtEnum->dwStartEnum;
|
|
STRCAT(pszBuffer, pfmtEnum->ppszEnumNames[dwData]);
|
|
}
|
|
}
|
|
|
|
EXIT(5, ("FormatEnum=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //FormatEnum
|
|
|
|
/***LP FormatBits - Format bit values
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold formatted string
|
|
* pfmt -> format record
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int FormatBits(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
|
|
{
|
|
TRACENAME("FORMATBITS")
|
|
int rc = FERR_NONE;
|
|
PFMTBITS pfmtBits = (PFMTBITS)pfmt;
|
|
DWORD dwData;
|
|
|
|
ENTER(5, ("FormatBits(Offset=%lx)\n", *pdwOffset));
|
|
|
|
if ((rc = GetData(pfmt->bUnitSize, pb, *pdwOffset, &dwData)) == FERR_NONE)
|
|
{
|
|
int i, j;
|
|
DWORD dw;
|
|
|
|
for (i = 31, j = 0; i >= 0; --i)
|
|
{
|
|
dw = 1L << i;
|
|
if (pfmtBits->dwMask & dw)
|
|
{
|
|
if (dwData & dw)
|
|
{
|
|
if ((pfmtBits->ppszOnNames != NULL) &&
|
|
(pfmtBits->ppszOnNames[j] != NULL))
|
|
{
|
|
STRCAT(pszBuffer, pfmtBits->ppszOnNames[j]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((pfmtBits->ppszOffNames != NULL) &&
|
|
(pfmtBits->ppszOffNames[j] != NULL))
|
|
{
|
|
STRCAT(pszBuffer, pfmtBits->ppszOffNames[j]);
|
|
}
|
|
}
|
|
|
|
if (!(pfmt->dwfFormat & FMTF_NO_SEP))
|
|
{
|
|
STRCAT(pszBuffer,
|
|
pfmt->pszFieldSep? pfmt->pszFieldSep: szDefSep);
|
|
}
|
|
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
EXIT(5, ("FormatBits=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //FormatBits
|
|
|
|
/***LP FormatString - Format string data
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold formatted string
|
|
* pfmt -> format record
|
|
* pb -> binary data buffer
|
|
* pdwOffset -> offset to binary data buffer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int FormatString(char *pszBuffer, PFMTHDR pfmt, BYTE *pb, DWORD *pdwOffset)
|
|
{
|
|
TRACENAME("FORMATSTRING")
|
|
int rc = FERR_NONE;
|
|
|
|
ENTER(5, ("FormatString(Offset=%lx)\n", *pdwOffset));
|
|
|
|
pb += *pdwOffset;
|
|
if (pfmt->dwfFormat & FMTF_STR_ASCIIZ)
|
|
{
|
|
pszBuffer[0] = '"';
|
|
STRCPY(pszBuffer + 1, (char *)pb);
|
|
pszBuffer[STRLEN(pszBuffer)] = '"';
|
|
if ((pfmt->bUnitSize == 0) && !(pfmt->dwfFormat & FMTF_NO_INC_OFFSET))
|
|
*pdwOffset += STRLEN((char *)pb) + 3;
|
|
}
|
|
else if (pfmt->bUnitSize != 0)
|
|
{
|
|
if (isalnum(*pb) || (*pb == ' '))
|
|
{
|
|
pszBuffer[0] = '\'';
|
|
STRCPYN(pszBuffer + 1, (char *)pb, pfmt->bUnitSize);
|
|
pszBuffer[pfmt->bUnitSize + 1] = '\'';
|
|
pszBuffer[pfmt->bUnitSize + 2] = '\0';
|
|
}
|
|
else
|
|
{
|
|
rc = PrintData(pszBuffer, pfmt->bUnitSize, *((PDWORD)pb), FALSE);
|
|
}
|
|
}
|
|
|
|
EXIT(5, ("FormatString=%d (Offset=%lx,Buff=%s)\n",
|
|
rc, *pdwOffset, pszBuffer));
|
|
return rc;
|
|
} //FormatString
|
|
|
|
/***LP GetData - Get data of appropriate size from the binary buffer
|
|
*
|
|
* ENTRY
|
|
* bUnitSize - size of data unit
|
|
* pb -> data buffer
|
|
* dwOffset - offset into data buffer
|
|
* pdwData -> to hold data
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int GetData(BYTE bUnitSize, BYTE *pb, DWORD dwOffset, DWORD *pdwData)
|
|
{
|
|
TRACENAME("GETDATA")
|
|
int rc = FERR_NONE;
|
|
|
|
ENTER(6, ("GetData(UnitSize=%d,Data=%lx,Offset=%lx)\n",
|
|
bUnitSize, *(DWORD *)pb, dwOffset));
|
|
|
|
pb += dwOffset;
|
|
switch (bUnitSize)
|
|
{
|
|
case UNIT_BYTE:
|
|
*pdwData = (DWORD)(*pb);
|
|
break;
|
|
case UNIT_WORD:
|
|
*pdwData = (DWORD)(*((WORD *)pb));
|
|
break;
|
|
case UNIT_DWORD:
|
|
*pdwData = *(DWORD *)pb;
|
|
break;
|
|
default:
|
|
rc = FERR_INVALID_UNITSIZE;
|
|
}
|
|
|
|
EXIT(6, ("GetData=%d (Data=%lx)\n", rc, *pdwData));
|
|
return rc;
|
|
} //GetData
|
|
|
|
/***LP PrintData - Print data value according to its size
|
|
*
|
|
* ENTRY
|
|
* pszBuffer -> buffer to hold formatted string
|
|
* bUnitSize - size of data unit
|
|
* dwData - number
|
|
* fPadSpace - if TRUE pad space to 8 chars
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns FERR_NONE
|
|
* EXIT-FAILURE
|
|
* returns negative error code
|
|
*/
|
|
|
|
int PrintData(char *pszBuffer, BYTE bUnitSize, DWORD dwData, BOOL fPadSpace)
|
|
{
|
|
TRACENAME("PRINTDATA")
|
|
int rc = FERR_NONE;
|
|
|
|
ENTER(6, ("PrintData(UnitSize=%d,Data=%lx)\n", bUnitSize, dwData));
|
|
|
|
switch (bUnitSize)
|
|
{
|
|
case UNIT_BYTE:
|
|
SPRINTF(pszBuffer, "%02x", (BYTE)dwData);
|
|
if (fPadSpace)
|
|
STRCAT(pszBuffer, " ");
|
|
break;
|
|
case UNIT_WORD:
|
|
SPRINTF(pszBuffer, "%04x", (WORD)dwData);
|
|
if (fPadSpace)
|
|
STRCAT(pszBuffer, " ");
|
|
break;
|
|
case UNIT_DWORD:
|
|
SPRINTF(pszBuffer, "%08lx", dwData);
|
|
break;
|
|
default:
|
|
rc = FERR_INVALID_UNITSIZE;
|
|
}
|
|
|
|
EXIT(6, ("PrintData=%d (Buff=%s)\n", rc, pszBuffer));
|
|
return rc;
|
|
} //PrintData
|
|
|
|
#endif //ifdef __UNASM
|