Source code of Windows XP (NT5)
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.

550 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1998
  5. //
  6. // File: main.cxx
  7. //
  8. // Contents: Index Server V1.x property file dumper.
  9. //
  10. // History: 29 Oct 1996 KyleP Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <proprec.hxx>
  16. #include <propdesc.hxx>
  17. DECLARE_INFOLEVEL(ci)
  18. unsigned const SixtyFourK = 1024 * 64;
  19. unsigned const cMaxFields = 10;
  20. unsigned fVerbose = 0;
  21. enum eRecType
  22. {
  23. Virgin,
  24. Top,
  25. Overflow,
  26. Free
  27. };
  28. struct SmallInfo
  29. {
  30. ULONG Type;
  31. ULONG Length;
  32. ULONG ulPrev;
  33. ULONG ulNext;
  34. ULONG ulChainLength;
  35. };
  36. int __cdecl main( int argc, char * argv[] )
  37. {
  38. char * pszFile = argv[1];
  39. BOOL fReadMetadata = 0;
  40. unsigned cField = 0;
  41. int aiField[cMaxFields];
  42. for ( int i = 1; i < argc; i++ )
  43. {
  44. if ( argv[i][0] == '-' )
  45. {
  46. switch ( argv[i][1] )
  47. {
  48. case 'v':
  49. case 'V':
  50. fVerbose = 1;
  51. break;
  52. case 'm':
  53. case 'M':
  54. fReadMetadata = TRUE;
  55. break;
  56. case 'f':
  57. case 'F':
  58. i++;
  59. if ( cField < cMaxFields )
  60. aiField[cField++] = strtol( argv[i], 0, 10 );
  61. break;
  62. }
  63. }
  64. else
  65. pszFile = argv[i];
  66. }
  67. BYTE abTemp[SixtyFourK];
  68. //
  69. // First, read out the metadata
  70. //
  71. unsigned cFixed = 0;
  72. unsigned cTotal = 0;
  73. unsigned culFixed = 0;
  74. CPropDesc aFieldRec[cMaxFields];
  75. if ( fReadMetadata || cField != 0 )
  76. {
  77. //
  78. // Build path.
  79. //
  80. char szPath[MAX_PATH];
  81. strcpy( szPath, pszFile );
  82. char * pLastSlash = strrchr( szPath, '\\' );
  83. pLastSlash++;
  84. strcpy( pLastSlash, "CIPS0000.001" );
  85. HANDLE h = CreateFileA( szPath,
  86. GENERIC_READ,
  87. FILE_SHARE_READ,
  88. 0,
  89. OPEN_EXISTING,
  90. 0,
  91. 0 );
  92. if ( INVALID_HANDLE_VALUE == h )
  93. {
  94. printf( "Can't open file %s. Error %u\n", szPath, GetLastError() );
  95. return 0;
  96. }
  97. ULONG cbRead;
  98. if ( ReadFile( h,
  99. abTemp,
  100. sizeof(abTemp),
  101. &cbRead,
  102. 0 ) )
  103. {
  104. //
  105. // Loop through records
  106. //
  107. CPropDesc * pPropDesc = (CPropDesc *)abTemp;
  108. if ( fReadMetadata )
  109. printf( "Record\tPid\t\tType\t\tOffset\tSize\tOrdinal\tMask\n" );
  110. for ( unsigned i = 0; i < cbRead/sizeof(CPropDesc); i++, pPropDesc++ )
  111. {
  112. if ( pPropDesc->Pid() != 0 )
  113. {
  114. if ( fReadMetadata )
  115. printf( "%u:\t%u (0x%x)%s\t%u (0x%x)\t%d\t%u\t%u\t0x%x\n",
  116. pPropDesc->Record(),
  117. pPropDesc->Pid(), pPropDesc->Pid(),
  118. (pPropDesc->Pid() > 10) ? "" : "\t",
  119. pPropDesc->Type(), pPropDesc->Type(),
  120. pPropDesc->Offset(),
  121. pPropDesc->Size(),
  122. pPropDesc->Ordinal(),
  123. pPropDesc->Mask() );
  124. cTotal++;
  125. if ( pPropDesc->Offset() != -1 )
  126. {
  127. cFixed++;
  128. culFixed += (pPropDesc->Size() / sizeof(DWORD));
  129. }
  130. for ( unsigned j = 0; j < cField; j++ )
  131. {
  132. if ( aiField[j] == (int)pPropDesc->Record() )
  133. memcpy( &aFieldRec[j], pPropDesc, sizeof(aFieldRec[0]) );
  134. }
  135. }
  136. }
  137. printf( "\n%u Properties, %u Fixed totaling %u bytes\n\n", cTotal, cFixed, culFixed * sizeof(DWORD) );
  138. }
  139. else
  140. {
  141. printf( "Can't read file %s. Error %u\n", szPath, GetLastError() );
  142. return 0;
  143. }
  144. }
  145. HANDLE h = CreateFileA( pszFile,
  146. GENERIC_READ,
  147. FILE_SHARE_READ,
  148. 0,
  149. OPEN_EXISTING,
  150. 0,
  151. 0 );
  152. if ( INVALID_HANDLE_VALUE == h )
  153. {
  154. printf( "Can't open file %s. Error %u\n", pszFile, GetLastError() );
  155. return 0;
  156. }
  157. BY_HANDLE_FILE_INFORMATION fi;
  158. if ( !GetFileInformationByHandle( h, &fi ) )
  159. {
  160. printf( "Error %u getting size from handle\n", GetLastError() );
  161. return 0;
  162. }
  163. ULONG oFile = 0;
  164. ULONG cbRec = 0;
  165. ULONG cRecPerBuf;
  166. ULONG cRecTotal;
  167. ULONG cTotalSections = 0;
  168. HANDLE hSmallInfo;
  169. SmallInfo * aSmallInfo = 0;
  170. ULONG iSection = 0;
  171. BOOL fFirst = TRUE;
  172. ULONG iCurrentPct = 0;
  173. for (;;)
  174. {
  175. ULONG cbRead;
  176. if ( ReadFile( h,
  177. abTemp,
  178. sizeof(abTemp),
  179. &cbRead,
  180. 0 ) )
  181. {
  182. if (fVerbose)
  183. printf( "READ: 0x%x bytes, offset %0x%x\n", cbRead, oFile );
  184. if ( 0 == cbRead )
  185. break;
  186. if ( fFirst )
  187. {
  188. //
  189. // Determine record size
  190. //
  191. if ( abTemp[0] != 0 || abTemp[1] != 0 )
  192. {
  193. printf( "Record 0 not blank. File corrupt!\n" );
  194. break;
  195. }
  196. for ( unsigned i = 0; i < cbRead && abTemp[i] == 0; i++ )
  197. continue;
  198. if ( i == cbRead )
  199. {
  200. printf( "First %uK segment all zero!. File corrupt!\n", sizeof(abTemp)/1024 );
  201. break;
  202. }
  203. switch ( *(USHORT *)&abTemp[i] )
  204. {
  205. case 0x5555:
  206. case 0xAAAA:
  207. case 0xBBBB:
  208. cbRec = i;
  209. if ( cbRec % 4 != 0 )
  210. {
  211. printf( "Record size (%u bytes) not DWORD aligned!\n\n", cbRec );
  212. return 0;
  213. }
  214. cRecPerBuf = sizeof(abTemp) / cbRec;
  215. printf( "Record size: %u bytes (%u / %uK)\n", i, cRecPerBuf, sizeof(abTemp)/1024 );
  216. cTotalSections = (fi.nFileSizeLow + sizeof(abTemp) - 1)/ sizeof abTemp;
  217. hSmallInfo = LocalAlloc( LMEM_MOVEABLE,
  218. ((fi.nFileSizeLow / sizeof(abTemp)) + 1) * cRecPerBuf * sizeof(SmallInfo) );
  219. aSmallInfo = (SmallInfo *)LocalLock( hSmallInfo );
  220. break;
  221. default:
  222. printf( "First non-zero byte is not a proper signature (%u)!\n", *(SHORT *)&abTemp[i] );
  223. return 0;
  224. }
  225. fFirst = FALSE;
  226. }
  227. ULONG iRec = 0;
  228. while ( iRec < cRecPerBuf )
  229. {
  230. COnDiskPropertyRecord * pRec = new( iRec, abTemp, cbRec/4 ) COnDiskPropertyRecord;
  231. if ( !pRec->IsValidType() )
  232. {
  233. printf( "Record 0x%x (%u:%u) (file offset 0x%x) is corrupt!\n",
  234. iSection * cRecPerBuf + iRec,
  235. iSection, iRec,
  236. iSection * sizeof(abTemp) + iRec * cbRec );
  237. }
  238. if (fVerbose )
  239. printf( "%u:%u, %s, length = %u record(s)",
  240. iSection, iRec,
  241. pRec->IsTopLevel() ? "Top Level" :
  242. pRec->IsOverflow() ? "Overflow" :
  243. pRec->IsFreeRecord() ? "Free" :
  244. "Virgin",
  245. pRec->CountRecords() );
  246. aSmallInfo[iSection*cRecPerBuf + iRec].ulChainLength = 0;
  247. if ( pRec->IsOverflow() )
  248. {
  249. aSmallInfo[iSection*cRecPerBuf + iRec].Type = Overflow;
  250. /* printf( ", Previous = %u:%u (file offset 0x%x)",
  251. pRec->PreviousBlock() / cRecPerBuf,
  252. pRec->PreviousBlock() % cRecPerBuf,
  253. (pRec->PreviousBlock() / cRecPerBuf) * sizeof(abTemp) +
  254. (pRec->PreviousBlock() % cRecPerBuf) * cbRec ); */
  255. }
  256. else if ( pRec->IsTopLevel() )
  257. {
  258. aSmallInfo[iSection*cRecPerBuf + iRec].Type = Top;
  259. aSmallInfo[iSection*cRecPerBuf + iRec].ulChainLength = pRec->GetOverflowChainLength();
  260. for ( unsigned j = 0; j < cField; j++ )
  261. {
  262. PROPVARIANT var;
  263. BYTE abExtra[MAX_PATH * 5];
  264. unsigned cbExtra = sizeof(abExtra);
  265. if ( 0 == j )
  266. printf( "%6u: ", iSection*cRecPerBuf + iRec );
  267. if ( aFieldRec[j].IsFixedSize() )
  268. {
  269. pRec->ReadFixed( aFieldRec[j].Ordinal(),
  270. aFieldRec[j].Mask(),
  271. aFieldRec[j].Offset(),
  272. cTotal,
  273. aFieldRec[j].Type(),
  274. var,
  275. abExtra,
  276. &cbExtra );
  277. switch ( var.vt )
  278. {
  279. case VT_EMPTY:
  280. printf( "n/a " );
  281. break;
  282. case VT_I4:
  283. printf( "%8d ", var.iVal );
  284. break;
  285. case VT_UI4:
  286. printf( "%8u ", var.uiVal );
  287. break;
  288. case VT_FILETIME:
  289. printf( "%8u,%8u ",
  290. var.filetime.dwHighDateTime,
  291. var.filetime.dwLowDateTime );
  292. break;
  293. case VT_I8:
  294. printf( "%12hu ", var.hVal );
  295. break;
  296. }
  297. }
  298. else
  299. {
  300. BOOL fOk = pRec->ReadVariable( aFieldRec[j].Ordinal(),
  301. aFieldRec[j].Mask(),
  302. culFixed,
  303. cTotal,
  304. cFixed,
  305. var,
  306. abExtra,
  307. &cbExtra );
  308. if ( fOk )
  309. {
  310. switch ( var.vt )
  311. {
  312. case VT_LPSTR:
  313. printf( "%s ", var.pszVal );
  314. break;
  315. case VT_LPWSTR:
  316. printf( "%ws ", var.pwszVal );
  317. break;
  318. }
  319. }
  320. }
  321. }
  322. if ( 0 != cField )
  323. printf( "\n" );
  324. }
  325. else if ( pRec->IsFreeRecord() )
  326. {
  327. aSmallInfo[iSection*cRecPerBuf + iRec].Type = Free;
  328. }
  329. else
  330. {
  331. aSmallInfo[iSection*cRecPerBuf + iRec].Type = Virgin;
  332. }
  333. // 1.1 vs 2.0 change // aSmallInfo[iSection*cRecPerBuf + iRec].ulPrev = pRec->ToplevelBlock();
  334. aSmallInfo[iSection*cRecPerBuf + iRec].ulNext = pRec->OverflowBlock();
  335. aSmallInfo[iSection*cRecPerBuf + iRec].Length = pRec->CountRecords();
  336. if ( pRec->CountRecords() == 0 )
  337. {
  338. printf( "Record %u (file offset 0x%x) is zero length!\n",
  339. iSection * cRecPerBuf + iRec,
  340. iSection * sizeof(abTemp) + iRec * cbRec );
  341. }
  342. if ( pRec->OverflowBlock() != 0 )
  343. {
  344. /* printf( ", Overflow = %u:%u (file offset 0x%x)",
  345. pRec->OverflowBlock() / cRecPerBuf,
  346. pRec->OverflowBlock() % cRecPerBuf,
  347. (pRec->OverflowBlock() / cRecPerBuf) * sizeof(abTemp) +
  348. (pRec->OverflowBlock() % cRecPerBuf) * cbRec ); */
  349. }
  350. if (fVerbose)
  351. printf( "\n" );
  352. if ( pRec->IsValidType() )
  353. iRec += pRec->CountRecords();
  354. else
  355. iRec++;
  356. ULONG iPct = (iSection * (100/5) / cTotalSections) * 5;
  357. if (iPct != iCurrentPct)
  358. {
  359. iCurrentPct = iPct;
  360. printf( "Read %u%%\n", iCurrentPct );
  361. }
  362. }
  363. iSection++;
  364. oFile += cbRead;
  365. }
  366. else
  367. {
  368. ULONG Status = GetLastError();
  369. if ( Status == ERROR_HANDLE_EOF )
  370. break;
  371. else
  372. {
  373. printf( "Error %u reading file.\n", Status );
  374. }
  375. }
  376. }
  377. printf( "Read 100%%\n" );
  378. CloseHandle( h );
  379. //
  380. // Now check inter-record state
  381. //
  382. unsigned iRec = 0;
  383. unsigned iCurrentSection = 0;
  384. iCurrentPct = 0;
  385. while ( iRec < iSection * cRecPerBuf )
  386. {
  387. if ( aSmallInfo[iRec].Type == Top )
  388. {
  389. unsigned iOverflowRec = aSmallInfo[iRec].ulNext;
  390. unsigned cOverflowRec = 0;
  391. while ( 0 != iOverflowRec )
  392. {
  393. if ( aSmallInfo[iOverflowRec].Type != Overflow )
  394. {
  395. printf( "Record 0x%x (%u:%u) (file offset 0x%x) should be overflow and is not!\n Top level = 0x%x (%u:%u) (file offset 0x%x)\n",
  396. iOverflowRec,
  397. iOverflowRec / cRecPerBuf,
  398. iOverflowRec % cRecPerBuf,
  399. (iOverflowRec / cRecPerBuf) * sizeof(abTemp) +
  400. (iOverflowRec % cRecPerBuf) * cbRec,
  401. iRec,
  402. iRec / cRecPerBuf,
  403. iRec % cRecPerBuf,
  404. (iRec / cRecPerBuf) * sizeof(abTemp) +
  405. (iRec % cRecPerBuf) * cbRec );
  406. break;
  407. }
  408. iOverflowRec = aSmallInfo[iOverflowRec].ulNext;
  409. cOverflowRec++;
  410. if ( cOverflowRec > aSmallInfo[iRec].ulChainLength )
  411. break;
  412. }
  413. if ( aSmallInfo[iRec].ulChainLength != cOverflowRec )
  414. {
  415. printf( "Record 0x%x (%u:%u) (file offset 0x%x) chain length mismatch %d,%d!\n",
  416. iRec,
  417. iRec / cRecPerBuf,
  418. iRec % cRecPerBuf,
  419. (iRec / cRecPerBuf) * sizeof(abTemp) +
  420. (iRec % cRecPerBuf) * cbRec,
  421. aSmallInfo[iRec].ulChainLength, cOverflowRec );
  422. }
  423. }
  424. if (aSmallInfo[iRec].Length == 0)
  425. {
  426. printf( "%u:%u (file offset 0x%x) zero length record!\n",
  427. iRec / cRecPerBuf,
  428. iRec % cRecPerBuf,
  429. (iRec / cRecPerBuf) * sizeof(abTemp) +
  430. (iRec % cRecPerBuf) * cbRec );
  431. iRec++;
  432. } else {
  433. iRec += aSmallInfo[iRec].Length;
  434. }
  435. if ( (iRec / cRecPerBuf) != iCurrentSection )
  436. {
  437. if (fVerbose)
  438. printf( "Checked section %u\n", iCurrentSection );
  439. ULONG iPct = (iCurrentSection * (100/5) / iSection) * 5;
  440. if (iPct != iCurrentPct)
  441. {
  442. iCurrentPct = iPct;
  443. printf( "Checked %u%%\n", iCurrentPct );
  444. }
  445. iCurrentSection = (iRec / cRecPerBuf);
  446. }
  447. }
  448. printf( "Checked 100%%\n" );
  449. LocalUnlock( hSmallInfo );
  450. LocalFree( hSmallInfo );
  451. return 0;
  452. }