//+------------------------------------------------------------------------ // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1993 - 1993 // // File: tstgdir.cpp // // Contents: Recursive directory display of a storage // document // // Functions: main // // History: 04 Nov 94 - Created by philh // //------------------------------------------------------------------------- #include #include #include #include #include #include #include static int indent = 0; static BOOL fVerbose = FALSE; static BOOL fDebug = FALSE; static BOOL fRead = FALSE; static BOOL fReadVerbose = FALSE; static BOOL fBrief = FALSE; #define READ_BUF_SIZE 10000 static BYTE readBuf[READ_BUF_SIZE]; static CLSID NullClsid; typedef struct { SCODE sc; char *text; } StatusCodeText; static StatusCodeText scodes[] = { S_OK, "S_OK", S_FALSE, "S_FALSE", STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION", STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND", STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND", STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES", STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED", STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE", STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY", STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER", STG_E_NOMOREFILES, "STG_E_NOMOREFILES", STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED", STG_E_SEEKERROR, "STG_E_SEEKERROR", STG_E_WRITEFAULT, "STG_E_WRITEFAULT", STG_E_READFAULT, "STG_E_READFAULT", STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION", STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION", STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS", STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER", STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL", STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT", STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER", STG_E_INVALIDNAME, "STG_E_INVALIDNAME", STG_E_UNKNOWN, "STG_E_UNKNOWN", STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION", STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG", STG_E_INUSE, "STG_E_INUSE", STG_E_NOTCURRENT, "STG_E_NOTCURRENT", STG_E_REVERTED, "STG_E_REVERTED", STG_E_CANTSAVE, "STG_E_CANTSAVE", STG_E_OLDFORMAT, "STG_E_OLDFORMAT", STG_E_OLDDLL, "STG_E_OLDDLL", STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED", STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE", STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS", E_NOINTERFACE, "E_NOINTERFACE", STG_S_CONVERTED, "STG_S_CONVERTED" }; #define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0])) // Convert a HRESULT to text static char *hResultText(HRESULT hResult) { static char buf[80]; int i; for (i = 0; i 0) printf(" "); va_start( pArgs, Format ); vsprintf(aBuf, Format, pArgs); printf("%s", aBuf); } #pragma pack(1) struct SplitGuid { DWORD dw1; WORD w1; WORD w2; BYTE b[8]; }; #pragma pack() static char *GuidText(GUID *pguid) { static char buf[39]; SplitGuid *psg = (SplitGuid *)pguid; sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}", psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2], psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]); return buf; } static char *FileTimeText(FILETIME *pft) { static char buf[80]; FILETIME ftLocal; struct tm ctm; SYSTEMTIME st; FileTimeToLocalFileTime(pft, &ftLocal); if (FileTimeToSystemTime(&ftLocal, &st)) { ctm.tm_sec = st.wSecond; ctm.tm_min = st.wMinute; ctm.tm_hour = st.wHour; ctm.tm_mday = st.wDay; ctm.tm_mon = st.wMonth-1; ctm.tm_year = st.wYear-1900; ctm.tm_wday = st.wDayOfWeek; ctm.tm_yday = 0; ctm.tm_isdst = 0; strcpy(buf, asctime(&ctm)); buf[strlen(buf)-1] = 0; } else sprintf(buf, "", pft->dwHighDateTime, pft->dwLowDateTime); return buf; } static void DispStatStg(STATSTG *pStatStg) { char *szSTGTY; switch (pStatStg->type) { case STGTY_STORAGE: szSTGTY = "STGTY_STORAGE"; break; case STGTY_STREAM: szSTGTY = "STGTY_STREAM"; break; case STGTY_LOCKBYTES: szSTGTY = "STGTY_LOCKBYTES"; break; default: szSTGTY = "STGTY_???"; } if (pStatStg->type == STGTY_STREAM) DirPrintf("%S %s size:%ld\n", pStatStg->pwcsName, szSTGTY, pStatStg->cbSize.LowPart); else { DirPrintf("%S %s\n", pStatStg->pwcsName, szSTGTY); if (!fBrief && pStatStg->clsid != NullClsid) DirPrintf("CLSID: %s\n", GuidText(&pStatStg->clsid)); } if (fVerbose) { DirPrintf("size: %ld,%ld Mode: %lx StateBits: %lx Locks: %ld\n", pStatStg->cbSize.HighPart, pStatStg->cbSize.LowPart, pStatStg->grfMode, pStatStg->grfStateBits, pStatStg->grfLocksSupported); if ((pStatStg->mtime.dwHighDateTime != 0) || (pStatStg->mtime.dwLowDateTime != 0)) DirPrintf("mtime %s\n", FileTimeText(&pStatStg->mtime)); if ((pStatStg->ctime.dwHighDateTime != 0) || (pStatStg->ctime.dwLowDateTime != 0)) DirPrintf("ctime %s\n", FileTimeText(&pStatStg->ctime)); if ((pStatStg->atime.dwHighDateTime != 0) || (pStatStg->atime.dwLowDateTime != 0)) DirPrintf("atime %s\n", FileTimeText(&pStatStg->atime)); } } #define CROW 16 void BinText(ULONG cbSize, BYTE *pb) { ULONG cb, i; while (cbSize > 0) { cb = min(CROW, cbSize); cbSize -= cb; for (i = 0; i= 0x20 && pb[i] <= 0x7f) printf("%c", pb[i]); else printf("."); pb += cb; printf("'\n"); } } void DispStream(IStream *pstm); void DispStorage(IStorage *pstg); void DispStream(IStream *pstm) { HRESULT hResult; STATSTG statStg; hResult = pstm->Stat(&statStg, STATFLAG_DEFAULT); if (SUCCEEDED(hResult)) { DispStatStg(&statStg); if (statStg.pwcsName != NULL) CoTaskMemFree(statStg.pwcsName); } else { DirPrintf("Stat => %lx\n", hResult); return; } if (fRead) { ULONG ulTotalRead = 0; ULONG ulBytesRead; int i = 0; while (TRUE) { ulBytesRead = 0; hResult = pstm->Read(readBuf, READ_BUF_SIZE, &ulBytesRead); if (FAILED(hResult)) { DirPrintf("IStream->Read => %lx\n", hResult); break; } if (fReadVerbose) { DirPrintf("%lu bytes starting at offset: 0x%08lX\n", ulBytesRead, ulTotalRead); BinText(ulBytesRead, readBuf); } ulTotalRead += ulBytesRead; if (ulBytesRead < READ_BUF_SIZE) break; i++; if (i % 10 == 0) { if (fReadVerbose) DirPrintf("Read %ld bytes\n", ulTotalRead); else DirPrintf("Read %ld bytes\r", ulTotalRead); } } DirPrintf("Read %ld bytes\n", ulTotalRead); } } void DispStorage(IStorage *pstg) { HRESULT hResult; DWORD grfMode; STATSTG statStg; CLSID readClsid; IStorage *pstgChild; IStream *pstmChild; IEnumSTATSTG *penumStatStg; hResult = pstg->Stat(&statStg, STATFLAG_DEFAULT); if (SUCCEEDED(hResult)) { DispStatStg(&statStg); if (statStg.pwcsName != NULL) CoTaskMemFree(statStg.pwcsName); } else { DirPrintf("Stat => %s\n", hResultText(hResult)); return; } hResult = ReadClassStg(pstg, &readClsid); if (SUCCEEDED(hResult)) { if (readClsid != statStg.clsid) DirPrintf("ReadClassStg CLSID: %s\n", GuidText(&readClsid)); } else DirPrintf("ReadClassStg => %s\n", hResultText(hResult)); indent += 2; hResult = pstg->EnumElements(0, NULL, 0, &penumStatStg); if (FAILED(hResult)) DirPrintf("EnumElements => %lx\n", hResult); else { while(TRUE) { hResult = penumStatStg->Next(1, &statStg, NULL); if (hResult == S_FALSE) break; if (FAILED(hResult)) { DirPrintf("EnumStatStg => %lx\n", hResult); break; } else { switch (statStg.type) { case STGTY_STORAGE: if ((statStg.pwcsName == NULL) || (statStg.pwcsName[0] == L'.')) DispStatStg(&statStg); else { grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE; hResult = pstg->OpenStorage( statStg.pwcsName, NULL, // pstgPriority grfMode, NULL, // snbExclude 0, // dwReserved &pstgChild); if (FAILED(hResult)) { DispStatStg(&statStg); DirPrintf("OpenStorage => %lx\n", hResult); } else { if (fDebug) { DirPrintf("--- Enum ---\n"); DispStatStg(&statStg); DirPrintf("--- Enum ---\n"); } DispStorage(pstgChild); pstgChild->Release(); } } break; case STGTY_STREAM: if ((statStg.pwcsName == NULL) || (statStg.pwcsName[0] == L'.')) DispStatStg(&statStg); else { grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE; hResult = pstg->OpenStream( statStg.pwcsName, NULL, // pReserved1 grfMode, 0, // dwReserved2 &pstmChild); if (FAILED(hResult)) { DispStatStg(&statStg); DirPrintf("OpenStream => %lx\n", hResult); } else { if (fDebug) { DirPrintf("--- Enum ---\n"); DispStatStg(&statStg); DirPrintf("--- Enum ---\n"); } DispStream(pstmChild); pstmChild->Release(); } } break; default: DispStatStg(&statStg); } if (statStg.pwcsName != NULL) CoTaskMemFree(statStg.pwcsName); } } // while loop penumStatStg->Release(); } indent -= 2; } static void Usage(void) { printf("Usage: tstgdir [options] \n"); printf("Options are:\n"); printf(" -h - This message\n"); printf(" -b - Brief\n"); printf(" -d - Debug\n"); printf(" -r - Read streams (don't display)\n"); printf(" -R - Read streams (display contents)\n"); printf(" -v - Verbose\n"); printf("\n"); } int _cdecl main(int argc, char * argv[]) { WCHAR wcsFile[_MAX_PATH]; HRESULT hResult; DWORD grfMode; IStorage *pstgRoot; wcscpy(wcsFile, L""); while (--argc>0) { if (**++argv == '-') { switch(argv[0][1]) { case 'b': fBrief = TRUE; break; case 'd': fDebug = TRUE; break; case 'R': fReadVerbose = TRUE; case 'r': fRead = TRUE; break; case 'v': fVerbose = TRUE; break; case 'h': default: Usage(); return -1; } } else mbstowcs(wcsFile, argv[0], strlen(argv[0]) + 1); } if (wcsFile[0] == L'\0') { printf("missing filename\n"); Usage(); return -1; } if (fVerbose) fBrief = FALSE; if (FAILED(hResult = CoInitialize(NULL))) { printf("CoInitialize => %s\n", hResultText(hResult)); return -1; } grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE; hResult = StgOpenStorage(wcsFile, NULL, //pstgPriority grfMode, NULL, // snbExclude 0, //dwReserved &pstgRoot); if (FAILED(hResult)) { CoUninitialize(); printf("StgOpenStorage => %s\n", hResultText(hResult)); return -1; } DispStorage(pstgRoot); pstgRoot->Release(); CoUninitialize(); return 0; }