windows-nt/Source/XPSP1/NT/com/ole32/stg/utils/stgview/stgview.cxx
2020-09-26 16:20:57 +08:00

412 lines
10 KiB
C++

//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1992.
//
// File: stgview.cxx
//
// Contents: Storage viewer utility
//
// History: 10-Dec-91 DrewB Created
//
//---------------------------------------------------------------
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <windows.h>
#if WIN32 != 300
#include <storage.h>
#endif
#include <wchar.h>
#include <dfmsp.hxx>
#define FLG_RECURSIVE 0x00000001
#define FLG_STREAMS 0x00000002
#define FLG_VERBOSE 0x00000004
#define DFTOUCH
#ifdef DFTOUCH
#define CB_BUFFER 1024
#else
#define CB_BUFFER 16
#endif
BYTE abBuffer[CB_BUFFER];
char *szTypes[] =
{
"", "IStorage", "IStream", "ILockBytes"
};
void utMemFree(void *pv)
{
IMalloc FAR* pMalloc;
if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
{
pMalloc->Free(pv);
pMalloc->Release();
}
}
void LevSpace(int iLevel)
{
int i;
for (i = 0; i<iLevel; i++)
printf(" ");
}
void PrintStat(STATSTG *psstg, ULONG flOptions, int iLevel)
{
LevSpace(iLevel);
if (flOptions & FLG_VERBOSE)
{
#ifdef UNICODE
wprintf(L"%s:%hs =>\n", psstg->pwcsName, szTypes[psstg->type]);
#else
printf("%s:%s =>\n", psstg->pwcsName, szTypes[psstg->type]);
#endif
#ifdef FLAT
SYSTEMTIME systime;
struct tm stime;
LevSpace(iLevel+1);
if (((psstg->ctime.dwHighDateTime != 0) ||
(psstg->ctime.dwLowDateTime != 0 )) &&
FileTimeToSystemTime(&psstg->ctime, &systime))
{
stime.tm_sec = systime.wSecond;
stime.tm_min = systime.wMinute;
stime.tm_hour = systime.wHour;
stime.tm_mday = systime.wDay;
stime.tm_mon = systime.wMonth - 1;
stime.tm_year = systime.wYear - 1900;
stime.tm_wday = systime.wDayOfWeek;
stime.tm_yday = 0;
stime.tm_isdst = 0;
printf("Created : %s", asctime(&stime));
}
else
printf("Created : %lx %lx (conversion unavailable)\n",
psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
LevSpace(iLevel+1);
if (((psstg->mtime.dwHighDateTime != 0) ||
(psstg->mtime.dwLowDateTime != 0 )) &&
FileTimeToSystemTime(&psstg->mtime, &systime))
{
stime.tm_sec = systime.wSecond;
stime.tm_min = systime.wMinute;
stime.tm_hour = systime.wHour;
stime.tm_mday = systime.wDay;
stime.tm_mon = systime.wMonth - 1;
stime.tm_year = systime.wYear - 1900;
stime.tm_wday = systime.wDayOfWeek;
stime.tm_yday = 0;
stime.tm_isdst = 0;
printf("Modified : %s", asctime(&stime));
}
else
printf("Modified : %lx %lx (conversion unavailable)\n",
psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
LevSpace(iLevel+1);
if (((psstg->atime.dwHighDateTime != 0) ||
(psstg->atime.dwLowDateTime != 0 )) &&
FileTimeToSystemTime(&psstg->mtime, &systime))
{
stime.tm_sec = systime.wSecond;
stime.tm_min = systime.wMinute;
stime.tm_hour = systime.wHour;
stime.tm_mday = systime.wDay;
stime.tm_mon = systime.wMonth - 1;
stime.tm_year = systime.wYear - 1900;
stime.tm_wday = systime.wDayOfWeek;
stime.tm_yday = 0;
stime.tm_isdst = 0;
printf("Accessed : %s", asctime(&stime));
}
else
printf("Accessed : %lx %lx (conversion unavailable)\n",
psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
#else
LevSpace(iLevel+1);
printf("Created : %lx %lx (conversion unavailable)\n",
psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
LevSpace(iLevel+1);
printf("Modified : %lx %lx (conversion unavailable)\n",
psstg->mtime.dwHighDateTime, psstg->mtime.dwLowDateTime);
LevSpace(iLevel+1);
printf("Accessed : %lx %lx (conversion unavailable)\n",
psstg->atime.dwHighDateTime, psstg->atime.dwLowDateTime);
#endif
if (psstg->type == STGTY_STREAM || psstg->type == STGTY_LOCKBYTES)
{
LevSpace(iLevel+1);
printf("Size: %lu:%lu\n", ULIGetHigh(psstg->cbSize),
ULIGetLow(psstg->cbSize));
}
}
else
#ifdef UNICODE
wprintf(L"%s\n", psstg->pwcsName);
#else
printf("%s\n", psstg->pwcsName);
#endif
}
// ctype doesn't work properly
#define dfisprint(c) ((c) >= ' ' && (c) < 127)
void Stream(IStream *pstm, ULONG flOptions, int iLevel)
{
ULONG cbRead;
#ifdef DFTOUCH
ULONG cbTotal = 0;
#endif
SCODE sc;
sc = GetScode(pstm->Read(abBuffer, CB_BUFFER, &cbRead));
while (SUCCEEDED(sc) && (cbRead > 0))
{
LevSpace(iLevel);
#ifdef DFTOUCH
cbTotal += cbRead;
printf("Read %lu bytes\n", cbTotal);
#else
for (ULONG ib = 0; ib < cbRead; ib++)
{
printf("%.2X", (int)abBuffer[ib]);
}
for (ib = ib; ib < CB_BUFFER + 1; ib++)
{
printf(" ");
}
for (ib = 0; ib < cbRead; ib++)
{
printf("%c", dfisprint(abBuffer[ib]) ? abBuffer[ib] : '.');
}
printf("\n");
#endif
sc = GetScode(pstm->Read(abBuffer, CB_BUFFER, &cbRead));
}
if (FAILED(sc))
printf("Read failed with 0x%lX\n", sc);
}
void Contents(IStorage *pdf, ULONG flOptions, int iLevel)
{
IEnumSTATSTG *pdfi;
SCODE sc;
IStorage *pdfChild;
IStream *pstmChild;
STATSTG sstg;
if (FAILED(pdf->EnumElements(0, NULL, 0, &pdfi)))
{
fprintf(stderr, "Unable to create iterator\n");
return;
}
for (;;)
{
sc = GetScode(pdfi->Next(1, &sstg, NULL));
if (sc != S_OK)
break;
PrintStat(&sstg, flOptions, iLevel);
if ((sstg.type == STGTY_STORAGE) && (flOptions & FLG_RECURSIVE))
{
if (SUCCEEDED(pdf->OpenStorage(sstg.pwcsName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL, 0, &pdfChild)))
{
Contents(pdfChild, flOptions, iLevel+1);
pdfChild->Release();
}
else
fprintf(stderr, "%s: Unable to recurse\n", sstg.pwcsName);
}
else
if ((sstg.type == STGTY_STREAM) && (flOptions & FLG_STREAMS))
{
if (SUCCEEDED(pdf->OpenStream(sstg.pwcsName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0, &pstmChild)))
{
Stream(pstmChild, flOptions, iLevel+1);
pstmChild->Release();
}
else
fprintf(stderr, "%s: Unable to open\n", sstg.pwcsName);
}
utMemFree(sstg.pwcsName);
}
pdfi->Release();
if (FAILED(sc))
printf("Enumeration failed with 0x%lX\n", sc);
}
void Descend(IStorage *pdf, char *pszPath, IStorage **ppdf)
{
IStorage *pdfNext;
char *pszNext = pszPath;
char *pszEnd = strchr(pszNext, '\\');
TCHAR atcName[CWCSTORAGENAME];
while (pszNext != NULL)
{
if (pszEnd != NULL)
{
*pszEnd = '\0';
}
#ifdef UNICODE
if (mbstowcs(atcName, pszNext, CWCSTORAGENAME) == (size_t)-1)
{
pdf = NULL;
fprintf(stderr, "Unable to convert '%s' to Unicode\n", pszNext);
break;
}
#else
strcpy(atcName, pszNext);
#endif
if (SUCCEEDED(pdf->OpenStorage(atcName, NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL, 0, &pdfNext)))
{
pdf = pdfNext;
if (pszEnd != NULL)
{
*pszEnd = '\\';
pszNext = pszEnd + 1;
pszEnd = strchr(pszNext, '\\');
}
else
{
pszNext = NULL;
}
}
else
{
pdf = NULL;
fprintf(stderr, "Unable to open '%s' in docfile\n", pszPath);
break;
}
}
*ppdf = pdf;
}
void __cdecl main(int argc, char **argv)
{
ULONG flOptions = 0;
IStorage *pdf;
IStorage *pdfRoot;
STATSTG sstg;
argc--;
argv++;
while ((argc > 0) && ((*argv)[0] == '-'))
{
for (int ich = 1; (*argv)[ich] != '\0'; ich++)
{
switch((*argv)[ich])
{
case 's':
flOptions |= FLG_STREAMS;
break;
case 'v':
flOptions |= FLG_VERBOSE;
break;
case 'r':
flOptions |= FLG_RECURSIVE;
break;
default:
fprintf(stderr, "Unknown switch '%c'\n", (*argv)[ich]);
break;
}
}
argc--;
argv++;
}
if ((argc != 1) && (argc != 2))
{
printf("Usage: stgview [-v] [-s] [-r] docfile [path]\n");
exit(1);
}
SCODE sc;
#if WIN32 == 300
if (FAILED(sc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
#else
if (FAILED(sc = GetScode(CoInitialize(NULL))))
#endif
{
fprintf(stderr, "CoInitialize failed with sc = %lx\n", sc);
exit(1);
}
TCHAR atcName[_MAX_PATH];
#ifdef UNICODE
if (mbstowcs(atcName, *argv, _MAX_PATH) == (size_t)-1)
{
fprintf(stderr, "Unable to convert '%s' to Unicode\n", *argv);
exit(1);
}
#else
strcpy(atcName, *argv);
#endif
if (FAILED(StgOpenStorage(atcName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE,
NULL, 0, &pdf)))
{
fprintf(stderr, "Unable to open '%s'\n", *argv);
exit(1);
}
else
{
if (argc == 2)
{
Descend(pdf, *(argv + 1), &pdfRoot);
}
else
{
pdf->AddRef();
pdfRoot = pdf;
}
if (pdfRoot != NULL)
{
if (FAILED(pdfRoot->Stat(&sstg, 0)))
fprintf(stderr, "Unable to stat root\n");
else
{
PrintStat(&sstg, flOptions, 0);
utMemFree(sstg.pwcsName);
}
Contents(pdfRoot, flOptions, 1);
pdfRoot->Release();
}
pdf->Release();
}
CoUninitialize();
}