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.

650 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: stgdbg.cxx
  7. //
  8. // Contents: OLE Storage debugger extention DLL
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 8-05-94 kevinro Created
  15. // 5/02/97 bchapman Debugged and added storage features
  16. //
  17. //----------------------------------------------------------------------------
  18. #include "bighdr.h"
  19. #include "stgdbg.h"
  20. PNTSD_EXTENSION_APIS pExtApis;
  21. HANDLE hDbgThread;
  22. HANDLE hDbgProcess;
  23. //
  24. char achTokenBuf[1024];
  25. char *pszTokenNext = NULL;
  26. char *pszToken = NULL;
  27. void InitTokenStr(LPSTR lpszString)
  28. {
  29. if (lpszString)
  30. {
  31. strcpy(achTokenBuf,lpszString);
  32. }
  33. else
  34. {
  35. achTokenBuf[0]=0;
  36. }
  37. pszTokenNext = achTokenBuf;
  38. pszToken = NULL;
  39. }
  40. char *NextToken()
  41. {
  42. return(NULL);
  43. }
  44. //+---------------------------------------------------------------------------
  45. //
  46. // Function: ReadMemory
  47. //
  48. // Synopsis: Reads memory from the debuggee
  49. //
  50. // Effects:
  51. //
  52. // Arguments: [pvAddress] --
  53. // [cbMemory] --
  54. // [pvLocalMemory] --
  55. //
  56. // Requires:
  57. //
  58. // Returns:
  59. //
  60. // Signals:
  61. //
  62. // Modifies:
  63. //
  64. // Algorithm:
  65. //
  66. // History: 8-05-94 kevinro Created
  67. //
  68. // Notes:
  69. //
  70. //----------------------------------------------------------------------------
  71. DWORD
  72. ReadMemory( PVOID pvAddress,
  73. ULONG cbMemory,
  74. PVOID pvLocalMemory)
  75. {
  76. ULONG cbActual = cbMemory;
  77. if (ReadProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
  78. {
  79. if (cbActual != cbMemory)
  80. {
  81. return((DWORD)-1);
  82. }
  83. return(0);
  84. }
  85. return(GetLastError());
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Function: WriteMemory
  90. //
  91. // Synopsis: Writes memory to the debuggee
  92. //
  93. // Effects:
  94. //
  95. // Arguments: [pvLocalMemory] --
  96. // [cbMemory] --
  97. // [pvAddress] --
  98. //
  99. // Requires:
  100. //
  101. // Returns:
  102. //
  103. // Signals:
  104. //
  105. // Modifies:
  106. //
  107. // Algorithm:
  108. //
  109. // History: 8-05-94 kevinro Created
  110. //
  111. // Notes:
  112. //
  113. //----------------------------------------------------------------------------
  114. DWORD
  115. WriteMemory(PVOID pvLocalMemory,
  116. ULONG cbMemory,
  117. PVOID pvAddress)
  118. {
  119. ULONG cbActual = cbMemory;
  120. if (WriteProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
  121. {
  122. if (cbActual != cbMemory)
  123. {
  124. return((DWORD)-1);
  125. }
  126. return(0);
  127. }
  128. return(GetLastError());
  129. }
  130. #define AllocHeap(x) RtlAllocateHeap(RtlProcessHeap(), 0, x)
  131. #define FreeHeap(x) RtlFreeHeap(RtlProcessHeap(), 0, x)
  132. DWORD
  133. GetOleTlsEntry(PVOID * ppvValue)
  134. {
  135. NTSTATUS Status;
  136. THREAD_BASIC_INFORMATION ThreadInfo;
  137. ULONG cbReturned;
  138. TEB Teb;
  139. Status = NtQueryInformationThread( hDbgThread,
  140. ThreadBasicInformation,
  141. &ThreadInfo,
  142. sizeof(ThreadInfo),
  143. &cbReturned);
  144. if (!NT_SUCCESS(Status))
  145. {
  146. return(Status);
  147. }
  148. ReadMemory(ThreadInfo.TebBaseAddress, sizeof(TEB), &Teb);
  149. *ppvValue = Teb.ReservedForOle;
  150. return(0);
  151. }
  152. DWORD
  153. GetOleThreadBase(DWORD *psmBase)
  154. {
  155. SOleTlsData oleBuf;
  156. PVOID OleTlsAddr;
  157. DWORD err;
  158. if(err = GetOleTlsEntry(&OleTlsAddr))
  159. return err;
  160. if(err = ReadMemory(OleTlsAddr, sizeof(SOleTlsData), &oleBuf))
  161. return err;
  162. *psmBase = (DWORD)oleBuf.pvThreadBase;
  163. return 0;
  164. }
  165. void ShowBinaryData(PBYTE pData,
  166. DWORD cbData)
  167. {
  168. DWORD i;
  169. char line[20];
  170. PNTSD_EXTENSION_APIS lpExt = pExtApis;
  171. line[16] = '\0';
  172. if (cbData > 65536)
  173. {
  174. ntsdPrintf("ShowBinaryData: Data @%x is said to be %d bytes in length\n");
  175. ntsdPrintf(" Rejecting request. Corrupt data\n");
  176. return;
  177. }
  178. for (; cbData > 0 ; )
  179. {
  180. for (i = 0; i < 16 && cbData > 0 ; i++, cbData-- )
  181. {
  182. ntsdPrintf(" %02x", (unsigned) *pData);
  183. if (isprint(*pData))
  184. line[i] = *pData;
  185. else
  186. line[i] = '.';
  187. pData++;
  188. }
  189. if (i < 16)
  190. {
  191. for (;i < 16 ; i++ )
  192. {
  193. ntsdPrintf(" ");
  194. line[i] = ' ';
  195. }
  196. }
  197. ntsdPrintf("\t%s\n",line);
  198. if (lpExt->lpCheckControlCRoutine())
  199. {
  200. break;
  201. }
  202. }
  203. }
  204. BOOL
  205. IsDebug_olethk32()
  206. {
  207. ULONG addr;
  208. DWORD dwValue;
  209. addr = ntsdGetExpr("olethk32!oledbgCheck_olethk32");
  210. if (addr == 0)
  211. {
  212. ntsdPrintf("warning: olethk32 not debug version\n");
  213. return(0);
  214. }
  215. if (ReadMemory((LPVOID)addr,sizeof(dwValue),(PVOID)&dwValue))
  216. {
  217. ntsdPrintf("warning: could not read check value at %x\n",addr);
  218. return(0);
  219. }
  220. if (dwValue != 0x12345678)
  221. {
  222. ntsdPrintf("warning: olethk32!oledbgCheck_olethk32 value wrong\n");
  223. ntsdPrintf("warning: suspect wrong symbols for olethk32\n");
  224. return(0);
  225. }
  226. return(1);
  227. }
  228. BOOL
  229. IsDebug_ole32()
  230. {
  231. ULONG addr;
  232. DWORD dwValue;
  233. addr = ntsdGetExpr("ole32!oledbgCheck_ole32");
  234. if (addr == 0)
  235. {
  236. ntsdPrintf("warning: ole32 not debug version\n");
  237. return(0);
  238. }
  239. if (ReadMemory((LPVOID)addr,sizeof(dwValue),(PVOID)&dwValue))
  240. {
  241. ntsdPrintf("warning: could not read check value at %x\n",addr);
  242. return(0);
  243. }
  244. if (dwValue != 0x12345678)
  245. {
  246. ntsdPrintf("warning: olethk32!oledbgCheck_ole32 value wrong\n");
  247. ntsdPrintf("warning: suspect wrong symbols for ole32\n");
  248. return(0);
  249. }
  250. return(1);
  251. }
  252. //+---------------------------------------------------------------------------
  253. //
  254. // Function: DumpVtbl
  255. //
  256. // Synopsis: Dumps a vtbl to the debugger
  257. //
  258. // Effects: Given a pointer to a vtbl, output the name of the vtbl, and
  259. // its contents to the debugger.
  260. //
  261. // Arguments: [pvtbl] -- Address of vtbl
  262. // [pszCommand] -- Symbolic expression for pvtbl
  263. //
  264. // History: 8-07-94 kevinro Created
  265. //
  266. //----------------------------------------------------------------------------
  267. //extern "C"
  268. void
  269. DumpVtbl(PVOID pvtbl, LPSTR pszCommand)
  270. {
  271. DWORD dwVtblOffset;
  272. char achNextSymbol[256];
  273. if (pvtbl == 0)
  274. {
  275. // Can't handle objects at zero
  276. ntsdPrintf("%s has a vtbl pointer of NULL\n",pszCommand);
  277. return;
  278. }
  279. if ((DWORD)pvtbl == 0xdededede)
  280. {
  281. // Can't handle objects at zero
  282. ntsdPrintf("%s may be deleted memory. pvtbl==0xdededede\n",pszCommand);
  283. return;
  284. }
  285. // This value points at the VTBL. Find a symbol for the VTBL
  286. ntsdGetSymbol((LPVOID)pvtbl,(UCHAR *)achNextSymbol,(LPDWORD)&dwVtblOffset);
  287. // If the dwVtblOffset is not zero, then we are pointing into the table.
  288. // This could mean multiple inheritance. We could be tricky, and try to
  289. // determine the vtbl by backing up here. Maybe later
  290. if (dwVtblOffset != 0)
  291. {
  292. ntsdPrintf("Closest Previous symbol is %s at 0x%x (offset -0x%x)\n",
  293. achNextSymbol,
  294. (DWORD)pvtbl - dwVtblOffset,
  295. dwVtblOffset);
  296. return;
  297. }
  298. ntsdPrintf("0x%08x -->\t %s\n",pvtbl,achNextSymbol);
  299. // vtbl entries should always point at functions. Therefore, we should
  300. // always have a displacement of zero. To check for the end of the table
  301. // we will reevaluate the vtbl pointer. If the offset isn't what we
  302. // expected, then we are done.
  303. DWORD dwIndex;
  304. for (dwIndex = 0 ; dwIndex < 4096 ; dwIndex += 4)
  305. {
  306. DWORD dwVtblEntry;
  307. ntsdGetSymbol((LPVOID)((DWORD)pvtbl+dwIndex),
  308. (UCHAR *)achNextSymbol,
  309. (LPDWORD)&dwVtblOffset);
  310. if (dwVtblOffset != dwIndex)
  311. {
  312. //
  313. // May have moved on to another vtable
  314. //
  315. #ifdef DBG_OLEDBG
  316. ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
  317. ntsdPrintf("Moved to another table?\n");
  318. #endif
  319. return;
  320. }
  321. if (ReadMemory((LPVOID)((DWORD)pvtbl+dwIndex),
  322. sizeof(dwVtblEntry),
  323. (PVOID)&dwVtblEntry))
  324. {
  325. //
  326. // Must be off the end of a page or something.
  327. //
  328. #ifdef DBG_OLEDBG
  329. ntsdPrintf("End of page?\n");
  330. #endif
  331. return;
  332. }
  333. // If the function is at zero, then must be at end of table
  334. if (dwVtblEntry == 0)
  335. {
  336. #ifdef DBG_OLEDBG
  337. ntsdPrintf("dwVtblEntry is zero. Must be end of table\n");
  338. return;
  339. #endif
  340. }
  341. // Now, determine the symbol for the entry in the vtbl
  342. ntsdGetSymbol((LPVOID)dwVtblEntry,
  343. (UCHAR *)achNextSymbol,
  344. (LPDWORD)&dwVtblOffset);
  345. // If it doesn't point to the start of a routine, then it
  346. // probably isn't part of the vtbl
  347. if (dwVtblOffset != 0)
  348. {
  349. #ifdef DBG_OLEDBG
  350. ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
  351. ntsdPrintf("Doesn't point to function?\n");
  352. #endif
  353. return;
  354. }
  355. ntsdPrintf(" 0x%08x\t %s\n",dwVtblEntry,achNextSymbol);
  356. }
  357. ntsdPrintf("Wow, there were at least 1024 entries in the table!\n");
  358. }
  359. void
  360. Dump_CFileStream(
  361. PVOID pv_arg,
  362. LPSTR pszCommand)
  363. {
  364. CFileStream *pflst = (CFileStream *)pv_arg;
  365. ntsdPrintf("_sig = %8x", pflst->_sig);
  366. switch(pflst->_sig)
  367. {
  368. case CFILESTREAM_SIG:
  369. ntsdPrintf("\t(Valid)\n");
  370. break;
  371. case CFILESTREAM_SIGDEL:
  372. ntsdPrintf("\t(Deleted)\n");
  373. break;
  374. default:
  375. ntsdPrintf("\t(Invalid Signature)\n");
  376. break;
  377. }
  378. ntsdPrintf("_pgfst = %x\n", pflst->_pgfst);
  379. ntsdPrintf("_ppc = %x\n", pflst->_ppc);
  380. ntsdPrintf("_hfile = %2x; _hMapObject = %2x\n",
  381. pflst->_hFile, pflst->_hMapObject);
  382. ntsdPrintf("_hReserved = %2x; _hPreDuped = %2x\n",
  383. pflst->_hReserved, pflst->_hPreDuped);
  384. ntsdPrintf("_pbBaseAddr = %8x\n", pflst->_pbBaseAddr);
  385. ntsdPrintf("_cbViewSize = %6x\n", pflst->_cbViewSize);
  386. }
  387. void
  388. Dump_CGlobalFileStream(
  389. PVOID pv_arg,
  390. LPSTR pszCommand)
  391. {
  392. CGlobalFileStream *pgfst = (CGlobalFileStream *)pv_arg;
  393. ntsdPrintf("_df = %8x\n", pgfst->_df);
  394. ntsdPrintf("_dwStartFlags = %x\n", pgfst->_dwStartFlags);
  395. ntsdPrintf("_pMalloc = %x\n", pgfst->_pMalloc);
  396. ntsdPrintf("_ulLowPos = %x\n", pgfst->_ulLowPos);
  397. #ifdef USE_FILEMAPPING
  398. ntsdPrintf("_cbMappedFileSize = %6x\n", pgfst->_cbMappedFileSize);
  399. ntsdPrintf("_cbMappedCommitSize = %6x\n", pgfst->_cbMappedCommitSize);
  400. ntsdPrintf("_dwMapFlags = %x\n", pgfst->_dwMapFlags);
  401. ntsdPrintf("_awcMapName = %ws\n", pgfst->_awcMapName);
  402. #endif
  403. ntsdPrintf("_awcPath = %ws\n", pgfst->_awcPath);
  404. #ifdef ASYNC
  405. ntsdPrintf("_dwTerminate = %x\n", pgfst->_dwTerminate);
  406. ntsdPrintf("_ulHighWater = %x\n", pgfst->_ulHighWater);
  407. ntsdPrintf("_ulFailurePoint = %x\n", pgfst->_ulFailurePoint);
  408. #endif
  409. ntsdPrintf("_ulLastFilePos = %x\n", pgfst->_ulLastFilePos);
  410. }
  411. extern "C" { // Everything from here down is Extern "C"
  412. void
  413. punk( HANDLE hProcess,
  414. HANDLE hThread,
  415. DWORD dwCurrentPc,
  416. PNTSD_EXTENSION_APIS lpExt,
  417. LPSTR pszCommand)
  418. {
  419. PVOID punk;
  420. PVOID pvtbl;
  421. InitDebugHelp(hProcess, hThread, lpExt);
  422. // Evalute the first pointer. This is a pointer to the object
  423. punk = (PVOID) ntsdGetExpr(pszCommand);
  424. if (punk == NULL)
  425. {
  426. // Can't handle objects at zero
  427. ntsdPrintf("%s is not a valid pointer\n",pszCommand);
  428. return;
  429. }
  430. // Now, read the first DWORD of this memory location
  431. // This is a pointer to the table
  432. if (ReadMemory(punk,sizeof(pvtbl),(PVOID)&pvtbl))
  433. {
  434. ntsdPrintf("Couldn't read memory at %x\n",punk);
  435. return;
  436. }
  437. DumpVtbl(pvtbl,pszCommand);
  438. }
  439. void
  440. vtbl( HANDLE hProcess,
  441. HANDLE hThread,
  442. DWORD dwCurrentPc,
  443. PNTSD_EXTENSION_APIS lpExt,
  444. LPSTR pszCommand)
  445. {
  446. PVOID pvtbl;
  447. InitDebugHelp(hProcess, hThread, lpExt);
  448. // Evalute the first pointer. This is a pointer to the table
  449. pvtbl = (PVOID) ntsdGetExpr(pszCommand);
  450. DumpVtbl(pvtbl,pszCommand);
  451. }
  452. void
  453. expr( HANDLE hProcess,
  454. HANDLE hThread,
  455. DWORD dwCurrentPc,
  456. PNTSD_EXTENSION_APIS lpExt,
  457. LPSTR pszCommand)
  458. {
  459. InitDebugHelp(hProcess, hThread, lpExt);
  460. UCHAR symbol[256];
  461. DWORD expr;
  462. DWORD disp;
  463. expr = ntsdGetExpr(pszCommand);
  464. ntsdGetSymbol((LPVOID)expr,(UCHAR *)symbol,(LPDWORD)&disp);
  465. ntsdPrintf("expr: %x (%d) %s+0x%x\n", expr, expr, symbol, disp);
  466. }
  467. void
  468. isdbg( HANDLE hProcess,
  469. HANDLE hThread,
  470. DWORD dwCurrentPc,
  471. PNTSD_EXTENSION_APIS lpExt,
  472. LPSTR pszCommand)
  473. {
  474. InitDebugHelp(hProcess, hThread, lpExt);
  475. if (IsDebug_ole32())
  476. {
  477. ntsdPrintf("ole32.dll is debug\n");
  478. }
  479. if (IsDebug_olethk32())
  480. {
  481. ntsdPrintf("olethk32.dll is debug\n");
  482. }
  483. }
  484. void
  485. smbase(
  486. HANDLE hProcess,
  487. HANDLE hThread,
  488. DWORD dwCurrentPc,
  489. PNTSD_EXTENSION_APIS lpExt,
  490. LPSTR pszCommand)
  491. {
  492. DWORD smBase;
  493. InitDebugHelp(hProcess, hThread, lpExt);
  494. GetOleThreadBase(&smBase);
  495. ntsdPrintf("Shared memory base address = %x\n", smBase);
  496. }
  497. void
  498. pflst( HANDLE hProcess,
  499. HANDLE hThread,
  500. DWORD dwCurrentPc,
  501. PNTSD_EXTENSION_APIS lpExt,
  502. LPSTR pszCommand)
  503. {
  504. PVOID pflst;
  505. char buf[sizeof(CFileStream)];
  506. InitDebugHelp(hProcess, hThread, lpExt);
  507. pflst = (PVOID) ntsdGetExpr(pszCommand);
  508. if (ReadMemory(pflst,sizeof(CFileStream),(PVOID)buf))
  509. {
  510. ntsdPrintf("Couldn't read all %d bytes at 0x%x\n",
  511. sizeof(CFileStream), pflst);
  512. return;
  513. }
  514. Dump_CFileStream(buf,pszCommand);
  515. }
  516. void
  517. pgfst( HANDLE hProcess,
  518. HANDLE hThread,
  519. DWORD dwCurrentPc,
  520. PNTSD_EXTENSION_APIS lpExt,
  521. LPSTR pszCommand)
  522. {
  523. PVOID pgfst;
  524. char buf[sizeof(CGlobalFileStream)];
  525. InitDebugHelp(hProcess, hThread, lpExt);
  526. pgfst = (PVOID) ntsdGetExpr(pszCommand);
  527. if (ReadMemory(pgfst,sizeof(CGlobalFileStream),(PVOID)buf))
  528. {
  529. ntsdPrintf("Couldn't read all %d bytes at 0x%x\n",
  530. sizeof(CGlobalFileStream), pgfst);
  531. return;
  532. }
  533. Dump_CGlobalFileStream(buf,pszCommand);
  534. }
  535. void
  536. help( HANDLE hProcess,
  537. HANDLE hThread,
  538. DWORD dwCurrentPc,
  539. PNTSD_EXTENSION_APIS lpExt,
  540. LPSTR pszCommand)
  541. {
  542. InitDebugHelp(hProcess, hThread, lpExt);
  543. ntsdPrintf(" help This Message\n");
  544. ntsdPrintf("COM commands:\n");
  545. ntsdPrintf(" isdbg Determine if DLL's are debug\n");
  546. ntsdPrintf(" punk <expr> Dump IUnknown vtbl\n");
  547. ntsdPrintf(" vtbl <expr> Dump vtbl\n");
  548. ntsdPrintf("Storage commands:\n");
  549. ntsdPrintf(" smbase Print shared memory base address\n");
  550. ntsdPrintf(" pflst <expr> Dump CFileStream\n");
  551. ntsdPrintf(" pgfst <expr> Dump CGlobalFileStream\n");
  552. }
  553. }; // end Extern "C"