1464 lines
35 KiB
C++
1464 lines
35 KiB
C++
|
|
|
|
//+============================================================================
|
|
//
|
|
// File: PropDump.cxx
|
|
//
|
|
// Purpose:
|
|
// This file contains routines to dump all the properties of all
|
|
// the property sets of a DocFile. It's started by calling
|
|
// DumpOleStorage().
|
|
//
|
|
//+============================================================================
|
|
|
|
// --------
|
|
// Includes
|
|
// --------
|
|
|
|
#include "pch.cxx"
|
|
|
|
|
|
// -------
|
|
// Globals
|
|
// -------
|
|
|
|
OLECHAR *oszDays[] =
|
|
{
|
|
OLESTR("Sun"),
|
|
OLESTR("Mon"),
|
|
OLESTR("Tue"),
|
|
OLESTR("Wed"),
|
|
OLESTR("Thu"),
|
|
OLESTR("Fri"),
|
|
OLESTR("Sat")
|
|
};
|
|
|
|
OLECHAR *oszMonths[] =
|
|
{
|
|
OLESTR("Jan"), OLESTR("Feb"), OLESTR("Mar"), OLESTR("Apr"), OLESTR("May"), OLESTR("Jun"),
|
|
OLESTR("Jul"), OLESTR("Aug"), OLESTR("Sep"), OLESTR("Oct"), OLESTR("Nov"), OLESTR("Dec")
|
|
};
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//+----------------------------------------------------------------------------
|
|
|
|
OLECHAR *
|
|
oszft(FILETIME *pft)
|
|
{
|
|
static OLECHAR oszbuf[32];
|
|
|
|
#ifdef _MAC
|
|
|
|
soprintf( oszbuf, OLESTR("%08X-%08X"), pft->dwHighDateTime, pft->dwLowDateTime );
|
|
|
|
#else
|
|
|
|
FILETIME ftlocal;
|
|
SYSTEMTIME st;
|
|
|
|
oszbuf[0] = '\0';
|
|
if (pft->dwHighDateTime != 0 || pft->dwLowDateTime != 0)
|
|
{
|
|
if (!FileTimeToLocalFileTime(pft, &ftlocal) ||
|
|
!FileTimeToSystemTime(&ftlocal, &st))
|
|
{
|
|
return(OLESTR("Time???"));
|
|
}
|
|
soprintf(
|
|
oszbuf,
|
|
OLESTR("%s %s %2d %2d:%02d:%02d %4d"),
|
|
oszDays[st.wDayOfWeek],
|
|
oszMonths[st.wMonth - 1],
|
|
st.wDay,
|
|
st.wHour,
|
|
st.wMinute,
|
|
st.wSecond,
|
|
st.wYear);
|
|
}
|
|
|
|
#endif
|
|
|
|
return(oszbuf);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpTime(OLECHAR *pozname, FILETIME *pft)
|
|
{
|
|
LARGE_INTEGER UNALIGNED *pli = (LARGE_INTEGER UNALIGNED *) pft;
|
|
|
|
ASYNC_PRINTF(
|
|
"%s%08lx:%08lx%hs%s\n",
|
|
pozname,
|
|
pli->HighPart,
|
|
pli->LowPart,
|
|
pli->QuadPart == 0? g_szEmpty : " - ",
|
|
oszft((FILETIME *) pft));
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintGuid(GUID *pguid)
|
|
{
|
|
ASYNC_PRINTF(
|
|
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
pguid->Data1,
|
|
pguid->Data2,
|
|
pguid->Data3,
|
|
pguid->Data4[0],
|
|
pguid->Data4[1],
|
|
pguid->Data4[2],
|
|
pguid->Data4[3],
|
|
pguid->Data4[4],
|
|
pguid->Data4[5],
|
|
pguid->Data4[6],
|
|
pguid->Data4[7]);
|
|
}
|
|
|
|
|
|
VOID
|
|
ListPropSetHeader(
|
|
STATPROPSETSTG *pspss,
|
|
OLECHAR *poszName)
|
|
{
|
|
BOOLEAN fDocumentSummarySection2;
|
|
OLECHAR oszStream[CCH_PROPSETSZ];
|
|
|
|
fDocumentSummarySection2 = (BOOLEAN)
|
|
memcmp(&pspss->fmtid, &FMTID_UserDefinedProperties, sizeof(GUID)) == 0;
|
|
|
|
ASYNC_PRINTF(" Property set ");
|
|
PrintGuid(&pspss->fmtid);
|
|
|
|
RtlGuidToPropertySetName(&pspss->fmtid, oszStream);
|
|
|
|
ASYNC_OPRINTF(
|
|
OLESTR("\n %hs Name %s"),
|
|
(pspss->grfFlags & PROPSETFLAG_NONSIMPLE)?
|
|
"Embedding" : "Stream",
|
|
oszStream);
|
|
if (poszName != NULL || fDocumentSummarySection2)
|
|
{
|
|
ASYNC_OPRINTF(
|
|
OLESTR(" (%s)"),
|
|
poszName != NULL? poszName : OLESTR("User defined properties"));
|
|
}
|
|
ASYNC_PRINTF("\n");
|
|
|
|
if (pspss->grfFlags & PROPSETFLAG_NONSIMPLE)
|
|
{
|
|
DumpTime(OLESTR(" Create Time "), &pspss->ctime);
|
|
}
|
|
DumpTime(OLESTR(" Modify Time "), &pspss->mtime);
|
|
if (pspss->grfFlags & PROPSETFLAG_NONSIMPLE)
|
|
{
|
|
DumpTime(OLESTR(" Access Time "), &pspss->atime);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef enum _PUBLICPROPSET
|
|
{
|
|
PUBPS_UNKNOWN = 0,
|
|
PUBPS_SUMMARYINFO = 3,
|
|
PUBPS_DOCSUMMARYINFO = 4,
|
|
PUBPS_USERDEFINED = 5,
|
|
} PUBLICPROPSET;
|
|
|
|
|
|
#define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1)
|
|
ULONG
|
|
SizeProp(PROPVARIANT *pv)
|
|
{
|
|
ULONG j;
|
|
ULONG cbprop = 0;
|
|
|
|
switch (pv->vt)
|
|
{
|
|
default:
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
break;
|
|
|
|
case VT_UI1:
|
|
cbprop = sizeof(pv->bVal);
|
|
break;
|
|
|
|
case VT_I2:
|
|
case VT_UI2:
|
|
case VT_BOOL:
|
|
cbprop = sizeof(pv->iVal);
|
|
break;
|
|
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
case VT_R4:
|
|
case VT_ERROR:
|
|
cbprop = sizeof(pv->lVal);
|
|
break;
|
|
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
case VT_R8:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_FILETIME:
|
|
cbprop = sizeof(pv->hVal);
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
cbprop = sizeof(*pv->puuid);
|
|
break;
|
|
|
|
case VT_BLOB_OBJECT:
|
|
case VT_BLOB:
|
|
cbprop = pv->blob.cbSize + sizeof(pv->blob.cbSize);
|
|
break;
|
|
|
|
case VT_CF:
|
|
cbprop = sizeof(pv->pclipdata->cbSize) +
|
|
pv->pclipdata->cbSize;
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
// count + string
|
|
cbprop = sizeof(ULONG);
|
|
if (pv->bstrVal != NULL)
|
|
{
|
|
cbprop += BSTRLEN(pv->bstrVal);
|
|
}
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
// count + string + null char
|
|
cbprop = sizeof(ULONG);
|
|
if (pv->pszVal != NULL)
|
|
{
|
|
cbprop += strlen(pv->pszVal) + 1;
|
|
}
|
|
break;
|
|
|
|
case VT_STREAM:
|
|
case VT_STREAMED_OBJECT:
|
|
case VT_STORAGE:
|
|
case VT_STORED_OBJECT:
|
|
case VT_LPWSTR:
|
|
// count + string + null char
|
|
cbprop = sizeof(ULONG);
|
|
if (pv->pwszVal != NULL)
|
|
{
|
|
cbprop += sizeof(pv->pwszVal[0]) * (wcslen(pv->pwszVal) + 1);
|
|
}
|
|
break;
|
|
|
|
// vectors
|
|
case VT_VECTOR | VT_UI1:
|
|
cbprop = sizeof(pv->caub.cElems) +
|
|
pv->caub.cElems * sizeof(pv->caub.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I2:
|
|
case VT_VECTOR | VT_UI2:
|
|
case VT_VECTOR | VT_BOOL:
|
|
cbprop = sizeof(pv->cai.cElems) +
|
|
pv->cai.cElems * sizeof(pv->cai.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I4:
|
|
case VT_VECTOR | VT_UI4:
|
|
case VT_VECTOR | VT_R4:
|
|
case VT_VECTOR | VT_ERROR:
|
|
cbprop = sizeof(pv->cal.cElems) +
|
|
pv->cal.cElems * sizeof(pv->cal.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I8:
|
|
case VT_VECTOR | VT_UI8:
|
|
case VT_VECTOR | VT_R8:
|
|
case VT_VECTOR | VT_CY:
|
|
case VT_VECTOR | VT_DATE:
|
|
case VT_VECTOR | VT_FILETIME:
|
|
cbprop = sizeof(pv->cah.cElems) +
|
|
pv->cah.cElems * sizeof(pv->cah.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CLSID:
|
|
cbprop = sizeof(pv->cauuid.cElems) +
|
|
pv->cauuid.cElems * sizeof(pv->cauuid.pElems[0]);
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
cbprop = sizeof(pv->caclipdata.cElems);
|
|
for (j = 0; j < pv->caclipdata.cElems; j++)
|
|
{
|
|
cbprop += sizeof(pv->caclipdata.pElems[j].cbSize) +
|
|
DwordAlign(pv->caclipdata.pElems[j].cbSize);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
cbprop = sizeof(pv->cabstr.cElems);
|
|
for (j = 0; j < pv->cabstr.cElems; j++)
|
|
{
|
|
// count + string + null char
|
|
cbprop += sizeof(ULONG);
|
|
if (pv->cabstr.pElems[j] != NULL)
|
|
{
|
|
cbprop += DwordAlign(BSTRLEN(pv->cabstr.pElems[j]));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_LPSTR:
|
|
cbprop = sizeof(pv->calpstr.cElems);
|
|
for (j = 0; j < pv->calpstr.cElems; j++)
|
|
{
|
|
// count + string + null char
|
|
cbprop += sizeof(ULONG);
|
|
if (pv->calpstr.pElems[j] != NULL)
|
|
{
|
|
cbprop += DwordAlign(strlen(pv->calpstr.pElems[j]) + 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
cbprop = sizeof(pv->calpwstr.cElems);
|
|
for (j = 0; j < pv->calpwstr.cElems; j++)
|
|
{
|
|
// count + string + null char
|
|
cbprop += sizeof(ULONG);
|
|
if (pv->calpwstr.pElems[j] != NULL)
|
|
{
|
|
cbprop += DwordAlign(
|
|
sizeof(pv->calpwstr.pElems[j][0]) *
|
|
(wcslen(pv->calpwstr.pElems[j]) + 1));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
cbprop = sizeof(pv->calpwstr.cElems);
|
|
for (j = 0; j < pv->calpwstr.cElems; j++)
|
|
{
|
|
cbprop += SizeProp(&pv->capropvar.pElems[j]);
|
|
}
|
|
break;
|
|
}
|
|
return(DwordAlign(cbprop) + DwordAlign(sizeof(pv->vt)));
|
|
}
|
|
|
|
|
|
PUBLICPROPSET
|
|
GuidToPropSet(GUID *pguid)
|
|
{
|
|
PUBLICPROPSET pubps = PUBPS_UNKNOWN;
|
|
|
|
if (pguid != NULL)
|
|
{
|
|
if (memcmp(pguid, &FMTID_SummaryInformation, sizeof(GUID)) == 0)
|
|
{
|
|
pubps = PUBPS_SUMMARYINFO;
|
|
}
|
|
else if (memcmp(pguid, &FMTID_DocSummaryInformation, sizeof(GUID)) == 0)
|
|
{
|
|
pubps = PUBPS_DOCSUMMARYINFO;
|
|
}
|
|
else if (memcmp(pguid, &FMTID_UserDefinedProperties, sizeof(GUID)) == 0)
|
|
{
|
|
pubps = PUBPS_USERDEFINED;
|
|
}
|
|
}
|
|
return(pubps);
|
|
}
|
|
|
|
|
|
char
|
|
PrintableChar(char ch)
|
|
{
|
|
if (ch < ' ' || ch > '~')
|
|
{
|
|
ch = '.';
|
|
}
|
|
return(ch);
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpHex(BYTE *pb, ULONG cb, ULONG base)
|
|
{
|
|
char *pszsep;
|
|
ULONG r, i, cbremain;
|
|
int fZero = FALSE;
|
|
int fSame = FALSE;
|
|
|
|
for (r = 0; r < cb; r += 16)
|
|
{
|
|
cbremain = cb - r;
|
|
if (r != 0 && cbremain >= 16)
|
|
{
|
|
if (pb[r] == 0)
|
|
{
|
|
ULONG j;
|
|
|
|
for (j = r + 1; j < cb; j++)
|
|
{
|
|
if (pb[j] != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (j == cb)
|
|
{
|
|
fZero = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (memcmp(&pb[r], &pb[r - 16], 16) == 0)
|
|
{
|
|
fSame = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
if (fSame)
|
|
{
|
|
ASYNC_PRINTF("\n\t *");
|
|
fSame = FALSE;
|
|
}
|
|
for (i = 0; i < min(cbremain, 16); i++)
|
|
{
|
|
pszsep = " ";
|
|
if ((i % 8) == 0) // 0 or 8
|
|
{
|
|
pszsep = " ";
|
|
if (i == 0) // 0
|
|
{
|
|
// start a new line
|
|
ASYNC_PRINTF("%s %04x:", r == 0? "" : "\n", r + base);
|
|
pszsep = " ";
|
|
}
|
|
}
|
|
ASYNC_PRINTF("%s%02x", pszsep, pb[r + i]);
|
|
}
|
|
if (i != 0)
|
|
{
|
|
ASYNC_PRINTF("%*s", 3 + (16 - i)*3 + ((i <= 8)? 1 : 0), "");
|
|
for (i = 0; i < min(cbremain, 16); i++)
|
|
{
|
|
ASYNC_PRINTF("%c", PrintableChar(pb[r + i]));
|
|
}
|
|
}
|
|
}
|
|
if (r != 0)
|
|
{
|
|
ASYNC_PRINTF("\n");
|
|
}
|
|
if (fZero)
|
|
{
|
|
ASYNC_PRINTF(" Remaining %lx bytes are zero\n", cbremain);
|
|
}
|
|
}
|
|
|
|
|
|
// Property Id's for Summary Info
|
|
#define PID_TITLE 0x00000002L // VT_LPSTR
|
|
#define PID_SUBJECT 0x00000003L // VT_LPSTR
|
|
#define PID_AUTHOR 0x00000004L // VT_LPSTR
|
|
#define PID_KEYWORDS 0x00000005L // VT_LPSTR
|
|
#define PID_COMMENTS 0x00000006L // VT_LPSTR
|
|
#define PID_TEMPLATE 0x00000007L // VT_LPSTR
|
|
#define PID_LASTAUTHOR 0x00000008L // VT_LPSTR
|
|
#define PID_REVNUMBER 0x00000009L // VT_LPSTR
|
|
#define PID_EDITTIME 0x0000000aL // VT_FILETIME
|
|
#define PID_LASTPRINTED 0x0000000bL // VT_FILETIME
|
|
#define PID_CREATE_DTM 0x0000000cL // VT_FILETIME
|
|
#define PID_LASTSAVE_DTM 0x0000000dL // VT_FILETIME
|
|
#define PID_PAGECOUNT 0x0000000eL // VT_I4
|
|
#define PID_WORDCOUNT 0x0000000fL // VT_I4
|
|
#define PID_CHARCOUNT 0x00000010L // VT_I4
|
|
#define PID_THUMBNAIL 0x00000011L // VT_CF
|
|
#define PID_APPNAME 0x00000012L // VT_LPSTR
|
|
#define PID_SECURITY_DSI 0x00000013L // VT_I4
|
|
|
|
// Property Id's for Document Summary Info
|
|
#define PID_CATEGORY 0x00000002L // VT_LPSTR
|
|
#define PID_PRESFORMAT 0x00000003L // VT_LPSTR
|
|
#define PID_BYTECOUNT 0x00000004L // VT_I4
|
|
#define PID_LINECOUNT 0x00000005L // VT_I4
|
|
#define PID_PARACOUNT 0x00000006L // VT_I4
|
|
#define PID_SLIDECOUNT 0x00000007L // VT_I4
|
|
#define PID_NOTECOUNT 0x00000008L // VT_I4
|
|
#define PID_HIDDENCOUNT 0x00000009L // VT_I4
|
|
#define PID_MMCLIPCOUNT 0x0000000aL // VT_I4
|
|
#define PID_SCALE 0x0000000bL // VT_BOOL
|
|
#define PID_HEADINGPAIR 0x0000000cL // VT_VECTOR | VT_VARIANT
|
|
#define PID_DOCPARTS 0x0000000dL // VT_VECTOR | VT_LPSTR
|
|
#define PID_MANAGER 0x0000000eL // VT_LPSTR
|
|
#define PID_COMPANY 0x0000000fL // VT_LPSTR
|
|
#define PID_LINKSDIRTY 0x00000010L // VT_BOOL
|
|
#define PID_CCHWITHSPACES 0x00000011L // VT_I4
|
|
#define PID_GUID 0x00000012L // VT_LPSTR
|
|
#define PID_SHAREDDOC 0x00000013L // VT_BOOL
|
|
#define PID_LINKBASE 0x00000014L // VT_LPSTR
|
|
#define PID_HLINKS 0x00000015L // VT_VECTOR | VT_VARIANT
|
|
#define PID_HYPERLINKSCHANGED 0x00000016L // VT_BOOL
|
|
|
|
|
|
VOID
|
|
DisplayProps(
|
|
GUID *pguid,
|
|
ULONG cprop,
|
|
PROPID apid[],
|
|
STATPROPSTG asps[],
|
|
PROPVARIANT *av,
|
|
BOOLEAN fsumcat,
|
|
ULONG *pcbprop)
|
|
{
|
|
PROPVARIANT *pv;
|
|
PROPVARIANT *pvend;
|
|
STATPROPSTG *psps;
|
|
BOOLEAN fVariantVector;
|
|
PUBLICPROPSET pubps;
|
|
|
|
fVariantVector = (asps == NULL);
|
|
|
|
pubps = GuidToPropSet(pguid);
|
|
pvend = &av[cprop];
|
|
for (pv = av, psps = asps; pv < pvend; pv++, psps++)
|
|
{
|
|
ULONG j;
|
|
ULONG cbprop;
|
|
PROPID propid;
|
|
OLECHAR *postrName;
|
|
char *psz;
|
|
BOOLEAN fNewLine = TRUE;
|
|
int ccol;
|
|
static char szNoFormat[] = " (no display format)";
|
|
char achvt[19 + 8 + 1];
|
|
|
|
cbprop = SizeProp(pv);
|
|
*pcbprop += cbprop;
|
|
|
|
postrName = NULL;
|
|
if (asps != NULL)
|
|
{
|
|
propid = psps->propid;
|
|
postrName = psps->lpwstrName;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(apid != NULL);
|
|
propid = apid[0];
|
|
}
|
|
|
|
ASYNC_PRINTF(" ");
|
|
ccol = 0;
|
|
|
|
if (propid != PID_ILLEGAL)
|
|
{
|
|
ASYNC_PRINTF(" %04x", propid);
|
|
ccol += 5;
|
|
if (propid & (0xf << 28))
|
|
{
|
|
ccol += 4;
|
|
}
|
|
else if (propid & (0xf << 24))
|
|
{
|
|
ccol += 3;
|
|
}
|
|
else if (propid & (0xf << 20))
|
|
{
|
|
ccol += 2;
|
|
}
|
|
else if (propid & (0xf << 16))
|
|
{
|
|
ccol++;
|
|
}
|
|
}
|
|
if (postrName != NULL)
|
|
{
|
|
ASYNC_OPRINTF(OLESTR(" '%s'"), postrName);
|
|
ccol += ocslen(postrName) + 3;
|
|
}
|
|
else if (fVariantVector)
|
|
{
|
|
ULONG i = (ULONG) ((ULONG_PTR)pv - (ULONG_PTR)av);
|
|
|
|
ASYNC_PRINTF("[%x]", i);
|
|
do
|
|
{
|
|
ccol++;
|
|
i >>= 4;
|
|
} while (i != 0);
|
|
ccol += 2;
|
|
}
|
|
else
|
|
{
|
|
psz = NULL;
|
|
|
|
switch (propid)
|
|
{
|
|
case PID_LOCALE: psz = "Locale"; break;
|
|
case PID_SECURITY: psz = "SecurityId"; break;
|
|
case PID_MODIFY_TIME: psz = "ModifyTime"; break;
|
|
case PID_CODEPAGE: psz = "CodePage"; break;
|
|
case PID_DICTIONARY: psz = "Dictionary"; break;
|
|
}
|
|
if (psz == NULL)
|
|
switch (pubps)
|
|
{
|
|
case PUBPS_SUMMARYINFO:
|
|
switch (propid)
|
|
{
|
|
case PID_TITLE: psz = "Title"; break;
|
|
case PID_SUBJECT: psz = "Subject"; break;
|
|
case PID_AUTHOR: psz = "Author"; break;
|
|
case PID_KEYWORDS: psz = "Keywords"; break;
|
|
case PID_COMMENTS: psz = "Comments"; break;
|
|
case PID_TEMPLATE: psz = "Template"; break;
|
|
case PID_LASTAUTHOR: psz = "LastAuthor"; break;
|
|
case PID_REVNUMBER: psz = "RevNumber"; break;
|
|
case PID_EDITTIME: psz = "EditTime"; break;
|
|
case PID_LASTPRINTED: psz = "LastPrinted"; break;
|
|
case PID_CREATE_DTM: psz = "CreateDateTime"; break;
|
|
case PID_LASTSAVE_DTM: psz = "LastSaveDateTime";break;
|
|
case PID_PAGECOUNT: psz = "PageCount"; break;
|
|
case PID_WORDCOUNT: psz = "WordCount"; break;
|
|
case PID_CHARCOUNT: psz = "CharCount"; break;
|
|
case PID_THUMBNAIL: psz = "ThumbNail"; break;
|
|
case PID_APPNAME: psz = "AppName"; break;
|
|
case PID_DOC_SECURITY: psz = "Security"; break;
|
|
|
|
}
|
|
break;
|
|
|
|
case PUBPS_DOCSUMMARYINFO:
|
|
switch (propid)
|
|
{
|
|
case PID_CATEGORY: psz = "Category"; break;
|
|
case PID_PRESFORMAT: psz = "PresFormat"; break;
|
|
case PID_BYTECOUNT: psz = "ByteCount"; break;
|
|
case PID_LINECOUNT: psz = "LineCount"; break;
|
|
case PID_PARACOUNT: psz = "ParaCount"; break;
|
|
case PID_SLIDECOUNT: psz = "SlideCount"; break;
|
|
case PID_NOTECOUNT: psz = "NoteCount"; break;
|
|
case PID_HIDDENCOUNT: psz = "HiddenCount"; break;
|
|
case PID_MMCLIPCOUNT: psz = "MmClipCount"; break;
|
|
case PID_SCALE: psz = "Scale"; break;
|
|
case PID_HEADINGPAIR: psz = "HeadingPair"; break;
|
|
case PID_DOCPARTS: psz = "DocParts"; break;
|
|
case PID_MANAGER: psz = "Manager"; break;
|
|
case PID_COMPANY: psz = "Company"; break;
|
|
case PID_LINKSDIRTY: psz = "LinksDirty"; break;
|
|
case PID_CCHWITHSPACES: psz = "CchWithSpaces"; break;
|
|
case PID_GUID: psz = "Guid"; break;
|
|
case PID_SHAREDDOC: psz = "SharedDoc"; break;
|
|
case PID_LINKBASE: psz = "LinkBase"; break;
|
|
case PID_HLINKS: psz = "HLinks"; break;
|
|
case PID_HYPERLINKSCHANGED: psz = "HyperLinksChanged";break;
|
|
}
|
|
break;
|
|
}
|
|
if (psz != NULL)
|
|
{
|
|
ASYNC_PRINTF(" %s", psz);
|
|
ccol += strlen(psz) + 1;
|
|
}
|
|
}
|
|
#define CCOLPROPID 20
|
|
if (ccol != CCOLPROPID)
|
|
{
|
|
if (ccol > CCOLPROPID)
|
|
{
|
|
ccol = -1;
|
|
}
|
|
ASYNC_PRINTF("%s%*s", ccol == -1? "\n" : "", CCOLPROPID - ccol, "");
|
|
}
|
|
ASYNC_PRINTF(" %08x %04x %04x ", propid, cbprop, pv->vt);
|
|
|
|
psz = "";
|
|
switch (pv->vt)
|
|
{
|
|
default:
|
|
psz = achvt;
|
|
sprintf(psz, "Unknown (vt = %hx)", pv->vt);
|
|
break;
|
|
|
|
case VT_EMPTY:
|
|
ASYNC_PRINTF("EMPTY");
|
|
break;
|
|
|
|
case VT_NULL:
|
|
ASYNC_PRINTF("NULL");
|
|
break;
|
|
|
|
case VT_UI1:
|
|
ASYNC_PRINTF("UI1 = %02lx", pv->bVal);
|
|
psz = "";
|
|
break;
|
|
|
|
case VT_I2:
|
|
psz = "I2";
|
|
goto doshort;
|
|
|
|
case VT_UI2:
|
|
psz = "UI2";
|
|
goto doshort;
|
|
|
|
case VT_BOOL:
|
|
psz = "BOOL";
|
|
doshort:
|
|
ASYNC_PRINTF("%s = %04hx", psz, pv->iVal);
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_I4:
|
|
psz = "I4";
|
|
goto dolong;
|
|
|
|
case VT_UI4:
|
|
psz = "UI4";
|
|
goto dolong;
|
|
|
|
case VT_R4:
|
|
psz = "R4";
|
|
goto dolong;
|
|
|
|
case VT_ERROR:
|
|
psz = "ERROR";
|
|
dolong:
|
|
ASYNC_PRINTF("%s = %08lx", psz, pv->lVal);
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_I8:
|
|
psz = "I8";
|
|
goto dolonglong;
|
|
|
|
case VT_UI8:
|
|
psz = "UI8";
|
|
goto dolonglong;
|
|
|
|
case VT_R8:
|
|
psz = "R8";
|
|
goto dolonglong;
|
|
|
|
case VT_CY:
|
|
psz = "R8";
|
|
goto dolonglong;
|
|
|
|
case VT_DATE:
|
|
psz = "R8";
|
|
dolonglong:
|
|
ASYNC_PRINTF(
|
|
"%s = %08lx:%08lx",
|
|
psz,
|
|
pv->hVal.HighPart,
|
|
pv->hVal.LowPart);
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_FILETIME:
|
|
DumpTime(OLESTR("FILETIME =\n\t "), &pv->filetime);
|
|
fNewLine = FALSE; // skip newline printf
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
ASYNC_PRINTF("CLSID =\n\t ");
|
|
PrintGuid(pv->puuid);
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
psz = "BLOB";
|
|
goto doblob;
|
|
|
|
case VT_BLOB_OBJECT:
|
|
psz = "BLOB_OBJECT";
|
|
doblob:
|
|
ASYNC_PRINTF("%s (cbSize %x)", psz, pv->blob.cbSize);
|
|
if (pv->blob.cbSize != 0)
|
|
{
|
|
ASYNC_PRINTF(" =\n");
|
|
DumpHex(pv->blob.pBlobData, pv->blob.cbSize, 0);
|
|
}
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_CF:
|
|
ASYNC_PRINTF(
|
|
"CF (cbSize %x, ulClipFmt %x)\n",
|
|
pv->pclipdata->cbSize,
|
|
pv->pclipdata->ulClipFmt);
|
|
DumpHex(pv->pclipdata->pClipData,
|
|
pv->pclipdata->cbSize - sizeof(pv->pclipdata->ulClipFmt),
|
|
0);
|
|
break;
|
|
|
|
case VT_STREAM:
|
|
psz = "STREAM";
|
|
goto dostring;
|
|
|
|
case VT_STREAMED_OBJECT:
|
|
psz = "STREAMED_OBJECT";
|
|
goto dostring;
|
|
|
|
case VT_STORAGE:
|
|
psz = "STORAGE";
|
|
goto dostring;
|
|
|
|
case VT_STORED_OBJECT:
|
|
psz = "STORED_OBJECT";
|
|
goto dostring;
|
|
|
|
case VT_BSTR:
|
|
ASYNC_PRINTF(
|
|
"BSTR (cb = %04lx)%s\n",
|
|
pv->bstrVal == NULL? 0 : BSTRLEN(pv->bstrVal),
|
|
pv->bstrVal == NULL? " NULL" : g_szEmpty);
|
|
if (pv->bstrVal != NULL)
|
|
{
|
|
DumpHex(
|
|
(BYTE *) pv->bstrVal,
|
|
BSTRLEN(pv->bstrVal) + sizeof(WCHAR),
|
|
0);
|
|
}
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
psz = "LPSTR";
|
|
ASYNC_PRINTF(
|
|
"%s = %s%s%s",
|
|
psz,
|
|
pv->pszVal == NULL? g_szEmpty : "'",
|
|
pv->pszVal == NULL? "NULL" : pv->pszVal,
|
|
pv->pszVal == NULL? g_szEmpty : "'");
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
psz = "LPWSTR";
|
|
dostring:
|
|
ASYNC_PRINTF(
|
|
"%s = %s%ws%s",
|
|
psz,
|
|
pv->pwszVal == NULL? g_szEmpty : "'",
|
|
pv->pwszVal == NULL? L"NULL" : pv->pwszVal,
|
|
pv->pwszVal == NULL? g_szEmpty : "'");
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
// vectors
|
|
|
|
case VT_VECTOR | VT_UI1:
|
|
ASYNC_PRINTF("UI1[%x] =", pv->caub.cElems);
|
|
for (j = 0; j < pv->caub.cElems; j++)
|
|
{
|
|
if ((j % 16) == 0)
|
|
{
|
|
ASYNC_PRINTF("\n %02hx:", j);
|
|
}
|
|
ASYNC_PRINTF(" %02hx", pv->caub.pElems[j]);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I2:
|
|
psz = "I2";
|
|
goto doshortvector;
|
|
|
|
case VT_VECTOR | VT_UI2:
|
|
psz = "UI2";
|
|
goto doshortvector;
|
|
|
|
case VT_VECTOR | VT_BOOL:
|
|
psz = "BOOL";
|
|
doshortvector:
|
|
ASYNC_PRINTF("%s[%x] =", psz, pv->cai.cElems);
|
|
for (j = 0; j < pv->cai.cElems; j++)
|
|
{
|
|
if ((j % 8) == 0)
|
|
{
|
|
ASYNC_PRINTF("\n %04hx:", j);
|
|
}
|
|
ASYNC_PRINTF(" %04hx", pv->cai.pElems[j]);
|
|
}
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I4:
|
|
psz = "I4";
|
|
goto dolongvector;
|
|
|
|
case VT_VECTOR | VT_UI4:
|
|
psz = "UI4";
|
|
goto dolongvector;
|
|
|
|
case VT_VECTOR | VT_R4:
|
|
psz = "R4";
|
|
goto dolongvector;
|
|
|
|
case VT_VECTOR | VT_ERROR:
|
|
psz = "ERROR";
|
|
dolongvector:
|
|
ASYNC_PRINTF("%s[%x] =", psz, pv->cal.cElems);
|
|
for (j = 0; j < pv->cal.cElems; j++)
|
|
{
|
|
if ((j % 4) == 0)
|
|
{
|
|
ASYNC_PRINTF("\n %04x:", j);
|
|
}
|
|
ASYNC_PRINTF(" %08lx", pv->cal.pElems[j]);
|
|
}
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_I8:
|
|
psz = "I8";
|
|
goto dolonglongvector;
|
|
|
|
case VT_VECTOR | VT_UI8:
|
|
psz = "UI8";
|
|
goto dolonglongvector;
|
|
|
|
case VT_VECTOR | VT_R8:
|
|
psz = "R8";
|
|
goto dolonglongvector;
|
|
|
|
case VT_VECTOR | VT_CY:
|
|
psz = "CY";
|
|
goto dolonglongvector;
|
|
|
|
case VT_VECTOR | VT_DATE:
|
|
psz = "DATE";
|
|
dolonglongvector:
|
|
ASYNC_PRINTF("%s[%x] =", psz, pv->cah.cElems);
|
|
for (j = 0; j < pv->cah.cElems; j++)
|
|
{
|
|
if ((j % 2) == 0)
|
|
{
|
|
ASYNC_PRINTF("\n %04x:", j);
|
|
}
|
|
ASYNC_PRINTF(
|
|
" %08lx:%08lx",
|
|
pv->cah.pElems[j].HighPart,
|
|
pv->cah.pElems[j].LowPart);
|
|
}
|
|
psz = g_szEmpty;
|
|
break;
|
|
|
|
case VT_VECTOR | VT_FILETIME:
|
|
ASYNC_PRINTF("FILETIME[%x] =\n", pv->cafiletime.cElems);
|
|
for (j = 0; j < pv->cafiletime.cElems; j++)
|
|
{
|
|
ASYNC_PRINTF(" %04x: ", j);
|
|
DumpTime(OLESTR(""), &pv->cafiletime.pElems[j]);
|
|
}
|
|
fNewLine = FALSE; // skip newline printf
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CLSID:
|
|
ASYNC_PRINTF("CLSID[%x] =", pv->cauuid.cElems);
|
|
for (j = 0; j < pv->cauuid.cElems; j++)
|
|
{
|
|
ASYNC_PRINTF("\n %04x: ", j);
|
|
PrintGuid(&pv->cauuid.pElems[j]);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_CF:
|
|
ASYNC_PRINTF("CF[%x] =", pv->caclipdata.cElems);
|
|
for (j = 0; j < pv->caclipdata.cElems; j++)
|
|
{
|
|
ASYNC_PRINTF("\n %04x: (cbSize %x, ulClipFmt %x) =\n",
|
|
j,
|
|
pv->caclipdata.pElems[j].cbSize,
|
|
pv->caclipdata.pElems[j].ulClipFmt);
|
|
DumpHex(
|
|
pv->caclipdata.pElems[j].pClipData,
|
|
pv->caclipdata.pElems[j].cbSize - sizeof(pv->caclipdata.pElems[j].ulClipFmt),
|
|
0);
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_BSTR:
|
|
ASYNC_PRINTF("BSTR[%x] =", pv->cabstr.cElems);
|
|
for (j = 0; j < pv->cabstr.cElems; j++)
|
|
{
|
|
BSTR bstr = pv->cabstr.pElems[j];
|
|
|
|
ASYNC_PRINTF(
|
|
"\n %04x: cb = %04lx%s\n",
|
|
j,
|
|
bstr == NULL? 0 : BSTRLEN(pv->cabstr.pElems[j]),
|
|
bstr == NULL? " NULL" : g_szEmpty);
|
|
if (bstr != NULL)
|
|
{
|
|
DumpHex((BYTE *) bstr, BSTRLEN(bstr) + sizeof(WCHAR), 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_LPSTR:
|
|
ASYNC_PRINTF("LPSTR[%x] =", pv->calpstr.cElems);
|
|
for (j = 0; j < pv->calpstr.cElems; j++)
|
|
{
|
|
CHAR *psz = pv->calpstr.pElems[j];
|
|
|
|
ASYNC_PRINTF(
|
|
"\n %04x: %s%s%s",
|
|
j,
|
|
psz == NULL? g_szEmpty : "'",
|
|
psz == NULL? "NULL" : psz,
|
|
psz == NULL? g_szEmpty : "'");
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_LPWSTR:
|
|
ASYNC_PRINTF("LPWSTR[%x] =", pv->calpwstr.cElems);
|
|
for (j = 0; j < pv->calpwstr.cElems; j++)
|
|
{
|
|
WCHAR *pwsz = pv->calpwstr.pElems[j];
|
|
|
|
ASYNC_PRINTF(
|
|
"\n %04x: %s%ws%s",
|
|
j,
|
|
pwsz == NULL? g_szEmpty : "'",
|
|
pwsz == NULL? L"NULL" : pwsz,
|
|
pwsz == NULL? g_szEmpty : "'");
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR | VT_VARIANT:
|
|
ASYNC_PRINTF("VARIANT[%x] =\n", pv->capropvar.cElems);
|
|
DisplayProps(
|
|
pguid,
|
|
pv->capropvar.cElems,
|
|
&propid,
|
|
NULL,
|
|
pv->capropvar.pElems,
|
|
fsumcat,
|
|
pcbprop);
|
|
fNewLine = FALSE; // skip newline printf
|
|
break;
|
|
}
|
|
if (*psz != '\0')
|
|
{
|
|
ASYNC_PRINTF("%s", psz);
|
|
if (pv->vt & VT_VECTOR)
|
|
{
|
|
ASYNC_PRINTF("[%x]", pv->cal.cElems);
|
|
}
|
|
ASYNC_PRINTF("%s", szNoFormat);
|
|
}
|
|
if (!fVariantVector && apid != NULL && apid[pv - av] != propid)
|
|
{
|
|
ASYNC_PRINTF(" (bad PROPID: %04x)", apid[pv - av]);
|
|
fNewLine = TRUE;
|
|
}
|
|
if (asps != NULL && pv->vt != psps->vt)
|
|
{
|
|
ASYNC_PRINTF(" (bad STATPROPSTG VARTYPE: %04x)", psps->vt);
|
|
fNewLine = TRUE;
|
|
}
|
|
if (fNewLine)
|
|
{
|
|
ASYNC_PRINTF("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
STATPROPSTG aspsStatic[] = {
|
|
{ NULL, PID_CODEPAGE, VT_I2 },
|
|
{ NULL, PID_MODIFY_TIME, VT_FILETIME },
|
|
{ NULL, PID_SECURITY, VT_UI4 },
|
|
};
|
|
#define CPROPSTATIC (sizeof(aspsStatic)/sizeof(aspsStatic[0]))
|
|
|
|
|
|
#define CB_STREAM_OVERHEAD 28
|
|
#define CB_PROPSET_OVERHEAD (CB_STREAM_OVERHEAD + 8)
|
|
#define CB_PROP_OVERHEAD 8
|
|
|
|
HRESULT
|
|
DumpOlePropertySet(
|
|
IPropertySetStorage *ppsstg,
|
|
STATPROPSETSTG *pspss,
|
|
ULONG *pcprop,
|
|
ULONG *pcbprop)
|
|
{
|
|
HRESULT hr;
|
|
IEnumSTATPROPSTG *penumsps = NULL;
|
|
IPropertyStorage *pps;
|
|
ULONG cprop, cbpropset;
|
|
PROPID propid;
|
|
OLECHAR *poszName;
|
|
ULONG ispsStatic;
|
|
|
|
*pcprop = *pcbprop = 0;
|
|
|
|
hr = ppsstg->Open(
|
|
pspss->fmtid,
|
|
STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
|
|
&pps);
|
|
|
|
if( FAILED(hr) )
|
|
return(hr);
|
|
|
|
propid = PID_DICTIONARY;
|
|
|
|
hr = pps->ReadPropertyNames(1, &propid, &poszName);
|
|
if( (HRESULT) S_FALSE == hr )
|
|
hr = S_OK;
|
|
Check( S_OK, hr );
|
|
|
|
ListPropSetHeader(pspss, poszName);
|
|
if (poszName != NULL)
|
|
{
|
|
CoTaskMemFree(poszName);
|
|
}
|
|
|
|
cprop = cbpropset = 0;
|
|
|
|
Check(S_OK, pps->Enum(&penumsps) );
|
|
|
|
ispsStatic = 0;
|
|
hr = S_OK;
|
|
while (hr == S_OK)
|
|
{
|
|
STATPROPSTG sps;
|
|
PROPSPEC propspec;
|
|
PROPVARIANT propvar;
|
|
ULONG count;
|
|
|
|
hr = (HRESULT) S_FALSE;
|
|
if (ispsStatic == 0)
|
|
{
|
|
hr = penumsps->Next(1, &sps, &count);
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
if (hr == (HRESULT) S_FALSE)
|
|
{
|
|
hr = S_OK;
|
|
if (ispsStatic >= CPROPSTATIC)
|
|
{
|
|
break;
|
|
}
|
|
sps = aspsStatic[ispsStatic];
|
|
ispsStatic++;
|
|
count = 1;
|
|
}
|
|
Check( S_OK, hr );
|
|
}
|
|
PropVariantInit(&propvar);
|
|
if (sps.lpwstrName != NULL)
|
|
{
|
|
propspec.ulKind = PRSPEC_LPWSTR;
|
|
propspec.lpwstr = sps.lpwstrName;
|
|
}
|
|
else
|
|
{
|
|
propspec.ulKind = PRSPEC_PROPID;
|
|
propspec.propid = sps.propid;
|
|
}
|
|
|
|
hr = pps->ReadMultiple(1, &propspec, &propvar);
|
|
if (hr == (HRESULT) S_FALSE)
|
|
{
|
|
if (g_fVerbose)
|
|
{
|
|
ASYNC_PRINTF(
|
|
"%s(%u, %x) vt=%x returned hr=%x\n",
|
|
"IPropertyStorage::ReadMultiple",
|
|
ispsStatic,
|
|
propspec.propid,
|
|
propvar.vt,
|
|
hr);
|
|
}
|
|
ASSERT(propvar.vt == VT_EMPTY);
|
|
hr = S_OK;
|
|
}
|
|
Check( S_OK, hr );
|
|
|
|
if (ispsStatic == 0 || propvar.vt != VT_EMPTY)
|
|
{
|
|
ASSERT(count == 1);
|
|
cprop += count;
|
|
if (cprop == 1)
|
|
{
|
|
ASYNC_PRINTF(g_szPropHeader);
|
|
}
|
|
|
|
DisplayProps(
|
|
&pspss->fmtid,
|
|
1,
|
|
NULL,
|
|
&sps,
|
|
&propvar,
|
|
FALSE,
|
|
&cbpropset);
|
|
g_pfnPropVariantClear(&propvar);
|
|
}
|
|
if (sps.lpwstrName != NULL)
|
|
{
|
|
CoTaskMemFree(sps.lpwstrName);
|
|
}
|
|
}
|
|
if (penumsps != NULL)
|
|
{
|
|
penumsps->Release();
|
|
}
|
|
pps->Release();
|
|
if (cprop != 0)
|
|
{
|
|
cbpropset += CB_PROPSET_OVERHEAD + cprop * CB_PROP_OVERHEAD;
|
|
ASYNC_PRINTF(" %04x bytes in %u properties\n\n", cbpropset, cprop);
|
|
}
|
|
*pcprop = cprop;
|
|
*pcbprop = cbpropset;
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
DumpOlePropertySets(
|
|
IStorage *pstg,
|
|
IPropertySetStorage *pIPropSetStorage,
|
|
OLECHAR *aocpath)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
IPropertySetStorage *ppsstg = pIPropSetStorage;
|
|
ULONG cbproptotal = 0;
|
|
ULONG cproptotal = 0;
|
|
ULONG cpropset = 0;
|
|
IID IIDpsstg = IID_IPropertySetStorage;
|
|
|
|
if (ppsstg == NULL)
|
|
{
|
|
Check(S_OK, StgToPropSetStg( pstg, &ppsstg ));
|
|
}
|
|
|
|
{
|
|
IEnumSTATPROPSETSTG *penumspss = NULL;
|
|
|
|
Check(S_OK, ppsstg->Enum(&penumspss) );
|
|
|
|
while (hr == S_OK)
|
|
{
|
|
STATPROPSETSTG spss;
|
|
ULONG count;
|
|
BOOLEAN fDocumentSummarySection2;
|
|
|
|
hr = penumspss->Next(1, &spss, &count);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
if (hr == (HRESULT) S_FALSE)
|
|
{
|
|
hr = (HRESULT) S_OK;
|
|
}
|
|
|
|
Check( (HRESULT) S_OK, hr );
|
|
break;
|
|
}
|
|
ASSERT(count == 1);
|
|
|
|
fDocumentSummarySection2 = FALSE;
|
|
while (TRUE)
|
|
{
|
|
ULONG cprop, cbprop;
|
|
HRESULT hr;
|
|
|
|
hr = DumpOlePropertySet(
|
|
ppsstg,
|
|
&spss,
|
|
&cprop,
|
|
&cbprop);
|
|
|
|
if( (HRESULT) STG_E_FILENOTFOUND == hr
|
|
&&
|
|
fDocumentSummarySection2 )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
cpropset++;
|
|
cproptotal += cprop;
|
|
cbproptotal += cbprop;
|
|
|
|
if (memcmp(&spss.fmtid, &FMTID_DocSummaryInformation, sizeof(FMTID)))
|
|
{
|
|
break;
|
|
}
|
|
spss.fmtid = FMTID_UserDefinedProperties;
|
|
fDocumentSummarySection2 = TRUE;
|
|
}
|
|
}
|
|
|
|
if (penumspss != NULL)
|
|
{
|
|
penumspss->Release();
|
|
}
|
|
ppsstg->Release();
|
|
}
|
|
if ((cbproptotal | cproptotal | cpropset) != 0)
|
|
{
|
|
ASYNC_PRINTF(
|
|
" %04x bytes in %u properties in %u property sets\n",
|
|
cbproptotal,
|
|
cproptotal,
|
|
cpropset);
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DumpOleStream(
|
|
LPSTREAM pstm,
|
|
ULONG cb)
|
|
{
|
|
ULONG cbTotal = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
ULONG cbOut;
|
|
BYTE ab[4096];
|
|
|
|
Check(S_OK, pstm->Read(ab, min(cb, sizeof(ab)), &cbOut) );
|
|
if (cbOut == 0)
|
|
{
|
|
break;
|
|
}
|
|
if (g_fVerbose)
|
|
{
|
|
DumpHex(ab, cbOut, cbTotal);
|
|
}
|
|
cb -= cbOut;
|
|
cbTotal += cbOut;
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
DumpOleStorage(
|
|
IStorage *pstg,
|
|
IPropertySetStorage *pIPropertySetStorage,
|
|
LPOLESTR aocpath )
|
|
{
|
|
LPENUMSTATSTG penum;
|
|
STATSTG ss;
|
|
IStorage* pstgChild;
|
|
LPSTREAM pstmChild;
|
|
char *szType;
|
|
OLECHAR *pocChild;
|
|
HRESULT hr;
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
|
|
Check( S_OK, DumpOlePropertySets(pstg, pIPropertySetStorage, aocpath) );
|
|
|
|
if (NULL == pstg)
|
|
{
|
|
return;
|
|
}
|
|
Check( S_OK, pstg->EnumElements(0, NULL, 0, &penum) );
|
|
|
|
pocChild = &aocpath[ocslen(aocpath)];
|
|
|
|
// Continue enumeration until IEnumStatStg::Next returns non-S_OK
|
|
|
|
while (TRUE)
|
|
{
|
|
ULONG ulCount;
|
|
|
|
// Enumerate one element at a time
|
|
hr = penum->Next(1, &ss, &ulCount);
|
|
if( (HRESULT) S_FALSE == hr )
|
|
break;
|
|
else
|
|
Check( S_OK, hr );
|
|
|
|
// Select the human-readable type of object to display
|
|
switch (ss.type)
|
|
{
|
|
case STGTY_STREAM: szType = "Stream"; break;
|
|
case STGTY_STORAGE: szType = "Storage"; break;
|
|
case STGTY_LOCKBYTES: szType = "LockBytes"; break;
|
|
case STGTY_PROPERTY: szType = "Property"; break;
|
|
default: szType = "<Unknown>"; break;
|
|
}
|
|
if (g_fVerbose)
|
|
{
|
|
ASYNC_OPRINTF(
|
|
OLESTR("Type=%hs Size=%lx Mode=%lx LocksSupported=%lx StateBits=%lx '%s' + '%s'\n"),
|
|
szType,
|
|
ss.cbSize.LowPart,
|
|
ss.grfMode,
|
|
ss.grfLocksSupported,
|
|
ss.grfStateBits,
|
|
aocpath,
|
|
ss.pwcsName);
|
|
ASYNC_PRINTF("ss.clsid = ");
|
|
PrintGuid(&ss.clsid);
|
|
ASYNC_PRINTF("\n");
|
|
}
|
|
|
|
// If a stream, output the data in hex format.
|
|
|
|
if (ss.type == STGTY_STREAM)
|
|
{
|
|
ASYNC_OPRINTF(
|
|
OLESTR("Stream %s:%s, Size=%lx\n"),
|
|
aocpath,
|
|
ss.pwcsName,
|
|
ss.cbSize.LowPart);
|
|
|
|
Check(S_OK, pstg->OpenStream(
|
|
ss.pwcsName,
|
|
NULL,
|
|
STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
|
|
0,
|
|
&pstmChild) );
|
|
|
|
Check(S_OK, DumpOleStream(pstmChild, ss.cbSize.LowPart) );
|
|
pstmChild->Release();
|
|
}
|
|
|
|
// If a storage, recurse
|
|
if (ss.type == STGTY_STORAGE)
|
|
{
|
|
ASYNC_OPRINTF(
|
|
OLESTR("Storage %s\\%s, Size=%lx\n"),
|
|
aocpath,
|
|
ss.pwcsName,
|
|
ss.cbSize.LowPart);
|
|
Check( S_OK, pstg->OpenStorage(
|
|
ss.pwcsName,
|
|
NULL,
|
|
STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
|
|
NULL,
|
|
0,
|
|
&pstgChild) );
|
|
*pocChild = L'\\';
|
|
ocscpy(pocChild + 1, ss.pwcsName);
|
|
|
|
DumpOleStorage(pstgChild, NULL, aocpath);
|
|
pstgChild->Release();
|
|
|
|
*pocChild = L'\0';
|
|
}
|
|
CoTaskMemFree(ss.pwcsName);
|
|
PRINTF( "\n" );
|
|
}
|
|
penum->Release();
|
|
return;
|
|
|
|
}
|
|
|
|
|