403 lines
11 KiB
C
403 lines
11 KiB
C
|
/****************************** Module Header ******************************\
|
||
|
* Module Name: dsocode.c
|
||
|
*
|
||
|
* Copyright (c) 1985-96, Microsoft Corporation
|
||
|
*
|
||
|
* This file contains the dump structure offset (dso) extension. It is
|
||
|
* included by $(ALT_PROJECT)\dsotable.c which is generated by structo.exe
|
||
|
*
|
||
|
* History:
|
||
|
* 06/17/96 GerardoB Created
|
||
|
\***************************************************************************/
|
||
|
#include <stdexts.h>
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* dsoTerminateString
|
||
|
*
|
||
|
* This is used to "parse" the command line. It null-terminates a space
|
||
|
* delimited string, returns its size and a pointer to the begining
|
||
|
* of next string
|
||
|
*
|
||
|
* 06/17/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
LPSTR dsoTerminateString(LPSTR psz, PDWORD pdwSize)
|
||
|
{
|
||
|
LPSTR pszWork = psz;
|
||
|
|
||
|
while (*pszWork != 0) {
|
||
|
if (*pszWork == ' ') {
|
||
|
*pszWork++ = 0;
|
||
|
break;
|
||
|
}
|
||
|
pszWork++;
|
||
|
}
|
||
|
|
||
|
*pdwSize = (DWORD)(pszWork - psz);
|
||
|
if (*pszWork != 0) {
|
||
|
(*pdwSize)--;
|
||
|
}
|
||
|
|
||
|
while ((*pszWork != 0) && (*pszWork == ' ')) {
|
||
|
pszWork++;
|
||
|
}
|
||
|
|
||
|
return pszWork;
|
||
|
}
|
||
|
/***************************************************************************\
|
||
|
* dsoGetOffset
|
||
|
*
|
||
|
* If the highest order bit of psot->dwOffset is set, then the value is a
|
||
|
* relative offset from the previous field; otherwise, it is the
|
||
|
* actual field offset from the beginnig of the structure
|
||
|
*
|
||
|
* 06/20/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
UINT dsoGetOffset (PSTRUCTUREOFFSETSTABLE psot)
|
||
|
{
|
||
|
if (!(psot->dwOffset & 0x80000000)) {
|
||
|
return psot->dwOffset;
|
||
|
} else {
|
||
|
return ((psot->dwOffset & ~0x80000000) + dsoGetOffset(psot - 1));
|
||
|
}
|
||
|
}
|
||
|
/***************************************************************************\
|
||
|
* dsoGetSize
|
||
|
*
|
||
|
* The field size is calculated by substracting its offset from the next
|
||
|
* field's offset. If the struct has unions, several "fields" might have
|
||
|
* the same offset, or a given table entry (i.e., a field) might have an
|
||
|
* offset value greater than the offset value for the next entry (a union
|
||
|
* of two structures).
|
||
|
*
|
||
|
* 06/26/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
UINT dsoGetSize (PSTRUCTUREOFFSETSTABLE psot, DWORD dwOffset)
|
||
|
{
|
||
|
DWORD dwNextFieldOffset;
|
||
|
|
||
|
do {
|
||
|
psot++;
|
||
|
dwNextFieldOffset = dsoGetOffset(psot);
|
||
|
} while (dwNextFieldOffset <= dwOffset);
|
||
|
|
||
|
return dwNextFieldOffset - dwOffset;
|
||
|
}
|
||
|
/***************************************************************************\
|
||
|
* dsoGetStruct
|
||
|
*
|
||
|
* 07/03/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
PSTRUCTURESTABLE dosGetStruct (LPSTR pszStruct, DWORD dwSize)
|
||
|
{
|
||
|
PSTRUCTURESTABLE pst = gst;
|
||
|
|
||
|
/*
|
||
|
* try an exact match
|
||
|
*/
|
||
|
while (pst->pszName != NULL) {
|
||
|
if (!_stricmp(pszStruct, pst->pszName)) {
|
||
|
return pst;
|
||
|
}
|
||
|
pst++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Partial prefix match
|
||
|
*/
|
||
|
pst = gst;
|
||
|
while (pst->pszName != NULL) {
|
||
|
if (!_strnicmp(pszStruct, pst->pszName, dwSize)) {
|
||
|
return pst;
|
||
|
}
|
||
|
pst++;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
|
||
|
}
|
||
|
/***************************************************************************\
|
||
|
* dsoGetField
|
||
|
*
|
||
|
* 07/03/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
PSTRUCTUREOFFSETSTABLE dosGetField (PSTRUCTUREOFFSETSTABLE psot, LPSTR pszField, DWORD dwSize)
|
||
|
{
|
||
|
PSTRUCTUREOFFSETSTABLE psotFirst = psot;
|
||
|
|
||
|
/*
|
||
|
* try an exact match
|
||
|
*/
|
||
|
while (psot->pszField != NULL) {
|
||
|
if (!_stricmp(pszField, psot->pszField)) {
|
||
|
return psot;
|
||
|
}
|
||
|
psot++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Partial prefix match
|
||
|
*/
|
||
|
psot = psotFirst;
|
||
|
while (psot->pszField != NULL) {
|
||
|
if (!_strnicmp(pszField, psot->pszField, dwSize)) {
|
||
|
return psot;
|
||
|
}
|
||
|
psot++;
|
||
|
}
|
||
|
return NULL;
|
||
|
|
||
|
}
|
||
|
/***************************************************************************\
|
||
|
* Idso
|
||
|
*
|
||
|
* !dso StructName [FieldName] [Address]
|
||
|
*
|
||
|
* 06/17/96 Created Gerardob
|
||
|
\***************************************************************************/
|
||
|
BOOL Idso(DWORD opts, LPSTR pszCmdLine)
|
||
|
{
|
||
|
BOOL fOneField = FALSE;
|
||
|
DWORD dwOptions;
|
||
|
DWORD dwValue, dwSize, dwBytesRead, dwOffset, dwOffsetNext, dwFieldsPerRow, dwMoveSize;
|
||
|
DWORD dwBuffer [20]; /* Make sure it has an even number of elemnts and at least 4*/
|
||
|
const DWORD *pcdwLimit = dwBuffer + (sizeof(dwBuffer) / sizeof(*dwBuffer));
|
||
|
DWORD *pdwValue;
|
||
|
LPSTR pszField, pszAddress;
|
||
|
PBYTE pBufferOffset;
|
||
|
PSTRUCTURESTABLE pst;
|
||
|
PSTRUCTUREOFFSETSTABLE psot;
|
||
|
PVOID pAddress = NULL;
|
||
|
|
||
|
if (pszCmdLine == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* NULL terminate first argument and get a pointer to
|
||
|
* second one (presumably the field name)
|
||
|
*/
|
||
|
/*
|
||
|
* Get the options, if any
|
||
|
*/
|
||
|
if (*pszCmdLine == '-') {
|
||
|
dwOptions = GetOpts(&pszCmdLine, NULL);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Find the struct table
|
||
|
*/
|
||
|
pszField = dsoTerminateString(pszCmdLine, &dwSize);
|
||
|
pst = dosGetStruct (pszCmdLine, dwSize);
|
||
|
if (pst == NULL) {
|
||
|
Print("Structure not found: %s\n", pszCmdLine);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Got a table
|
||
|
*/
|
||
|
psot = pst->psot;
|
||
|
|
||
|
/*
|
||
|
* If there is another argument, let's assume a field name follows
|
||
|
*/
|
||
|
if (*pszField != 0) {
|
||
|
/*
|
||
|
* Find the field
|
||
|
*/
|
||
|
pszAddress = dsoTerminateString(pszField, &dwSize);
|
||
|
psot = dosGetField (psot, pszField, dwSize);
|
||
|
|
||
|
/*
|
||
|
* If it didn't find the field and an address was provided, game over.
|
||
|
* Otherwise, the second parameter might be the address
|
||
|
*/
|
||
|
if (psot == NULL) {
|
||
|
if (*pszAddress != 0) {
|
||
|
Print("Field not found: %s. Struct: %s\n", pszField, pst->pszName);
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
pszAddress = pszField;
|
||
|
/*
|
||
|
* Reset psot since this argument was not a field
|
||
|
*/
|
||
|
psot = pst->psot;
|
||
|
}
|
||
|
} else {
|
||
|
fOneField = TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Get the pointer to the struct
|
||
|
*/
|
||
|
if (*pszAddress != 0) {
|
||
|
pAddress = EvalExp(pszAddress);
|
||
|
if (pAddress == NULL) {
|
||
|
/*
|
||
|
* EvalExp displayed the error message, so return silently
|
||
|
*/
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} /* if (*pszField != 0) */
|
||
|
|
||
|
|
||
|
/*
|
||
|
* If a field name was specified, dump that field only
|
||
|
* Otherwise, dump the whole table.
|
||
|
*/
|
||
|
if (fOneField) {
|
||
|
/*
|
||
|
* If no address available, just display the field name and offset
|
||
|
*/
|
||
|
dwOffset = dsoGetOffset(psot);
|
||
|
Print ("Structure %s - Size: %#lx\n", pst->pszName, pst->dwSize);
|
||
|
Print("Field: %s - Offset: %#lx\n", psot->pszField, dwOffset);
|
||
|
if (pAddress == NULL) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Printing field value
|
||
|
*/
|
||
|
|
||
|
/*123456789 1*/
|
||
|
Print("Address Value\n");
|
||
|
|
||
|
dwBytesRead = 0;
|
||
|
dwSize = dsoGetSize(psot, dwOffset);
|
||
|
/*
|
||
|
* Print 4 DWORDS per row; one row per loop
|
||
|
*/
|
||
|
|
||
|
do { /* while ((int)dwSize > 0) */
|
||
|
|
||
|
/*
|
||
|
* Read values for next row
|
||
|
*/
|
||
|
if (4 * sizeof(DWORD) >= dwSize) {
|
||
|
dwMoveSize = dwSize;
|
||
|
} else {
|
||
|
dwMoveSize = 4 * sizeof(DWORD);
|
||
|
}
|
||
|
moveBlock(dwBuffer, (PBYTE)pAddress + dwOffset + dwBytesRead, dwMoveSize);
|
||
|
pBufferOffset = (PBYTE)dwBuffer;
|
||
|
|
||
|
/*
|
||
|
* Print the address
|
||
|
*/
|
||
|
Print("%08lx ", (DWORD)((PBYTE)pAddress + dwOffset + dwBytesRead));
|
||
|
/*
|
||
|
* Keep track of bytes read (dwBytesRead) and bytes
|
||
|
* remaining to be read (dwSize)
|
||
|
*/
|
||
|
dwBytesRead += dwMoveSize;
|
||
|
dwSize -= dwMoveSize;
|
||
|
/*
|
||
|
* Print the values, one dword at the time
|
||
|
*/
|
||
|
while (dwMoveSize >= sizeof(DWORD)) {
|
||
|
Print("%08lx ", *((DWORD *)pBufferOffset));
|
||
|
pBufferOffset += sizeof(DWORD);
|
||
|
dwMoveSize -= sizeof(DWORD);
|
||
|
}
|
||
|
/*
|
||
|
* If less than a DWORD left, zero extend and print a DWORD
|
||
|
*/
|
||
|
if (dwMoveSize > 0) {
|
||
|
dwValue = 0;
|
||
|
memcpy(&dwValue, pBufferOffset, dwMoveSize);
|
||
|
Print("%0*lx", dwMoveSize * 2, dwValue);
|
||
|
}
|
||
|
Print("\n");
|
||
|
|
||
|
} while ((int)dwSize > 0);
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
} /* if (fOneField) */
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Printing all the fields.
|
||
|
*/
|
||
|
Print ("Structure %s - Size: %#lx\n", pst->pszName, pst->dwSize);
|
||
|
|
||
|
dwOffset = 0;
|
||
|
pBufferOffset = NULL; /* Forces the local buffer to be loaded */
|
||
|
dwFieldsPerRow = 0;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Loop through all fields in the table. Print one field per loop
|
||
|
*/
|
||
|
while (psot->pszField != NULL) {
|
||
|
/*
|
||
|
* Print two fields per row
|
||
|
*/
|
||
|
if (dwFieldsPerRow == 2) {
|
||
|
Print("\n");
|
||
|
dwFieldsPerRow = 1;
|
||
|
} else {
|
||
|
dwFieldsPerRow++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If no address provided, Print field name(s) and offset(s) only
|
||
|
*/
|
||
|
if (pAddress == NULL) {
|
||
|
Print("%03lx %-34.33s", dsoGetOffset(psot), psot->pszField);
|
||
|
} else {
|
||
|
/*
|
||
|
* Printing offsets and values.
|
||
|
*
|
||
|
* Get the size of the value and max it to one DWORD
|
||
|
*/
|
||
|
dwOffsetNext = dsoGetOffset(psot + 1);
|
||
|
if (dwOffsetNext > dwOffset) {
|
||
|
dwSize = dwOffsetNext - dwOffset;
|
||
|
} else {
|
||
|
dwSize = dsoGetSize(psot, dwOffset);
|
||
|
}
|
||
|
if (dwSize > sizeof(DWORD)) {
|
||
|
dwSize = sizeof(DWORD);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Get a pointer to the value in the local buffer
|
||
|
* If the value is not in the buffer, load it
|
||
|
*/
|
||
|
pdwValue = (PDWORD)(pBufferOffset + dwOffset);
|
||
|
if ((pdwValue < dwBuffer) || (pdwValue + dwSize > pcdwLimit)) {
|
||
|
pBufferOffset = (PBYTE)dwBuffer - dwOffset;
|
||
|
pdwValue = dwBuffer;
|
||
|
|
||
|
if (sizeof(dwBuffer) >= pst->dwSize - dwOffset) {
|
||
|
dwMoveSize = pst->dwSize - dwOffset;
|
||
|
} else {
|
||
|
dwMoveSize = sizeof(dwBuffer);
|
||
|
}
|
||
|
moveBlock((PBYTE)dwBuffer, (PBYTE)pAddress + dwOffset, dwMoveSize);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Copy the value and print it
|
||
|
*/
|
||
|
dwValue = 0; /* in case size < sizeof(DWORD) */
|
||
|
memcpy(&dwValue, pdwValue, dwSize);
|
||
|
Print("(%03lx) %08lx %-24.23s", dwOffset, dwValue, psot->pszField);
|
||
|
} /* if (pAddress == NULL) */
|
||
|
|
||
|
|
||
|
dwOffset = dwOffsetNext;
|
||
|
psot++;
|
||
|
|
||
|
} /* while (psot->pszField != NULL) */
|
||
|
|
||
|
Print("\n");
|
||
|
|
||
|
return TRUE;
|
||
|
}
|