Leaked source code of windows server 2003
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.

479 lines
14 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1993
  5. //
  6. // File: tstgdir.cpp
  7. //
  8. // Contents: Recursive directory display of a storage
  9. // document
  10. //
  11. // Functions: main
  12. //
  13. // History: 04 Nov 94 - Created by philh
  14. //
  15. //-------------------------------------------------------------------------
  16. #include <windows.h>
  17. #include <assert.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <memory.h>
  22. #include <time.h>
  23. static int indent = 0;
  24. static BOOL fVerbose = FALSE;
  25. static BOOL fDebug = FALSE;
  26. static BOOL fRead = FALSE;
  27. static BOOL fReadVerbose = FALSE;
  28. static BOOL fBrief = FALSE;
  29. #define READ_BUF_SIZE 10000
  30. static BYTE readBuf[READ_BUF_SIZE];
  31. static CLSID NullClsid;
  32. typedef struct
  33. {
  34. SCODE sc;
  35. char *text;
  36. } StatusCodeText;
  37. static StatusCodeText scodes[] =
  38. {
  39. S_OK, "S_OK",
  40. S_FALSE, "S_FALSE",
  41. STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
  42. STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
  43. STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
  44. STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
  45. STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
  46. STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
  47. STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
  48. STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
  49. STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
  50. STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
  51. STG_E_SEEKERROR, "STG_E_SEEKERROR",
  52. STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
  53. STG_E_READFAULT, "STG_E_READFAULT",
  54. STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
  55. STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
  56. STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
  57. STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
  58. STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
  59. STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
  60. STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
  61. STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
  62. STG_E_UNKNOWN, "STG_E_UNKNOWN",
  63. STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
  64. STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
  65. STG_E_INUSE, "STG_E_INUSE",
  66. STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
  67. STG_E_REVERTED, "STG_E_REVERTED",
  68. STG_E_CANTSAVE, "STG_E_CANTSAVE",
  69. STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
  70. STG_E_OLDDLL, "STG_E_OLDDLL",
  71. STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
  72. STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
  73. STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
  74. E_NOINTERFACE, "E_NOINTERFACE",
  75. STG_S_CONVERTED, "STG_S_CONVERTED"
  76. };
  77. #define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
  78. // Convert a HRESULT to text
  79. static char *hResultText(HRESULT hResult)
  80. {
  81. static char buf[80];
  82. int i;
  83. for (i = 0; i<NSCODETEXT; i++)
  84. if (scodes[i].sc == hResult)
  85. return scodes[i].text;
  86. sprintf(buf, "%lx", hResult);
  87. return buf;
  88. }
  89. static void DirPrintf(const char * Format, ...)
  90. {
  91. int i = indent;
  92. va_list pArgs;
  93. char aBuf[256];
  94. while (i-- > 0)
  95. printf(" ");
  96. va_start( pArgs, Format );
  97. vsprintf(aBuf, Format, pArgs);
  98. printf("%s", aBuf);
  99. }
  100. #pragma pack(1)
  101. struct SplitGuid
  102. {
  103. DWORD dw1;
  104. WORD w1;
  105. WORD w2;
  106. BYTE b[8];
  107. };
  108. #pragma pack()
  109. static char *GuidText(GUID *pguid)
  110. {
  111. static char buf[39];
  112. SplitGuid *psg = (SplitGuid *)pguid;
  113. sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  114. psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
  115. psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
  116. return buf;
  117. }
  118. static char *FileTimeText(FILETIME *pft)
  119. {
  120. static char buf[80];
  121. FILETIME ftLocal;
  122. struct tm ctm;
  123. SYSTEMTIME st;
  124. FileTimeToLocalFileTime(pft, &ftLocal);
  125. if (FileTimeToSystemTime(&ftLocal, &st))
  126. {
  127. ctm.tm_sec = st.wSecond;
  128. ctm.tm_min = st.wMinute;
  129. ctm.tm_hour = st.wHour;
  130. ctm.tm_mday = st.wDay;
  131. ctm.tm_mon = st.wMonth-1;
  132. ctm.tm_year = st.wYear-1900;
  133. ctm.tm_wday = st.wDayOfWeek;
  134. ctm.tm_yday = 0;
  135. ctm.tm_isdst = 0;
  136. strcpy(buf, asctime(&ctm));
  137. buf[strlen(buf)-1] = 0;
  138. }
  139. else
  140. sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
  141. pft->dwLowDateTime);
  142. return buf;
  143. }
  144. static void DispStatStg(STATSTG *pStatStg)
  145. {
  146. char *szSTGTY;
  147. switch (pStatStg->type) {
  148. case STGTY_STORAGE:
  149. szSTGTY = "STGTY_STORAGE";
  150. break;
  151. case STGTY_STREAM:
  152. szSTGTY = "STGTY_STREAM";
  153. break;
  154. case STGTY_LOCKBYTES:
  155. szSTGTY = "STGTY_LOCKBYTES";
  156. break;
  157. default:
  158. szSTGTY = "STGTY_???";
  159. }
  160. if (pStatStg->type == STGTY_STREAM)
  161. DirPrintf("%S %s size:%ld\n", pStatStg->pwcsName, szSTGTY,
  162. pStatStg->cbSize.LowPart);
  163. else {
  164. DirPrintf("%S %s\n", pStatStg->pwcsName, szSTGTY);
  165. if (!fBrief && pStatStg->clsid != NullClsid)
  166. DirPrintf("CLSID: %s\n", GuidText(&pStatStg->clsid));
  167. }
  168. if (fVerbose) {
  169. DirPrintf("size: %ld,%ld Mode: %lx StateBits: %lx Locks: %ld\n",
  170. pStatStg->cbSize.HighPart, pStatStg->cbSize.LowPart,
  171. pStatStg->grfMode, pStatStg->grfStateBits,
  172. pStatStg->grfLocksSupported);
  173. if ((pStatStg->mtime.dwHighDateTime != 0) ||
  174. (pStatStg->mtime.dwLowDateTime != 0))
  175. DirPrintf("mtime %s\n", FileTimeText(&pStatStg->mtime));
  176. if ((pStatStg->ctime.dwHighDateTime != 0) ||
  177. (pStatStg->ctime.dwLowDateTime != 0))
  178. DirPrintf("ctime %s\n", FileTimeText(&pStatStg->ctime));
  179. if ((pStatStg->atime.dwHighDateTime != 0) ||
  180. (pStatStg->atime.dwLowDateTime != 0))
  181. DirPrintf("atime %s\n", FileTimeText(&pStatStg->atime));
  182. }
  183. }
  184. #define CROW 16
  185. void BinText(ULONG cbSize, BYTE *pb)
  186. {
  187. ULONG cb, i;
  188. while (cbSize > 0)
  189. {
  190. cb = min(CROW, cbSize);
  191. cbSize -= cb;
  192. for (i = 0; i<cb; i++)
  193. printf(" %02X", pb[i]);
  194. for (i = cb; i<CROW; i++)
  195. printf(" ");
  196. printf(" '");
  197. for (i = 0; i<cb; i++)
  198. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  199. printf("%c", pb[i]);
  200. else
  201. printf(".");
  202. pb += cb;
  203. printf("'\n");
  204. }
  205. }
  206. void DispStream(IStream *pstm);
  207. void DispStorage(IStorage *pstg);
  208. void DispStream(IStream *pstm)
  209. {
  210. HRESULT hResult;
  211. STATSTG statStg;
  212. hResult = pstm->Stat(&statStg, STATFLAG_DEFAULT);
  213. if (SUCCEEDED(hResult)) {
  214. DispStatStg(&statStg);
  215. if (statStg.pwcsName != NULL)
  216. CoTaskMemFree(statStg.pwcsName);
  217. } else {
  218. DirPrintf("Stat => %lx\n", hResult);
  219. return;
  220. }
  221. if (fRead) {
  222. ULONG ulTotalRead = 0;
  223. ULONG ulBytesRead;
  224. int i = 0;
  225. while (TRUE) {
  226. ulBytesRead = 0;
  227. hResult = pstm->Read(readBuf, READ_BUF_SIZE, &ulBytesRead);
  228. if (FAILED(hResult)) {
  229. DirPrintf("IStream->Read => %lx\n", hResult);
  230. break;
  231. }
  232. if (fReadVerbose) {
  233. DirPrintf("%lu bytes starting at offset: 0x%08lX\n",
  234. ulBytesRead, ulTotalRead);
  235. BinText(ulBytesRead, readBuf);
  236. }
  237. ulTotalRead += ulBytesRead;
  238. if (ulBytesRead < READ_BUF_SIZE)
  239. break;
  240. i++;
  241. if (i % 10 == 0) {
  242. if (fReadVerbose)
  243. DirPrintf("Read %ld bytes\n", ulTotalRead);
  244. else
  245. DirPrintf("Read %ld bytes\r", ulTotalRead);
  246. }
  247. }
  248. DirPrintf("Read %ld bytes\n", ulTotalRead);
  249. }
  250. }
  251. void DispStorage(IStorage *pstg)
  252. {
  253. HRESULT hResult;
  254. DWORD grfMode;
  255. STATSTG statStg;
  256. CLSID readClsid;
  257. IStorage *pstgChild;
  258. IStream *pstmChild;
  259. IEnumSTATSTG *penumStatStg;
  260. hResult = pstg->Stat(&statStg, STATFLAG_DEFAULT);
  261. if (SUCCEEDED(hResult)) {
  262. DispStatStg(&statStg);
  263. if (statStg.pwcsName != NULL)
  264. CoTaskMemFree(statStg.pwcsName);
  265. } else {
  266. DirPrintf("Stat => %s\n", hResultText(hResult));
  267. return;
  268. }
  269. hResult = ReadClassStg(pstg, &readClsid);
  270. if (SUCCEEDED(hResult)) {
  271. if (readClsid != statStg.clsid)
  272. DirPrintf("ReadClassStg CLSID: %s\n", GuidText(&readClsid));
  273. } else
  274. DirPrintf("ReadClassStg => %s\n", hResultText(hResult));
  275. indent += 2;
  276. hResult = pstg->EnumElements(0, NULL, 0, &penumStatStg);
  277. if (FAILED(hResult))
  278. DirPrintf("EnumElements => %lx\n", hResult);
  279. else {
  280. while(TRUE) {
  281. hResult = penumStatStg->Next(1, &statStg, NULL);
  282. if (hResult == S_FALSE) break;
  283. if (FAILED(hResult)) {
  284. DirPrintf("EnumStatStg => %lx\n", hResult);
  285. break;
  286. } else {
  287. switch (statStg.type) {
  288. case STGTY_STORAGE:
  289. if ((statStg.pwcsName == NULL) ||
  290. (statStg.pwcsName[0] == L'.'))
  291. DispStatStg(&statStg);
  292. else {
  293. grfMode =
  294. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE;
  295. hResult = pstg->OpenStorage(
  296. statStg.pwcsName,
  297. NULL, // pstgPriority
  298. grfMode,
  299. NULL, // snbExclude
  300. 0, // dwReserved
  301. &pstgChild);
  302. if (FAILED(hResult)) {
  303. DispStatStg(&statStg);
  304. DirPrintf("OpenStorage => %lx\n", hResult);
  305. } else {
  306. if (fDebug) {
  307. DirPrintf("--- Enum ---\n");
  308. DispStatStg(&statStg);
  309. DirPrintf("--- Enum ---\n");
  310. }
  311. DispStorage(pstgChild);
  312. pstgChild->Release();
  313. }
  314. }
  315. break;
  316. case STGTY_STREAM:
  317. if ((statStg.pwcsName == NULL) ||
  318. (statStg.pwcsName[0] == L'.'))
  319. DispStatStg(&statStg);
  320. else {
  321. grfMode =
  322. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE;
  323. hResult = pstg->OpenStream(
  324. statStg.pwcsName,
  325. NULL, // pReserved1
  326. grfMode,
  327. 0, // dwReserved2
  328. &pstmChild);
  329. if (FAILED(hResult)) {
  330. DispStatStg(&statStg);
  331. DirPrintf("OpenStream => %lx\n", hResult);
  332. } else {
  333. if (fDebug) {
  334. DirPrintf("--- Enum ---\n");
  335. DispStatStg(&statStg);
  336. DirPrintf("--- Enum ---\n");
  337. }
  338. DispStream(pstmChild);
  339. pstmChild->Release();
  340. }
  341. }
  342. break;
  343. default:
  344. DispStatStg(&statStg);
  345. }
  346. if (statStg.pwcsName != NULL)
  347. CoTaskMemFree(statStg.pwcsName);
  348. }
  349. } // while loop
  350. penumStatStg->Release();
  351. }
  352. indent -= 2;
  353. }
  354. static void Usage(void)
  355. {
  356. printf("Usage: tstgdir [options] <filename>\n");
  357. printf("Options are:\n");
  358. printf(" -h - This message\n");
  359. printf(" -b - Brief\n");
  360. printf(" -d - Debug\n");
  361. printf(" -r - Read streams (don't display)\n");
  362. printf(" -R - Read streams (display contents)\n");
  363. printf(" -v - Verbose\n");
  364. printf("\n");
  365. }
  366. int _cdecl main(int argc, char * argv[])
  367. {
  368. WCHAR wcsFile[_MAX_PATH];
  369. HRESULT hResult;
  370. DWORD grfMode;
  371. IStorage *pstgRoot;
  372. wcscpy(wcsFile, L"");
  373. while (--argc>0)
  374. {
  375. if (**++argv == '-')
  376. {
  377. switch(argv[0][1])
  378. {
  379. case 'b':
  380. fBrief = TRUE;
  381. break;
  382. case 'd':
  383. fDebug = TRUE;
  384. break;
  385. case 'R':
  386. fReadVerbose = TRUE;
  387. case 'r':
  388. fRead = TRUE;
  389. break;
  390. case 'v':
  391. fVerbose = TRUE;
  392. break;
  393. case 'h':
  394. default:
  395. Usage();
  396. return -1;
  397. }
  398. }
  399. else
  400. mbstowcs(wcsFile, argv[0], strlen(argv[0]) + 1);
  401. }
  402. if (wcsFile[0] == L'\0') {
  403. printf("missing filename\n");
  404. Usage();
  405. return -1;
  406. }
  407. if (fVerbose)
  408. fBrief = FALSE;
  409. if (FAILED(hResult = CoInitialize(NULL))) {
  410. printf("CoInitialize => %s\n", hResultText(hResult));
  411. return -1;
  412. }
  413. grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
  414. hResult = StgOpenStorage(wcsFile,
  415. NULL, //pstgPriority
  416. grfMode,
  417. NULL, // snbExclude
  418. 0, //dwReserved
  419. &pstgRoot);
  420. if (FAILED(hResult)) {
  421. CoUninitialize();
  422. printf("StgOpenStorage => %s\n", hResultText(hResult));
  423. return -1;
  424. }
  425. DispStorage(pstgRoot);
  426. pstgRoot->Release();
  427. CoUninitialize();
  428. return 0;
  429. }