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.

1937 lines
51 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. inetdbg.c
  5. Abstract:
  6. This function contains the default ntsd debugger extensions
  7. Author:
  8. Mark Lucovsky (markl) 09-Apr-1991
  9. Revision History:
  10. --*/
  11. #ifdef DBG
  12. #undef DBG
  13. #endif
  14. #define dllexp
  15. #define CALL_STACK_BUF_SIZE 1024
  16. //
  17. // To obtain the private & protected members of C++ class,
  18. // let me fake the "private" keyword
  19. //
  20. # define private public
  21. # define protected public
  22. #define INCL_INETSRV_INCS
  23. #include <tigris.hxx>
  24. #include "smtpcli.h"
  25. #include <ntsdexts.h>
  26. #include "nntpdbgp.h"
  27. extern "C" {
  28. #if 0
  29. void __cdecl main( void )
  30. {
  31. ;
  32. }
  33. #endif
  34. }
  35. //
  36. // Globals that we have to have because we included others' headers
  37. //
  38. CShareLockNH CNewsGroupCore::m_rglock[GROUP_LOCK_ARRAY_SIZE];
  39. //DECLARE_DEBUG_PRINTS_OBJECT( );
  40. NTSD_EXTENSION_APIS ExtensionApis;
  41. HANDLE ExtensionCurrentProcess;
  42. // globals
  43. char g_szBuffer [1024]; // temp buffer for misc stuff
  44. VOID
  45. PrintUsage(
  46. VOID
  47. );
  48. VOID
  49. PrintSystemTime(
  50. FILETIME* pftTime
  51. );
  52. VOID
  53. PrintString(
  54. LPSTR lp1,
  55. LPSTR lp2
  56. );
  57. VOID
  58. DbgPrintInstance(
  59. NNTP_SERVER_INSTANCE* pInstance
  60. );
  61. VOID
  62. DbgPrintNewstree(
  63. CNewsTree* ptree,
  64. DWORD nGroups
  65. );
  66. CNewsGroup*
  67. DbgPrintNewsgroup(
  68. CNewsGroup * pSrcGroup
  69. );
  70. CNNTPVRoot*
  71. DbgPrintVRoot(
  72. CNNTPVRoot *pDestGroup
  73. );
  74. VOID
  75. DbgPrintVRootList(
  76. CNNTPVRoot* pFirstVRoot,
  77. DWORD nVRoots
  78. );
  79. VOID
  80. DbgPrintDebugVRootList(
  81. CNNTPVRoot* pFirstVRoot,
  82. DWORD nVRoots
  83. );
  84. void
  85. DbgPrintVRootTable(
  86. CNNTPVRootTable * pVRTable
  87. );
  88. VOID
  89. DbgDumpPool(
  90. CSmtpClientPool* pSCPool
  91. );
  92. VOID
  93. DbgDumpFeedBlock(
  94. PFEED_BLOCK feedBlock
  95. );
  96. VOID
  97. DbgDumpFeedList(
  98. CFeedList* pSrcFeedList,
  99. CFeedList* pDstFeedList
  100. );
  101. VOID
  102. DbgDumpCPool(CPool* pCPool, DWORD dwSignature, LPCSTR symbol);
  103. VOID
  104. SkipArgument( LPSTR* ppArg )
  105. {
  106. // skip the arg and the spaces after
  107. while( *(*ppArg) != ' ' ) (*ppArg)++;
  108. while( *(*ppArg) == ' ' ) (*ppArg)++;
  109. }
  110. //
  111. // Here and elsewhere we use "nntpsvc" prefix in GetExpression() calls.
  112. //
  113. #define DEBUG_PREFIX "&nntpsvc!"
  114. #define DumpDword( symbol ) \
  115. { \
  116. DWORD dw = GetExpression( DEBUG_PREFIX symbol ); \
  117. DWORD dwValue = 0; \
  118. \
  119. if ( dw ) \
  120. { \
  121. if ( ReadMemory( (LPVOID) dw, \
  122. &dwValue, \
  123. sizeof(dwValue), \
  124. NULL )) \
  125. { \
  126. dprintf( "\t" symbol " = %8d (0x%8lx)\n", \
  127. dwValue, \
  128. dwValue ); \
  129. } \
  130. } \
  131. }
  132. #define DumpCPool( symbol, signature ) \
  133. { \
  134. DbgDumpCPool((CPool*)GetExpression(DEBUG_PREFIX symbol), signature, symbol ); \
  135. }
  136. //
  137. // util functions
  138. //
  139. VOID
  140. CopyUnicodeStringIntoAscii(
  141. IN LPSTR AsciiString,
  142. IN LPWSTR UnicodeString
  143. )
  144. {
  145. while ( (*AsciiString++ = (CHAR)*UnicodeString++) != '\0');
  146. } // CopyUnicodeStringIntoAscii
  147. DECLARE_API( help )
  148. {
  149. INIT_API();
  150. PrintUsage();
  151. }
  152. DECLARE_API( cpool )
  153. {
  154. CPool* pCPool;
  155. INIT_API();
  156. while (*lpArgumentString == ' ')
  157. lpArgumentString++;
  158. if ( !*lpArgumentString )
  159. {
  160. PrintUsage();
  161. return;
  162. }
  163. //
  164. // Get the address of the instance
  165. //
  166. pCPool = (CPool*)GetExpression( lpArgumentString );
  167. if ( !pCPool )
  168. {
  169. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  170. return;
  171. }
  172. DbgDumpCPool(pCPool, 0, NULL);
  173. }
  174. DECLARE_API( cpools )
  175. {
  176. INIT_API();
  177. //
  178. // Dump Nntpsvc cpools
  179. //
  180. dprintf("Nntpsvc Cpools:\n");
  181. DumpCPool("CArticle__gArticlePool",ARTICLE_SIGNATURE);
  182. DumpCPool("CCIOAllocator__IOPool",CIO_SIGNATURE) ;
  183. DumpCPool("CFeed__gFeedPool",FEED_SIGNATURE) ;
  184. DumpCPool("CChannel__gChannelPool",CHANNEL_SIGNATURE) ;
  185. DumpCPool("CSessionSocket__gSocketAllocator",SESSION_SOCKET_SIGNATURE) ;
  186. DumpCPool("CSessionState__gStatePool",SESSION_STATE_SIGNATURE) ;
  187. DumpCPool("CXoverIndex__gCacheAllocator",1) ;
  188. DumpCPool("CXoverIndex__gXoverIndexAllocator",1) ;
  189. }
  190. DECLARE_API( instance )
  191. /*++
  192. Routine Description:
  193. This function is called as an NTSD extension to format and dump
  194. an object attributes structure.
  195. Arguments:
  196. hCurrentProcess - Supplies a handle to the current process (at the
  197. time the extension was called).
  198. hCurrentThread - Supplies a handle to the current thread (at the
  199. time the extension was called).
  200. CurrentPc - Supplies the current pc at the time the extension is
  201. called.
  202. lpExtensionApis - Supplies the address of the functions callable
  203. by this extension.
  204. lpArgumentString - Supplies the asciiz string that describes the
  205. ansi string to be dumped.
  206. Return Value:
  207. None.
  208. --*/
  209. {
  210. NNTP_SERVER_INSTANCE *pSrcInst, *pDstInst;
  211. DWORD cbInst = sizeof(NNTP_SERVER_INSTANCE);
  212. INIT_API();
  213. while (*lpArgumentString == ' ')
  214. lpArgumentString++;
  215. if ( !*lpArgumentString )
  216. {
  217. PrintUsage();
  218. return;
  219. }
  220. //
  221. // Get the address of the instance
  222. //
  223. pSrcInst = (NNTP_SERVER_INSTANCE*)GetExpression( lpArgumentString );
  224. if ( !pSrcInst )
  225. {
  226. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  227. return;
  228. }
  229. dprintf("Instance object is 0x%p\n", pSrcInst);
  230. //
  231. // Allocate memory in our address space so we can read data from the debuggee's address space
  232. //
  233. pDstInst = (NNTP_SERVER_INSTANCE*) DbgAlloc( cbInst );
  234. if( !pDstInst )
  235. {
  236. dprintf( "nntpdbg: Unable to allocate memory \n");
  237. return;
  238. }
  239. if( !ReadMemory( pSrcInst, pDstInst, cbInst, NULL ) )
  240. {
  241. dprintf("Could not get data at 0x%x\n", pSrcInst);
  242. DbgFree( pDstInst );
  243. return;
  244. }
  245. //
  246. // Dump the the server instance
  247. //
  248. DbgPrintInstance( pDstInst );
  249. DbgFree( pDstInst );
  250. }
  251. DECLARE_API( newstree )
  252. /*++
  253. Routine Description:
  254. This function is called as an NTSD extension to format and dump
  255. an object attributes structure.
  256. Arguments:
  257. hCurrentProcess - Supplies a handle to the current process (at the
  258. time the extension was called).
  259. hCurrentThread - Supplies a handle to the current thread (at the
  260. time the extension was called).
  261. CurrentPc - Supplies the current pc at the time the extension is
  262. called.
  263. lpExtensionApis - Supplies the address of the functions callable
  264. by this extension.
  265. lpArgumentString - Supplies the asciiz string that describes the
  266. ansi string to be dumped.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. CNewsTree *pSrcTree, *pDstTree;
  272. DWORD cbTree = sizeof(CNewsTree);
  273. DWORD nGroups = 0;
  274. INIT_API();
  275. while (*lpArgumentString == ' ')
  276. lpArgumentString++;
  277. if ( !*lpArgumentString )
  278. {
  279. PrintUsage();
  280. return;
  281. }
  282. //
  283. // Get the address of the global newstree pointer
  284. //
  285. pSrcTree = (CNewsTree*)GetExpression( lpArgumentString );
  286. if ( !pSrcTree )
  287. {
  288. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  289. return;
  290. }
  291. // same as doing pSrcTree = *ppSrcTree !!
  292. dprintf("Newstree object is 0x%p\n", pSrcTree);
  293. SkipArgument( &lpArgumentString );
  294. nGroups = atoi( lpArgumentString );
  295. //
  296. // Allocate memory in our address space so we can read data from the debuggee's address space
  297. //
  298. pDstTree = (CNewsTree*) DbgAlloc( cbTree );
  299. if( !pDstTree )
  300. {
  301. dprintf( "nntpdbg: Unable to allocate memory \n");
  302. return;
  303. }
  304. if( !ReadMemory( pSrcTree, pDstTree, cbTree, NULL ) )
  305. {
  306. dprintf("Could not get data at 0x%x\n", pSrcTree);
  307. DbgFree( pDstTree );
  308. return;
  309. }
  310. //
  311. // Dump the newstree
  312. //
  313. DbgPrintNewstree( pDstTree, nGroups );
  314. DbgFree( pDstTree );
  315. }
  316. DECLARE_API( vrootlist )
  317. /*++
  318. Routine Description:
  319. This function is called as an NTSD extension to format and dump
  320. an object attributes structure.
  321. Arguments:
  322. hCurrentProcess - Supplies a handle to the current process (at the
  323. time the extension was called).
  324. hCurrentThread - Supplies a handle to the current thread (at the
  325. time the extension was called).
  326. CurrentPc - Supplies the current pc at the time the extension is
  327. called.
  328. lpExtensionApis - Supplies the address of the functions callable
  329. by this extension.
  330. lpArgumentString - Supplies the asciiz string that describes the
  331. ansi string to be dumped.
  332. Return Value:
  333. None.
  334. --*/
  335. {
  336. CNNTPVRoot *pFirstVRoot;
  337. DWORD nVRoots = 0;
  338. INIT_API();
  339. while (*lpArgumentString == ' ')
  340. lpArgumentString++;
  341. if ( !*lpArgumentString )
  342. {
  343. PrintUsage();
  344. return;
  345. }
  346. //
  347. // Get the address of the first vroot
  348. //
  349. pFirstVRoot = (CNNTPVRoot*)GetExpression( lpArgumentString );
  350. if ( !pFirstVRoot )
  351. {
  352. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  353. return;
  354. }
  355. SkipArgument( &lpArgumentString );
  356. nVRoots = atoi( lpArgumentString );
  357. //
  358. // Dump the list
  359. //
  360. DbgPrintVRootList( pFirstVRoot, nVRoots );
  361. }
  362. DECLARE_API( newsgroup )
  363. /*++
  364. Routine Description:
  365. This function is called as an NTSD extension to format and dump
  366. an object attributes structure.
  367. Arguments:
  368. hCurrentProcess - Supplies a handle to the current process (at the
  369. time the extension was called).
  370. hCurrentThread - Supplies a handle to the current thread (at the
  371. time the extension was called).
  372. CurrentPc - Supplies the current pc at the time the extension is
  373. called.
  374. lpExtensionApis - Supplies the address of the functions callable
  375. by this extension.
  376. lpArgumentString - Supplies the asciiz string that describes the
  377. ansi string to be dumped.
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. CNewsGroup* pSrcGroup;
  383. INIT_API();
  384. while (*lpArgumentString == ' ')
  385. lpArgumentString++;
  386. if ( !*lpArgumentString )
  387. {
  388. PrintUsage();
  389. return;
  390. }
  391. //
  392. // Treat the argument as the address of a CNewsGroup struct
  393. // NOTE: pSrcGroup is an address in the debuggee's address space !
  394. //
  395. pSrcGroup = (CNewsGroup*)GetExpression( lpArgumentString );
  396. if ( !pSrcGroup )
  397. {
  398. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  399. return;
  400. }
  401. //
  402. // Dump the CNewsGroup object
  403. //
  404. DbgPrintNewsgroup( pSrcGroup );
  405. }
  406. DECLARE_API( vroot )
  407. /*++
  408. Routine Description:
  409. This function is called as an NTSD extension to format and dump
  410. an object attributes structure.
  411. Arguments:
  412. hCurrentProcess - Supplies a handle to the current process (at the
  413. time the extension was called).
  414. hCurrentThread - Supplies a handle to the current thread (at the
  415. time the extension was called).
  416. CurrentPc - Supplies the current pc at the time the extension is
  417. called.
  418. lpExtensionApis - Supplies the address of the functions callable
  419. by this extension.
  420. lpArgumentString - Supplies the asciiz string that describes the
  421. ansi string to be dumped.
  422. Return Value:
  423. None.
  424. --*/
  425. {
  426. CNNTPVRoot* pVroot = NULL;
  427. INIT_API();
  428. while (*lpArgumentString == ' ')
  429. lpArgumentString++;
  430. if ( !*lpArgumentString )
  431. {
  432. PrintUsage();
  433. return;
  434. }
  435. //
  436. // Treat the argument as the address of a CNNTPVRoot struct
  437. // NOTE: pVroot is an address in the debuggee's address space !
  438. //
  439. pVroot = (CNNTPVRoot*)GetExpression( lpArgumentString );
  440. if ( !pVroot )
  441. {
  442. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  443. return;
  444. }
  445. //
  446. // Dump the CNNTPVRoot object
  447. //
  448. DbgPrintVRoot( pVroot );
  449. }
  450. DECLARE_API( vrtable )
  451. /*++
  452. Routine Description:
  453. This function is called as an NTSD extension to format and dump
  454. an object attributes structure.
  455. Arguments:
  456. hCurrentProcess - Supplies a handle to the current process (at the
  457. time the extension was called).
  458. hCurrentThread - Supplies a handle to the current thread (at the
  459. time the extension was called).
  460. CurrentPc - Supplies the current pc at the time the extension is
  461. called.
  462. lpExtensionApis - Supplies the address of the functions callable
  463. by this extension.
  464. lpArgumentString - Supplies the asciiz string that describes the
  465. ansi string to be dumped.
  466. Return Value:
  467. None.
  468. --*/
  469. {
  470. CNNTPVRootTable* pVRTable = NULL;
  471. INIT_API();
  472. while (*lpArgumentString == ' ')
  473. lpArgumentString++;
  474. if ( !*lpArgumentString )
  475. {
  476. PrintUsage();
  477. return;
  478. }
  479. //
  480. // Treat the argument as the address of a CNNTPVRootTable struct
  481. // NOTE: pVRTable is an address in the debuggee's address space !
  482. //
  483. pVRTable = (CNNTPVRootTable*)GetExpression( lpArgumentString );
  484. if ( !pVRTable )
  485. {
  486. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  487. return;
  488. }
  489. //
  490. // Dump the CNNTPVRootTable object
  491. //
  492. DbgPrintVRootTable( pVRTable );
  493. }
  494. DECLARE_API( sockets )
  495. /*++
  496. Routine Description:
  497. This function is called as an NTSD extension to format and dump
  498. an object attributes structure.
  499. Arguments:
  500. hCurrentProcess - Supplies a handle to the current process (at the
  501. time the extension was called).
  502. hCurrentThread - Supplies a handle to the current thread (at the
  503. time the extension was called).
  504. CurrentPc - Supplies the current pc at the time the extension is
  505. called.
  506. lpExtensionApis - Supplies the address of the functions callable
  507. by this extension.
  508. lpArgumentString - Supplies the asciiz string that describes the
  509. ansi string to be dumped.
  510. Return Value:
  511. None.
  512. --*/
  513. {
  514. CSessionSocket *pSrcSocket, *pDstSocket;
  515. DWORD cbSocket = sizeof(CSessionSocket);
  516. INIT_API();
  517. while (*lpArgumentString == ' ')
  518. lpArgumentString++;
  519. if ( !*lpArgumentString )
  520. {
  521. PrintUsage();
  522. return;
  523. }
  524. //
  525. // Get the address of the socket obj
  526. //
  527. pSrcSocket = (CSessionSocket*)GetExpression( lpArgumentString );
  528. if ( !pSrcSocket )
  529. {
  530. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  531. return;
  532. }
  533. dprintf("Socket object is 0x%p\n", pSrcSocket);
  534. //
  535. // Allocate memory in our address space so we can read data from the debuggee's address space
  536. //
  537. pDstSocket = (CSessionSocket*) DbgAlloc( cbSocket );
  538. if( !pDstSocket )
  539. {
  540. dprintf( "nntpdbg: Unable to allocate memory \n");
  541. return;
  542. }
  543. if( !ReadMemory( pSrcSocket, pDstSocket, cbSocket, NULL ) )
  544. {
  545. dprintf("Could not get data at 0x%x\n", pSrcSocket);
  546. DbgFree( pDstSocket );
  547. return;
  548. }
  549. //
  550. // Dump the socket obj
  551. //
  552. dprintf(" ========== socket object =========== \n");
  553. dprintf(" Prev = 0x%p Next = 0x%p \n", pDstSocket->m_pPrev, pDstSocket->m_pPrev);
  554. dprintf(" Sink = 0x%p \n", pDstSocket->m_pSink );
  555. dprintf(" Port = 0x%08lx \n", pDstSocket->m_nntpPort );
  556. dprintf(" ClientContext = 0x%p \n", pDstSocket->m_context );
  557. dprintf(" ========== socket object =========== \n");
  558. DbgFree( pDstSocket );
  559. }
  560. DECLARE_API( smtp )
  561. /*++
  562. Routine Description:
  563. This function is called as an NTSD extension to format and dump
  564. an object attributes structure.
  565. Arguments:
  566. hCurrentProcess - Supplies a handle to the current process (at the
  567. time the extension was called).
  568. hCurrentThread - Supplies a handle to the current thread (at the
  569. time the extension was called).
  570. CurrentPc - Supplies the current pc at the time the extension is
  571. called.
  572. lpExtensionApis - Supplies the address of the functions callable
  573. by this extension.
  574. lpArgumentString - Supplies the asciiz string that describes the
  575. ansi string to be dumped.
  576. Return Value:
  577. None.
  578. --*/
  579. {
  580. CSmtpClientPool *pSrcSCPool, *pDstSCPool;
  581. DWORD cbSCPool = sizeof(CSmtpClientPool);
  582. INIT_API();
  583. //
  584. // Get the address of the global newstree pointer
  585. //
  586. pSrcSCPool = (CSmtpClientPool*)GetExpression( DEBUG_PREFIX "g_SCPool" );
  587. if ( !pSrcSCPool )
  588. {
  589. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", DEBUG_PREFIX "g_SCPool" );
  590. return;
  591. }
  592. //
  593. // Allocate memory in our address space so we can read data from the debuggee's address space
  594. //
  595. pDstSCPool = (CSmtpClientPool*) DbgAlloc( cbSCPool );
  596. if( !pDstSCPool )
  597. {
  598. dprintf( "nntpdbg: Unable to allocate memory \n");
  599. return;
  600. }
  601. if( !ReadMemory( pSrcSCPool, pDstSCPool, cbSCPool, NULL ) )
  602. {
  603. dprintf("Could not get data at 0x%x\n", pSrcSCPool);
  604. DbgFree( pDstSCPool );
  605. return;
  606. }
  607. //
  608. // Dump the smtp conx cache
  609. //
  610. DbgDumpPool( pDstSCPool );
  611. DbgFree( pDstSCPool );
  612. }
  613. DECLARE_API( feedlist )
  614. /*++
  615. Routine Description:
  616. This function is called as an NTSD extension to format and dump
  617. an object attributes structure.
  618. Arguments:
  619. hCurrentProcess - Supplies a handle to the current process (at the
  620. time the extension was called).
  621. hCurrentThread - Supplies a handle to the current thread (at the
  622. time the extension was called).
  623. CurrentPc - Supplies the current pc at the time the extension is
  624. called.
  625. lpExtensionApis - Supplies the address of the functions callable
  626. by this extension.
  627. lpArgumentString - Supplies the asciiz string that describes the
  628. ansi string to be dumped.
  629. Return Value:
  630. None.
  631. --*/
  632. {
  633. CFeedList* pSrcFeedList;
  634. CFeedList* pDstFeedList;
  635. DWORD cbFeedList = sizeof(CFeedList);
  636. INIT_API();
  637. while (*lpArgumentString == ' ')
  638. lpArgumentString++;
  639. if ( !*lpArgumentString )
  640. {
  641. PrintUsage();
  642. return;
  643. }
  644. //
  645. // Get the ActiveFeeds global
  646. //
  647. pSrcFeedList = (CFeedList*)GetExpression( lpArgumentString );
  648. if ( !pSrcFeedList )
  649. {
  650. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  651. return;
  652. }
  653. pDstFeedList = (CFeedList*)DbgAlloc( cbFeedList );
  654. if( !pDstFeedList )
  655. {
  656. dprintf("nntpdbg: Unable to allocate memory\n");
  657. return;
  658. }
  659. //
  660. // Dump the feedblock list
  661. //
  662. if( !ReadMemory( pSrcFeedList, pDstFeedList, cbFeedList, NULL ) )
  663. {
  664. dprintf("nntpdbg: Unable to read memory at 0x%p\n", pSrcFeedList );
  665. DbgFree( pDstFeedList );
  666. return;
  667. }
  668. DbgDumpFeedList( pSrcFeedList, pDstFeedList );
  669. DbgFree( pDstFeedList );
  670. }
  671. DECLARE_API( feed )
  672. /*++
  673. Routine Description:
  674. This function is called as an NTSD extension to format and dump
  675. an object attributes structure.
  676. Arguments:
  677. hCurrentProcess - Supplies a handle to the current process (at the
  678. time the extension was called).
  679. hCurrentThread - Supplies a handle to the current thread (at the
  680. time the extension was called).
  681. CurrentPc - Supplies the current pc at the time the extension is
  682. called.
  683. lpExtensionApis - Supplies the address of the functions callable
  684. by this extension.
  685. lpArgumentString - Supplies the asciiz string that describes the
  686. ansi string to be dumped.
  687. Return Value:
  688. None.
  689. --*/
  690. {
  691. PFEED_BLOCK feedBlock;
  692. INIT_API();
  693. while (*lpArgumentString == ' ')
  694. lpArgumentString++;
  695. if ( !*lpArgumentString )
  696. {
  697. PrintUsage();
  698. return;
  699. }
  700. //
  701. // Treat the argument as the address of a FEED_BLOCK
  702. //
  703. feedBlock = (PFEED_BLOCK)GetExpression( lpArgumentString );
  704. if ( !feedBlock )
  705. {
  706. dprintf( "nntpdbg: Unable to evaluate \"%s\"\n", lpArgumentString );
  707. return;
  708. }
  709. DbgDumpFeedBlock( feedBlock );
  710. }
  711. DECLARE_API( rf )
  712. /*++
  713. Routine Description:
  714. This function is called as an NTSD extension to format and dump
  715. an object attributes structure.
  716. Arguments:
  717. hCurrentProcess - Supplies a handle to the current process (at the
  718. time the extension was called).
  719. hCurrentThread - Supplies a handle to the current thread (at the
  720. time the extension was called).
  721. CurrentPc - Supplies the current pc at the time the extension is
  722. called.
  723. lpExtensionApis - Supplies the address of the functions callable
  724. by this extension.
  725. lpArgumentString - Supplies the asciiz string that describes the
  726. ansi string to be dumped.
  727. Return Value:
  728. None.
  729. --*/
  730. {
  731. INIT_API();
  732. PLONG pcCallStack = NULL;
  733. LONG cCallStack = 0;
  734. PVOID pvCallStack = NULL;
  735. CHAR** ppchCallStack = NULL;
  736. CHAR** ppchReal = NULL;
  737. LPVOID lpvCallStack = NULL;
  738. LPVOID lpvBuffer = NULL;
  739. //
  740. // Get the number of buffers
  741. //
  742. pcCallStack = (PLONG)GetExpression( "exstrace!g_iCallStack" );
  743. if ( !pcCallStack )
  744. {
  745. dprintf( "nntpdbg: Unable to evaluate \"exstrace!g_cCallStack\"\n" );
  746. return;
  747. }
  748. if ( !ReadMemory( pcCallStack, &cCallStack, sizeof(LONG), NULL ) ) {
  749. dprintf( "nntpdbg: Could not read g_cCallStack\n" );
  750. return;
  751. }
  752. //
  753. // Get pointer to buffer
  754. //
  755. pvCallStack = (CHAR**)GetExpression( "exstrace!g_ppchCallStack" );
  756. if ( !pvCallStack )
  757. {
  758. dprintf( "nntpdbg: Unable to evaluate \"exstrace!g_ppchCallStack\"\n" );
  759. return;
  760. }
  761. if ( !ReadMemory( pvCallStack, &ppchCallStack, sizeof(CHAR**), NULL ) ) {
  762. dprintf( "nntpdbg: Could not read g_ppchCallStack\n" );
  763. return;
  764. }
  765. lpvCallStack = DbgAlloc( sizeof(CHAR*) * cCallStack );
  766. if ( !lpvCallStack ) {
  767. dprintf( "nntpdbg: Unable to allocate memory\n" );
  768. return;
  769. }
  770. if ( !ReadMemory( ppchCallStack, lpvCallStack, sizeof(CHAR*)*cCallStack, NULL ) ) {
  771. dprintf( "nntpdbg: Could not get data at 0x%x\n", ppchCallStack );
  772. DbgFree( lpvCallStack );
  773. return;
  774. } else
  775. ppchReal = (CHAR**)lpvCallStack;
  776. lpvBuffer = DbgAlloc( CALL_STACK_BUF_SIZE );
  777. if ( !lpvBuffer ) {
  778. DbgFree( lpvCallStack );
  779. dprintf( "nntpdbg: Unable to allocate memory\n" );
  780. return;
  781. }
  782. for ( LONG i = 0; i < cCallStack; i++ ) {
  783. if( ppchReal[i] ) {
  784. if ( !ReadMemory( ppchReal[i], lpvBuffer, CALL_STACK_BUF_SIZE, NULL ) ) {
  785. dprintf( "nntpdbg: Could not get data at 0x%x\n", ppchReal[i] );
  786. DbgFree( lpvCallStack );
  787. DbgFree( lpvBuffer );
  788. return;
  789. }
  790. *(PBYTE(lpvBuffer)+CALL_STACK_BUF_SIZE-1) = 0;
  791. dprintf("%s\n", (PCHAR)lpvBuffer );
  792. }
  793. }
  794. DbgFree( lpvBuffer );
  795. DbgFree( lpvCallStack );
  796. }
  797. VOID
  798. PrintUsage(
  799. VOID
  800. )
  801. {
  802. dprintf("\n\nMicrosoft Internet News Server debugging extension, Version 2.0\n\n");
  803. dprintf("!vroot <address> - Dump nntp virtual root\n");
  804. dprintf("!vrtable <address> - Dump nntp virtual root table\n");
  805. dprintf("!vrootlist <address> <n> - Dump the first <n> vroots in the table\n");
  806. dprintf("!cpool <address> - Dump CPool at <address>\n");
  807. dprintf("!cpools - Dump nntpsvc cpools\n");
  808. dprintf("!instance <address> - Dump instance at <address> \n");
  809. dprintf("!newstree <address> <n>- Dump first <n> newsgroups in newstree at <address> \n");
  810. dprintf("!newsgroup <address> - Dump newsgroup at <address> \n");
  811. dprintf("!sockets <address> - Dump socket at <address> \n");
  812. dprintf("!smtp - Dump smtp conx cache \n");
  813. dprintf("!feedlist <address> - Dump active feedblock list at <address> \n");
  814. dprintf("!feed <address> - Dump feedblock at <address> \n");
  815. dprintf("!rf - Dump all randfail call stacks \n" );
  816. dprintf("!help - Usage \n\n");
  817. }
  818. VOID
  819. DbgPrintInstance(
  820. NNTP_SERVER_INSTANCE* pInst
  821. )
  822. /*++
  823. Routine Description:
  824. Dump the first n newsgroup objects in the newstree.
  825. NOTE: Assumed that the pointer passed is in OUR address space
  826. --*/
  827. {
  828. dprintf("\n\n======== Begin Instance dump =========\n");
  829. if ( NNTP_SERVER_INSTANCE_SIGNATURE == pInst->m_signature ) {
  830. switch( pInst->m_dwServerState ) {
  831. case MD_SERVER_STATE_STARTED:
  832. dprintf("Server state is started\n");
  833. break;
  834. case MD_SERVER_STATE_STARTING:
  835. dprintf("Server state is starting\n");
  836. break;
  837. case MD_SERVER_STATE_STOPPING:
  838. dprintf("Server state is stopping\n" );
  839. break;
  840. case MD_SERVER_STATE_STOPPED:
  841. dprintf("Server state is stopped\n" );
  842. break;
  843. case MD_SERVER_STATE_PAUSING:
  844. dprintf("Server state is pausing\n" );
  845. break;
  846. case MD_SERVER_STATE_PAUSED:
  847. dprintf("Server state is paused\n" );
  848. break;
  849. case MD_SERVER_STATE_CONTINUING:
  850. dprintf("Server state is continuing\n" );
  851. break;
  852. }
  853. dprintf("Server has %d references\n", pInst->m_reference );
  854. dprintf("Instance id is %d\n", pInst->QueryInstanceId() );
  855. dprintf("Default port is %d\n", pInst->m_sDefaultPort );
  856. pInst->m_fAddedToServerInstanceList ?
  857. dprintf("Added to server instance list\n" ) :
  858. dprintf("NOT added to server instance list\n" );
  859. dprintf("It has %d connections now\n", pInst->m_dwCurrentConnections );
  860. dprintf("Owning service is 0x%p\n", pInst->m_Service );
  861. dprintf("Previous instance 0x%p\n",
  862. CONTAINING_RECORD( pInst->m_InstanceListEntry.Flink,
  863. IIS_SERVER_INSTANCE,
  864. m_InstanceListEntry ) );
  865. dprintf("Next instance 0x%p\n",
  866. CONTAINING_RECORD( pInst->m_InstanceListEntry.Blink,
  867. IIS_SERVER_INSTANCE,
  868. m_InstanceListEntry ) );
  869. pInst->m_ServiceStartCalled ?
  870. dprintf("Start method called\n") :
  871. dprintf("Start method NOT called\n" );
  872. dprintf("Article table pointer 0x%p\n", pInst->m_pArticleTable );
  873. dprintf("History table pointer 0x%p\n", pInst->m_pHistoryTable );
  874. dprintf("Xover table pointer 0x%p\n", pInst->m_pXoverTable );
  875. dprintf("Xover cache is 0x%p\n", pInst->m_pXCache );
  876. dprintf("Expire object is 0x%p\n", pInst->m_pExpireObject );
  877. dprintf("VRoot table is 0x%p\n", pInst->m_pVRootTable );
  878. dprintf("Dirnot object is 0x%p\n", pInst->m_pDirNot );
  879. dprintf("Server object is 0x%p\n", pInst->m_pNntpServerObject );
  880. dprintf("Wrapper( for posting lib) is 0x%p\n", pInst->m_pInstanceWrapper );
  881. dprintf("Wrapper( for newstree lib) is 0x%p\n", pInst->m_pInstanceWrapperEx );
  882. dprintf("SEO router 0x%p\n", pInst->m_pSEORouter );
  883. dprintf("Newstree is 0x%p\n", pInst->m_pTree );
  884. pInst->m_fAllowClientPosts ?
  885. dprintf("Server allows client posts\n") :
  886. dprintf("Server doesn't allow client posts\n" );
  887. pInst->m_fAllowFeedPosts ?
  888. dprintf("Server allows feed posts\n" ) :
  889. dprintf("Server doesn't allow feed posts\n" );
  890. pInst->m_fAllowControlMessages ?
  891. dprintf("Server allows control messages\n" ) :
  892. dprintf("Server doesn't allow control messages\n" );
  893. pInst->m_fNewnewsAllowed ?
  894. dprintf("Newnews allowed\n" ) :
  895. dprintf("Newnews not allowed\n" );
  896. dprintf("Client post hard limit %d\n", pInst->m_cbHardLimit );
  897. dprintf("Client post soft limit %d\n", pInst->m_cbSoftLimit );
  898. dprintf("Feed hard limit %d\n", pInst->m_cbFeedHardLimit );
  899. dprintf("Feed soft limit %d\n", pInst->m_cbFeedSoftLimit );
  900. dprintf("SSL access params 0x%08lx\n", pInst->m_dwSslAccessPerms );
  901. dprintf("SSLInfo object 0x%p\n", pInst->m_pSSLInfo );
  902. dprintf("Rebuild object 0x%p\n", pInst->m_pRebuild );
  903. dprintf("Last rebuild error %d\n", pInst->m_dwLastRebuildError );
  904. dprintf("Socket list 0x%p\n", pInst->m_pInUseList );
  905. dprintf("Active feed list 0x%p\n", pInst->m_pActiveFeeds );
  906. dprintf("Passive feed list 0x%p\n", pInst->m_pPassiveFeeds );
  907. } else {
  908. dprintf("Instance signature bad\n" );
  909. }
  910. dprintf("\n\n======== End Instance dump =========\n\n");
  911. }
  912. VOID
  913. DbgPrintNewstree(
  914. CNewsTree* ptree,
  915. DWORD nGroups
  916. )
  917. /*++
  918. Routine Description:
  919. Dump the first n newsgroup objects in the newstree.
  920. NOTE: Assumed that the pointer passed is in OUR address space
  921. --*/
  922. {
  923. CNewsGroup* pGroup;
  924. dprintf("\n\n======== Newstree members =========\n");
  925. dprintf(" Owning instance is 0x%p\n", ptree->m_pInstance );
  926. dprintf(" StartSpecial is %d\n", ptree->m_idStartSpecial );
  927. dprintf(" LastSpecial is %d\n", ptree->m_idLastSpecial );
  928. dprintf(" idSlaveGroup is %d\n", ptree->m_idSlaveGroup );
  929. dprintf(" idSpecialHigh is %d\n", ptree->m_idSpecialHigh );
  930. dprintf(" idStart is %d\n", ptree->m_idStart );
  931. dprintf(" idHigh is %d\n", ptree->m_idHigh );
  932. dprintf(" First group is 0x%p\n", ptree->m_pFirst );
  933. dprintf(" Last group is 0x%p\n", ptree->m_pLast );
  934. dprintf(" Num groups is %d\n", ptree->m_cGroups );
  935. dprintf(" VRoot table is 0x%p\n", ptree->m_pVRTable );
  936. ptree->m_fStoppingTree ? dprintf( " Tree is being stopped\n" ) :
  937. dprintf( " Tree is not being stopped\n" );
  938. dprintf(" Group.lst object is 0x%p\n", ptree->m_pFixedPropsFile );
  939. dprintf(" Groupvar.lst object is 0x%p\n", ptree->m_pVarPropsFile );
  940. dprintf(" Server object is 0x%p\n", ptree->m_pServerObject );
  941. ptree->m_fVRTableInit ? dprintf(" Vroot table initialized\n" ) :
  942. dprintf(" Vroot table NOT initialized\n" );
  943. if( nGroups )
  944. {
  945. dprintf("\n\n======== Begin Newstree dump =========\n");
  946. for( pGroup = (CNewsGroup*)ptree->m_pFirst; pGroup && nGroups--; )
  947. {
  948. pGroup = DbgPrintNewsgroup( pGroup );
  949. }
  950. dprintf("\n\n======== End Newstree dump =========\n\n");
  951. }
  952. }
  953. VOID
  954. DbgPrintVRootList(
  955. CNNTPVRoot* pFirstVRoot,
  956. DWORD nVRoots
  957. )
  958. /*++
  959. Routine Description:
  960. Dump the first n newsgroup objects in the newstree.
  961. NOTE: Assumed that the pointer passed is in OUR address space
  962. --*/
  963. {
  964. CNNTPVRoot* pVRoot;
  965. if( nVRoots )
  966. {
  967. dprintf("\n\n======== Begin virtual root list dump =========\n");
  968. for( pVRoot = pFirstVRoot; pVRoot && nVRoots--; )
  969. {
  970. pVRoot = DbgPrintVRoot( pVRoot );
  971. }
  972. dprintf("\n\n======== End virtual root list dump =========\n\n");
  973. }
  974. }
  975. VOID
  976. PrintSystemTime(
  977. FILETIME* pftTime
  978. )
  979. {
  980. SYSTEMTIME st;
  981. FileTimeToSystemTime( pftTime, &st );
  982. dprintf(" %04d::%02d::%02d::::%02d::%02d::%02d\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
  983. }
  984. VOID
  985. PrintString(
  986. LPSTR lp1,
  987. LPSTR lp2
  988. )
  989. {
  990. move( g_szBuffer, lp2 );
  991. dprintf( lp1, g_szBuffer );
  992. }
  993. CNewsGroup*
  994. DbgPrintNewsgroup(
  995. CNewsGroup * pSrcGroup
  996. )
  997. /*++
  998. Routine Description:
  999. Dump the newsgroup object at pGroup.
  1000. NOTE: Assumed that the pointer passed in is in the debuggee's address space
  1001. ie. we need to allocate memory and copy the data over into our address space !
  1002. Arguments:
  1003. Returns:
  1004. The next newsgroup pointer
  1005. --*/
  1006. {
  1007. CNewsGroup *pGroup, *pDstGroup;
  1008. char szNewsGroup [MAX_NEWSGROUP_NAME];
  1009. DWORD cbGroupName;
  1010. LPCSTR lpstrGroup;
  1011. DWORD cbPath, cbNewsGroup;
  1012. CNewsGroup* pGroupRet = NULL;
  1013. BOOL fActive = TRUE;
  1014. SYSTEMTIME sysTime;
  1015. //
  1016. // Allocate memory in our address space so we can read data from the debuggee's address space
  1017. //
  1018. cbNewsGroup = sizeof(CNewsGroup);
  1019. pDstGroup = (CNewsGroup*) DbgAlloc( cbNewsGroup );
  1020. if( !pDstGroup )
  1021. {
  1022. dprintf( "nntpdbg: Unable to allocate memory \n");
  1023. return NULL;
  1024. }
  1025. if( !ReadMemory( pSrcGroup, pDstGroup, cbNewsGroup, NULL ) )
  1026. {
  1027. dprintf("Could not get data at 0x%x\n", pSrcGroup);
  1028. goto DbgPrintNewsgroup_Exit;
  1029. }
  1030. // Now, we can use pGroup to access the members of the CNewsGroup object
  1031. pGroup = pDstGroup;
  1032. //
  1033. // Dump the newsgroup object
  1034. //
  1035. dprintf("\n\n======== Begin Newsgroup object =========\n\n");
  1036. //
  1037. // Check to see if group object is deallocated
  1038. //
  1039. fActive = ( pGroup->m_dwSignature == CNEWSGROUPCORE_SIGNATURE );
  1040. if ( fActive ) {
  1041. //
  1042. // dump newsgroup name
  1043. //
  1044. lpstrGroup = pGroup->m_pszGroupName;
  1045. cbGroupName = pGroup->m_cchGroupName; // it should have already included '\0'
  1046. if( ReadMemory( lpstrGroup, szNewsGroup, cbGroupName, NULL) ) {
  1047. dprintf("Newsgroup name is %s\n", szNewsGroup );
  1048. }
  1049. //
  1050. // Dump native name
  1051. //
  1052. lpstrGroup = pGroup->m_pszNativeName;
  1053. if ( lpstrGroup && ReadMemory( lpstrGroup, szNewsGroup, cbGroupName, NULL ) ) {
  1054. dprintf("Pretty name is %s\n", szNewsGroup );
  1055. } else {
  1056. dprintf("No native name\n" );
  1057. }
  1058. //
  1059. // Dump pretty name
  1060. //
  1061. lpstrGroup = pGroup->m_pszPrettyName;
  1062. cbGroupName = pGroup->m_cchPrettyName;
  1063. if ( lpstrGroup && ReadMemory( lpstrGroup, szNewsGroup, cbGroupName, NULL ) ) {
  1064. dprintf("Pretty name is %s\n", szNewsGroup );
  1065. } else {
  1066. dprintf("No pretty name\n" );
  1067. }
  1068. //
  1069. // Dump help text
  1070. //
  1071. lpstrGroup = pGroup->m_pszHelpText;
  1072. cbGroupName = pGroup->m_cchHelpText;
  1073. if ( lpstrGroup && ReadMemory( lpstrGroup, szNewsGroup, cbGroupName, NULL ) ) {
  1074. dprintf("Help text is %s\n", szNewsGroup );
  1075. } else {
  1076. dprintf("No help text\n" );
  1077. }
  1078. //
  1079. // Dump moderator
  1080. //
  1081. lpstrGroup = pGroup->m_pszModerator;
  1082. cbGroupName = pGroup->m_cchModerator;
  1083. if ( lpstrGroup && ReadMemory( lpstrGroup, szNewsGroup, cbGroupName, NULL ) ) {
  1084. dprintf("Moderator is %s\n", szNewsGroup );
  1085. } else {
  1086. dprintf("No moderator\n" );
  1087. }
  1088. //
  1089. // dump group privates
  1090. //
  1091. dprintf("Ref count is %d\n", pGroup->m_cRefs );
  1092. dprintf("Parent tree is 0x%p\n", pGroup->m_pNewsTree );
  1093. dprintf("Parent vroot is 0x%p\n", pGroup->m_pVRoot );
  1094. dprintf("Low watermark is %d\n", pGroup->m_iLowWatermark);
  1095. dprintf("High watermark is %d\n", pGroup->m_iHighWatermark);
  1096. dprintf("Article estimate is %d\n", pGroup->m_cMessages );
  1097. dprintf("Group id is %d\n", pGroup->m_dwGroupId );
  1098. pGroup->m_fReadOnly ? dprintf("Group is read only\n" ) : dprintf("Group is not read only\n" );
  1099. pGroup->m_fDeleted ? dprintf("Group is marked deleted\n") : dprintf("Group is NOT marked deleted\n");
  1100. FileTimeToSystemTime( &(pGroup->m_ftCreateDate), &sysTime );
  1101. dprintf("Group create time: %d/%d/%d - %d:%d:%d\n",
  1102. sysTime.wMonth,
  1103. sysTime.wDay,
  1104. sysTime.wYear,
  1105. sysTime.wHour,
  1106. sysTime.wMinute,
  1107. sysTime.wSecond );
  1108. dprintf("Cache hit is %d\n", pGroup->m_dwCacheHit );
  1109. pGroup->m_fAllowExpire ? dprintf( "Expire allowed\n" ) : dprintf( "Expire not allowed\n" );
  1110. pGroup->m_fAllowPost ? dprintf( "Post allowed\n" ) : dprintf( "Expire not allowed\n" );
  1111. pGroup->m_fDecorateVisited ? dprintf( "Decorate visited\n" ) : dprintf( "Decorate non-visited\n" );
  1112. dprintf("m_artXoverExpireLow is %d\n", pGroup->m_artXoverExpireLow);
  1113. dprintf("Prev group is 0x%p\n", pGroup->m_pPrev);
  1114. dprintf("Next group is 0x%p\n", pGroup->m_pNext);
  1115. pGroupRet = (CNewsGroup*)pGroup->m_pNext;
  1116. } else {
  1117. dprintf( "Newsgroup signature is bad\n" );
  1118. }
  1119. dprintf("\n======== End Newsgroup object =========\n");
  1120. DbgPrintNewsgroup_Exit:
  1121. DbgFreeEx( pDstGroup );
  1122. return pGroupRet;
  1123. }
  1124. CNNTPVRoot*
  1125. DbgPrintVRoot(
  1126. CNNTPVRoot * pVRoot
  1127. )
  1128. /*++
  1129. Routine Description:
  1130. Dump the vroot object at pVRoot
  1131. NOTE: Assumed that the pointer passed in is in the debuggee's address space
  1132. ie. we need to allocate memory and copy the data over into our address space !
  1133. Arguments:
  1134. Returns:
  1135. The next newsgroup pointer
  1136. --*/
  1137. {
  1138. CNNTPVRoot *pDestVRoot, *pMyVRoot;
  1139. DWORD cbVRoot;
  1140. CNNTPVRoot* pVRootRet = NULL;
  1141. BOOL fActive = FALSE;
  1142. //
  1143. // Allocate memory in our address space so we can read data from the debuggee's address space
  1144. //
  1145. cbVRoot = sizeof(CNNTPVRoot);
  1146. pDestVRoot = (CNNTPVRoot*) DbgAlloc( cbVRoot );
  1147. if( !pDestVRoot )
  1148. {
  1149. dprintf( "nntpdbg: Unable to allocate memory \n");
  1150. return NULL;
  1151. }
  1152. if( !ReadMemory( pVRoot, pDestVRoot, cbVRoot, NULL ) )
  1153. {
  1154. dprintf("Could not get data at 0x%x\n", pVRoot );
  1155. goto DbgPrintVRoot_Exit;
  1156. }
  1157. // Now, we can use pMyVRoot to access the members of the CNNTPVRoot object
  1158. pMyVRoot = pDestVRoot;
  1159. //
  1160. // Dump the vroot object
  1161. //
  1162. dprintf("\n\n======== Begin virtual root object =========\n\n");
  1163. //
  1164. // Check to see if group object is deallocated
  1165. //
  1166. fActive = ( pMyVRoot->m_dwSig == VROOT_GOOD_SIG );
  1167. if ( fActive ) {
  1168. //
  1169. // Dump reference
  1170. //
  1171. dprintf("Reference count is %d\n", pMyVRoot->m_cRefs );
  1172. dprintf("Next vroot is 0x%p\n", pMyVRoot->m_pNext );
  1173. pVRootRet = (CNNTPVRoot*)pMyVRoot->m_pNext;
  1174. dprintf("Prev vroot is 0x%p\n", pMyVRoot->m_pPrev );
  1175. pMyVRoot->m_fInit ? dprintf("Vroot is initialized\n") :
  1176. dprintf("Vroot is NOT initialized\n" );
  1177. dprintf("Vroot name is %s\n", pMyVRoot->m_szVRootName );
  1178. dprintf("Owning vroot table is 0x%p\n", pMyVRoot->m_pVRootTable );
  1179. pMyVRoot->m_fUpgrade ? dprintf("This is an upgraded vroot\n" ) :
  1180. dprintf("This is not an upgraded vroot\n" );
  1181. pMyVRoot->m_fIsIndexed ? dprintf("Content indexed\n" ) :
  1182. dprintf("Not content indexed\n" );
  1183. dprintf("Access bitmask is 0x%08lx\n", pMyVRoot->m_dwAccess );
  1184. dprintf("SSL access bitmask 0x%08lx\n", pMyVRoot->m_dwSSL );
  1185. dprintf("Metabase object 0x%p\n", pMyVRoot->m_pMB );
  1186. dprintf("Directory path %s\n", pMyVRoot->m_szDirectory );
  1187. dprintf("Prepare driver 0x%p\n", pMyVRoot->m_pDriverPrepare );
  1188. dprintf("Good driver 0x%p\n", pMyVRoot->m_pDriver );
  1189. switch( pMyVRoot->m_eLogonInfo ) {
  1190. case CNNTPVRoot::VROOT_LOGON_DEFAULT:
  1191. dprintf("This is a file system vroot\n");
  1192. break;
  1193. case CNNTPVRoot::VROOT_LOGON_UNC:
  1194. dprintf("This is a UNC vroot\n" );
  1195. break;
  1196. case CNNTPVRoot::VROOT_LOGON_EX:
  1197. dprintf("This is an exchange vroot\n" );
  1198. break;
  1199. }
  1200. switch( pMyVRoot->m_eState ) {
  1201. case CNNTPVRoot::VROOT_STATE_UNINIT:
  1202. dprintf("Vroot not inited\n" );
  1203. break;
  1204. case CNNTPVRoot::VROOT_STATE_CONNECTING:
  1205. dprintf("Vroot is connecting\n" );
  1206. break;
  1207. case CNNTPVRoot::VROOT_STATE_CONNECTED:
  1208. dprintf("Vroot is connected\n" );
  1209. break;
  1210. }
  1211. dprintf("VRoot Win32 Error %d\n", pMyVRoot->m_dwWin32Error );
  1212. dprintf("Impersonation token ( for UNC ): %d\n", pMyVRoot->m_hImpersonation );
  1213. pMyVRoot->m_bExpire ? dprintf("Vroot handles expire himself\n") :
  1214. dprintf("Protocol should help him expire\n" );
  1215. pMyVRoot->m_lDecCompleted == 0 ?
  1216. dprintf("Decorate newstree in progress\n") :
  1217. dprintf("Decorate newstree completed\n" );
  1218. #ifdef DEBUG
  1219. dprintf("Next vroot in debug list 0x%p\n",
  1220. CONTAINING_RECORD( pMyVRoot->m_DebugList.Flink,
  1221. CVRoot,
  1222. m_DebugList ) );
  1223. #endif
  1224. } else {
  1225. dprintf("Vroot signature bad\n" );
  1226. }
  1227. dprintf("\n======== End virtual root object =========\n");
  1228. DbgPrintVRoot_Exit:
  1229. DbgFreeEx( pDestVRoot );
  1230. return pVRootRet;
  1231. }
  1232. void
  1233. DbgPrintVRootTable(
  1234. CNNTPVRootTable * pVRTable
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. Dump the vroot table object at pVRTable
  1239. NOTE: Assumed that the pointer passed in is in the debuggee's address space
  1240. ie. we need to allocate memory and copy the data over into our address space !
  1241. Arguments:
  1242. Returns:
  1243. The next newsgroup pointer
  1244. --*/
  1245. {
  1246. CNNTPVRootTable *pDestVRTable, *pMyVRTable;
  1247. DWORD cbVRTable;
  1248. CHAR szVRootPath[MAX_VROOT_PATH];
  1249. //
  1250. // Allocate memory in our address space so we can read data from the debuggee's address space
  1251. //
  1252. cbVRTable = sizeof(CNNTPVRootTable);
  1253. pDestVRTable = (CNNTPVRootTable*) DbgAlloc( cbVRTable );
  1254. if( !pDestVRTable )
  1255. {
  1256. dprintf( "nntpdbg: Unable to allocate memory \n");
  1257. return ;
  1258. }
  1259. if( !ReadMemory( pVRTable, pDestVRTable, cbVRTable, NULL ) )
  1260. {
  1261. dprintf("Could not get data at 0x%x\n", pVRTable );
  1262. goto DbgPrintVRootTable_Exit;
  1263. }
  1264. // Now, we can use pMyVRTable to access the members of the CNNTPVRoot object
  1265. pMyVRTable = pDestVRTable;
  1266. //
  1267. // Dump the vroot object
  1268. //
  1269. dprintf("\n\n======== Begin virtual root table object =========\n\n");
  1270. #ifdef DEBUG
  1271. if ( IsListEmpty( &pMyVRTable->impl.m_DebugListHead ) ) {
  1272. dprintf("Debug list is empty\n");
  1273. } else {
  1274. dprintf("First vroot in debug list 0x%p\n",
  1275. CONTAINING_RECORD( pMyVRTable->impl.m_DebugListHead.Flink,
  1276. CVRoot,
  1277. m_DebugList ) );
  1278. }
  1279. #endif
  1280. CopyUnicodeStringIntoAscii( szVRootPath, pMyVRTable->impl.m_wszRootPath );
  1281. dprintf("VRoot path is %s\n", szVRootPath );
  1282. pMyVRTable->impl.m_fInit ? dprintf("We have been initialized\n") :
  1283. dprintf("We are not initialized\n" );
  1284. pMyVRTable->impl.m_fShuttingDown ? dprintf("We are shutting down\n") :
  1285. dprintf("We are not shutting down\n" );
  1286. if ( pMyVRTable->impl.m_listVRoots.IsEmpty() ) {
  1287. dprintf("Table is empty\n" );
  1288. } else {
  1289. dprintf("The first vroot on table is 0x%p\n",
  1290. pMyVRTable->impl.m_listVRoots.m_pHead );
  1291. }
  1292. dprintf("Owning instance wrapper 0x%p\n", pMyVRTable->m_pInstWrapper );
  1293. dprintf("\n======== End virtual root table object =========\n");
  1294. DbgPrintVRootTable_Exit:
  1295. DbgFreeEx( pDestVRTable );
  1296. }
  1297. VOID
  1298. DbgDumpPool(
  1299. CSmtpClientPool* pSCPool
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. Dump the smtp cached conx
  1304. NOTE: Assumed that the pointer passed is in OUR address space
  1305. --*/
  1306. {
  1307. DWORD cSlots = pSCPool->m_cSlots;
  1308. DWORD i;
  1309. BOOL* rgAvailList = NULL;
  1310. CSmtpClient** rgppSCList = NULL;
  1311. dprintf("\n======== Begin CSmtpClientPool dump =========\n\n");
  1312. dprintf("Number of slots is %d\n", cSlots);
  1313. DWORD cbAvailList = sizeof(BOOL)*cSlots;
  1314. DWORD cbSCList = sizeof(CSmtpClient*)*cSlots;
  1315. rgAvailList = (BOOL*)DbgAlloc( cbAvailList );
  1316. if( !rgAvailList || !ReadMemory( pSCPool->m_rgAvailList, rgAvailList, cbAvailList, NULL) )
  1317. {
  1318. dprintf("Failed to allocate or read memory\n");
  1319. goto DbgDumpPool_Exit;
  1320. }
  1321. rgppSCList = (CSmtpClient**)DbgAlloc( cbSCList );
  1322. if( !rgppSCList || !ReadMemory( pSCPool->m_rgpSCList, rgppSCList, cbSCList, NULL) )
  1323. {
  1324. dprintf("Failed to allocate or read memory\n");
  1325. goto DbgDumpPool_Exit;
  1326. }
  1327. // Dump the conx object pointers and avail status
  1328. for(i=0; i<cSlots; i++)
  1329. {
  1330. dprintf("Smtp conx object %d is 0x%p\n", i+1, rgppSCList [i]);
  1331. dprintf("Avail status is %d\n", rgAvailList [i]);
  1332. }
  1333. dprintf("\n======== End CSmtpClientPool dump =========\n");
  1334. DbgDumpPool_Exit:
  1335. DbgFreeEx( rgAvailList );
  1336. DbgFreeEx( rgppSCList );
  1337. }
  1338. VOID
  1339. DbgDumpFeedBlock(
  1340. PFEED_BLOCK feedBlock
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. Dump the feedBlock passed in; validate signature
  1345. NOTE: Assumed that the pointer passed in is in the debuggee's address space
  1346. ie. we need to allocate memory and copy the data over into our address space !
  1347. Arguments:
  1348. Returns:
  1349. --*/
  1350. {
  1351. FEED_BLOCK feed;
  1352. // read memory from debuggee's address space
  1353. move( feed, feedBlock );
  1354. // validate signature
  1355. if( FEED_BLOCK_SIGN != feed.Signature )
  1356. {
  1357. dprintf("Invalid Feed block signature Expected: 0x%08lx Got: 0x%08lx \n", FEED_BLOCK_SIGN, feed.Signature );
  1358. return;
  1359. }
  1360. // ok, dump the feed block
  1361. dprintf("============ Begin feed block dump =============== \n");
  1362. dprintf("Number of feeds done so far is %d\n", feed.NumberOfFeeds);
  1363. dprintf("Number of failed connection attempts for Push feeds is %d\n", feed.cFailedAttempts);
  1364. dprintf("The last newsgroup spec Pulled is %d\n", feed.LastNewsgroupPulled);
  1365. dprintf("Resolved IP address is %d\n", feed.IPAddress);
  1366. dprintf("feedblock ListEntry Flink is 0x%p\n", feed.ListEntry.Flink);
  1367. dprintf("feedblock ListEntry Blink is 0x%p\n", feed.ListEntry.Blink);
  1368. dprintf("feed is in progress ? %d\n", feed.FeedsInProgress);
  1369. dprintf("Count of references to this block is %d\n", feed.ReferenceCount);
  1370. dprintf("Current State of this block is %d\n", feed.State);
  1371. dprintf("Should we delete this block when the references reach 0 ? %d\n", feed.MarkedForDelete);
  1372. dprintf("Pointer to a FEED_BLOCK that we are replaced by is 0x%p\n", feed.ReplacedBy);
  1373. dprintf("Pointer to a FEED_BLOCK we replace is 0x%p\n", feed.Replaces);
  1374. dprintf("Type of this feed (push/pull/passive) is %d\n", feed.FeedType);
  1375. //dprintf("Name of reg key this feed info is stored under 0x%p\n", feed.KeyName);
  1376. dprintf("The Queue used to record outgoing articles for this ACTIVE outgoing feed is 0x%p\n", feed.pFeedQueue);
  1377. dprintf("Unique id for this feed block is %d\n", feed.FeedId);
  1378. dprintf("Should we autocreate directories? %d\n", feed.AutoCreate);
  1379. dprintf("Minutes between feeds is %d\n", feed.FeedIntervalMinutes);
  1380. dprintf("Pull Request Time is");
  1381. PrintSystemTime( &feed.PullRequestTime );
  1382. FILETIME ft;
  1383. dprintf("Start Time is");
  1384. FILETIME_FROM_LI( &ft, &feed.StartTime );
  1385. PrintSystemTime( &ft );
  1386. dprintf("Next Active Time is");
  1387. FILETIME_FROM_LI( &ft, &feed.NextActiveTime);
  1388. PrintSystemTime( &ft );
  1389. PrintString("Name of the feed server is %s\n", feed.ServerName);
  1390. dprintf("Newsgroups to pull is 0x%p\n", feed.Newsgroups);
  1391. dprintf("Distributions is 0x%p\n", feed.Distribution);
  1392. dprintf("Flag indicating whether the feed is currently 'enabled' is %d\n", feed.fEnabled);
  1393. //PrintString("The name to be used in Path processing is %s\n", feed.UucpName);
  1394. PrintString("The directory where we are to store our temp files is %s\n", feed.FeedTempDirectory);
  1395. dprintf("Maximum number of consecutive failed connect attempts before\n");
  1396. dprintf("we disable the feed is %d\n", feed.MaxConnectAttempts);
  1397. dprintf("Number of sessions to create for outbound feeds is %d\n", feed.ConcurrentSessions);
  1398. dprintf("Type of security to have is %d\n", feed.SessionSecurityType);
  1399. dprintf("Authentication security is %d\n", feed.AuthenticationSecurity);
  1400. PrintString("User Account for clear text logons is %s\n", feed.NntpAccount);
  1401. PrintString("User Password for clear text logons is %s\n", feed.NntpPassword);
  1402. dprintf("Allow control messages on this feed ? %d\n", feed.fAllowControlMessages);
  1403. dprintf("============ End feed block dump =============== \n");
  1404. }
  1405. VOID
  1406. DbgDumpFeedList(
  1407. CFeedList* pSrcFeedList,
  1408. CFeedList* pDstFeedList
  1409. )
  1410. /*--
  1411. Arguments:
  1412. pSrcFeedList - pointer in debuggee's address space
  1413. pDstFeedList - pointer in OUR address space
  1414. --*/
  1415. {
  1416. LIST_ENTRY Entry;
  1417. PLIST_ENTRY listEntry;
  1418. PLIST_ENTRY SrclistEntry = (pDstFeedList->m_ListHead).Flink ;
  1419. listEntry = SrclistEntry;
  1420. DWORD offset = (DWORD)((DWORD_PTR)&((CFeedList*)0)->m_ListHead);
  1421. PLIST_ENTRY listEnd = (PLIST_ENTRY)((LPBYTE)pSrcFeedList+offset);
  1422. //dprintf("offset is %d listEnd is 0x%p\n", offset, listEnd);
  1423. while( listEntry != listEnd ) {
  1424. PFEED_BLOCK feedBlock = CONTAINING_RECORD( listEntry,
  1425. FEED_BLOCK,
  1426. ListEntry );
  1427. DbgDumpFeedBlock( feedBlock );
  1428. SrclistEntry = listEntry;
  1429. move( Entry, SrclistEntry );
  1430. listEntry = Entry.Flink ;
  1431. }
  1432. }
  1433. VOID
  1434. DbgDumpCPool(CPool* pCPool, DWORD dwSignature, LPCSTR szSymbol)
  1435. {
  1436. CPool* pPool = (CPool*)DbgAlloc( sizeof(CPool));
  1437. if ( pCPool && pPool )
  1438. {
  1439. if ( ReadMemory( (LPVOID) pCPool,
  1440. pPool,
  1441. sizeof(CPool),
  1442. NULL ))
  1443. {
  1444. dprintf( "%s at 0x%8lx, signature is 0x%.8x\n",
  1445. (szSymbol?szSymbol:"CPool"),
  1446. pCPool, pPool->m_dwSignature);
  1447. if( dwSignature != 0 && dwSignature != pPool->m_dwSignature ) {
  1448. dprintf(" *** signature mismatch\n" );
  1449. }
  1450. dprintf(" m_cMaxInstances = %d\n", pPool->m_cMaxInstances );
  1451. dprintf(" m_cInstanceSize = %d\n", pPool->m_cInstanceSize );
  1452. dprintf(" m_cNumberCommitted = %d\n", pPool->m_cNumberCommitted );
  1453. dprintf(" m_cNumberInUse = %d\n", pPool->m_cNumberInUse );
  1454. dprintf(" m_cNumberAvail = %d\n", pPool->m_cNumberAvail );
  1455. dprintf(" m_cFragmentInstances = %d\n", pPool->m_cFragmentInstances );
  1456. dprintf(" m_cFragments = %d\n", pPool->m_cFragments );
  1457. dprintf(" Fragments:\n");
  1458. for(int i=0; i<MAX_CPOOL_FRAGMENTS; i++) {
  1459. dprintf(" %p%s", pPool->m_pFragments[i], ((i+1)%4)==0?"\n":"" );
  1460. }
  1461. dprintf("=========================\n");
  1462. }
  1463. DbgFree( (PVOID)pPool );
  1464. }
  1465. }