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.

733 lines
19 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name:
  4. dbgcc.cxx
  5. Abstract:
  6. This module contains the default ntsd debugger extensions for
  7. IIS - W3SVC Client Connection
  8. Author:
  9. Murali R. Krishnan (MuraliK) 22-Aug-1997
  10. Revision History:
  11. --*/
  12. #include "inetdbgp.h"
  13. # undef DBG_ASSERT
  14. /************************************************************
  15. * Debugger Utility Functions
  16. ************************************************************/
  17. NTSD_EXTENSION_APIS ExtensionApis;
  18. HANDLE ExtensionCurrentProcess;
  19. /************************************************************
  20. * CLIENT_CONN related functions
  21. ************************************************************/
  22. char * g_rgchCCState[] = {
  23. "CcsStartup",
  24. "CcsGettingClientReq",
  25. "CcsGatheringGatewayData",
  26. "CcsProcessingClientReq",
  27. "CcsDisconnecting",
  28. "CcsShutdown",
  29. "CcsMaxItems"
  30. };
  31. #define LookupCCState( ItemState ) \
  32. ((((ItemState) >= CCS_STARTUP) && ((ItemState) <= CCS_SHUTDOWN)) ?\
  33. g_rgchCCState[ (ItemState)] : "<Invalid>")
  34. VOID PrintClientConn( CLIENT_CONN * pccOriginal,
  35. CLIENT_CONN * pcc, CHAR Verbosity);
  36. VOID
  37. PrintClientConnThunk( PVOID pccDebuggee,
  38. PVOID pccDebugger,
  39. CHAR verbosity,
  40. DWORD iCount);
  41. DECLARE_API( cc )
  42. /*++
  43. Routine Description:
  44. This function is called as an NTSD extension to format and dump
  45. an object attributes structure.
  46. Arguments:
  47. hCurrentProcess - Supplies a handle to the current process (at the
  48. time the extension was called).
  49. hCurrentThread - Supplies a handle to the current thread (at the
  50. time the extension was called).
  51. CurrentPc - Supplies the current pc at the time the extension is
  52. called.
  53. lpExtensionApis - Supplies the address of the functions callable
  54. by this extension.
  55. lpArgumentString - Supplies the asciiz string that describes the
  56. ansi string to be dumped.
  57. Return Value:
  58. None.
  59. --*/
  60. {
  61. BOOL fRet;
  62. DEFINE_CPP_VAR( CLIENT_CONN, cc);
  63. CLIENT_CONN * pcc;
  64. INIT_API();
  65. while (*lpArgumentString == ' ')
  66. lpArgumentString++;
  67. if ( !*lpArgumentString )
  68. {
  69. PrintUsage( "cc" );
  70. return;
  71. }
  72. if ( *lpArgumentString == '-' )
  73. {
  74. lpArgumentString++;
  75. if ( *lpArgumentString == 'h' )
  76. {
  77. PrintUsage( "cc" );
  78. return;
  79. }
  80. if ( *lpArgumentString == 'l' ) {
  81. DumpClientConnList( lpArgumentString[1], PrintClientConnThunk );
  82. return;
  83. }
  84. } // while
  85. //
  86. // Treat the argument as the address of an AtqContext
  87. //
  88. pcc = (CLIENT_CONN * ) GetExpression( lpArgumentString );
  89. if ( !pcc )
  90. {
  91. dprintf( "inetdbg.cc: Unable to evaluate \"%s\"\n",
  92. lpArgumentString );
  93. return;
  94. }
  95. move( cc, pcc );
  96. PrintClientConn( pcc, GET_CPP_VAR_PTR( CLIENT_CONN, cc), '2' );
  97. return;
  98. } // DECLARE_API( cc )
  99. VOID
  100. PrintClientConn( CLIENT_CONN * pccOriginal,
  101. CLIENT_CONN * pcc,
  102. CHAR Verbosity )
  103. /*++
  104. Description:
  105. This function takes the client connection object and prints out
  106. the details for the same in the debugger. The granularity of the
  107. deatils are controlled by the verbosity flag
  108. Arguments:
  109. pccOriginal - pointer to the location where the original CLIENT_CONN
  110. object is located.
  111. Note: pccOriginal points to object inside debuggee process
  112. pcc - pointer to the Client Connection object that is a copy
  113. of the contents located at [pccOriginal]
  114. Note: pcc points to object inside the debugger process
  115. Verbostiy - level of details requested.
  116. Returns:
  117. None
  118. --*/
  119. {
  120. if ( Verbosity >= '0') {
  121. //
  122. // print Brief information about the client connection
  123. //
  124. dprintf( "ClIENT_CONN:%08p Refs = %8d State = %15s\n"
  125. "\t HTTP_REQUEST = %08p AtqContext = %08p\n"
  126. ,
  127. pccOriginal, pcc->_cRef,
  128. LookupCCState( pcc->_ccState),
  129. pcc->_phttpReq,
  130. pcc->_AtqContext
  131. );
  132. }
  133. if ( Verbosity >= '1' ) {
  134. //
  135. // Print all details for the Client Connection object
  136. //
  137. dprintf( "\tSignature = %08x fSecurePort=%d fValid=%d; \n"
  138. "\tSocket = %08p Port: Local=%hd Remote=%hd\n"
  139. "\tListEntry.Flink = %08p ListEntry.Blink = %08p\n"
  140. "\tInitialBuffer = %08p InitialBytesRecvd = %d\n"
  141. "\tBuffLE.Flink = %08p BuffLE.Blink = %08p\n"
  142. "\tAddress Local = %10s Address Remote = %10s\n"
  143. "\tW3Instance = %08p Reflog = %08p\n"
  144. ,
  145. pcc->_Signature, pcc->_fSecurePort, pcc->_fIsValid,
  146. pcc->_sClient, pcc->_sPort, pcc->_sRemotePort,
  147. pcc->ListEntry.Flink, pcc->ListEntry.Blink,
  148. pcc->_pvInitial, pcc->_cbInitial,
  149. pcc->_BuffListEntry.Flink, pcc->_BuffListEntry.Blink,
  150. pcc->_achLocalAddr, pcc->_achRemoteAddr,
  151. pcc->m_pInstance,
  152. #if CC_REF_TRACKING // Enabled in free builds for build 585 and later
  153. pcc->_pDbgCCRefTraceLog
  154. #else
  155. (PVOID)(-1)
  156. #endif
  157. );
  158. }
  159. if ( Verbosity >= '2' ) {
  160. //
  161. // Print the initial request received for the client connection
  162. //
  163. dstring( " Initial Request", pcc->_pvInitial, pcc->_cbInitial);
  164. }
  165. return;
  166. } // PrintClientConn()
  167. VOID
  168. PrintClientConnThunk( PVOID pccDebuggee,
  169. PVOID pccDebugger,
  170. CHAR verbosity,
  171. DWORD iThunk)
  172. /*++
  173. Description:
  174. This is the callback function for printing the CLIENT_CONN object.
  175. Arguments:
  176. pccDebuggee - pointer to client conn object in the debuggee process
  177. pccDebugger - pointer to client conn object in the debugger process
  178. verbosity - character indicating the verbosity level desired
  179. Returns:
  180. None
  181. --*/
  182. {
  183. if ( ((CLIENT_CONN * )pccDebugger)->_Signature != CLIENT_CONN_SIGNATURE) {
  184. dprintf( "ClientConn(%08lp) signature %08lx doesn't"
  185. " match expected %08lx\n",
  186. pccDebuggee,
  187. ((CLIENT_CONN * )pccDebugger)->_Signature,
  188. CLIENT_CONN_SIGNATURE
  189. );
  190. return;
  191. }
  192. PrintClientConn( (CLIENT_CONN *) pccDebuggee,
  193. (CLIENT_CONN *) pccDebugger,
  194. verbosity);
  195. } // PrintClientConnThunk()
  196. VOID
  197. DumpClientConnList(
  198. CHAR Verbosity,
  199. PFN_LIST_ENUMERATOR pfnCC
  200. )
  201. {
  202. LIST_ENTRY * pccListHead;
  203. pccListHead = (LIST_ENTRY *) GetExpression( "&w3svc!listConnections");
  204. if ( NULL == pccListHead) {
  205. dprintf( " Unable to get Client Connections list \n");
  206. return;
  207. }
  208. EnumLinkedList( pccListHead, pfnCC, Verbosity,
  209. sizeof( CLIENT_CONN),
  210. FIELD_OFFSET( CLIENT_CONN, ListEntry)
  211. );
  212. return;
  213. } // DumpClientConnList()
  214. /************************************************************
  215. * HTTP_REQUEST related functions
  216. ************************************************************/
  217. char * g_rgchHREQState[] = {
  218. "HtrReadingClientRequest",
  219. "HtrReadingGatewayData",
  220. "HtrParse",
  221. "HtrDoVerb",
  222. "HtrGatewayAsyncIO",
  223. "HtrSendFile",
  224. "HtrProxySendingRequest",
  225. "HtrCgi",
  226. "HtrRange",
  227. "HtrRestartRequest",
  228. "HtrWritingFile",
  229. "HtrCertRenegotiate",
  230. "HtrMaxItems"
  231. };
  232. #define LookupHREQState( ItemState ) \
  233. ((((ItemState) >= HTR_READING_CLIENT_REQUEST) && \
  234. ((ItemState) <= HTR_DONE)) ?\
  235. g_rgchHREQState[ (ItemState)] : "<Invalid>")
  236. const char * g_rgchHreqPutState[] = {
  237. "PSTATE_START",
  238. "PSTATE_READING",
  239. "PSTATE_DISCARD_READING",
  240. "PSTATE_DISCARD_CHUNK"
  241. };
  242. # define LookupHreqPutState( ItemState) \
  243. ((((ItemState) >= PSTATE_START) && \
  244. ((ItemState) <= PSTATE_DISCARD_CHUNK)) ?\
  245. g_rgchHreqPutState[ (ItemState)] : "<Invalid>")
  246. VOID
  247. PrintHttpRequest( HTTP_REQUEST * phreqOriginal,
  248. HTTP_REQUEST * phreq,
  249. CHAR Verbosity);
  250. VOID
  251. PrintHttpRequestThunk( PVOID pccDebuggee,
  252. PVOID pccDebugger,
  253. CHAR verbosity,
  254. DWORD iCount);
  255. DECLARE_API( hreq )
  256. /*++
  257. Routine Description:
  258. This function is called as an NTSD extension to format and dump
  259. an object attributes structure.
  260. Arguments:
  261. hCurrentProcess - Supplies a handle to the current process (at the
  262. time the extension was called).
  263. hCurrentThread - Supplies a handle to the current thread (at the
  264. time the extension was called).
  265. CurrentPc - Supplies the current pc at the time the extension is
  266. called.
  267. lpExtensionApis - Supplies the address of the functions callable
  268. by this extension.
  269. lpArgumentString - Supplies the asciiz string that describes the
  270. ansi string to be dumped.
  271. Return Value:
  272. None.
  273. --*/
  274. {
  275. BOOL fRet;
  276. DEFINE_CPP_VAR( HTTP_REQUEST, hreq);
  277. HTTP_REQUEST * phreq;
  278. INIT_API();
  279. while (*lpArgumentString == ' ')
  280. lpArgumentString++;
  281. if ( !*lpArgumentString )
  282. {
  283. PrintUsage( "hreq" );
  284. return;
  285. }
  286. if ( *lpArgumentString == '-' )
  287. {
  288. lpArgumentString++;
  289. if ( *lpArgumentString == 'h' )
  290. {
  291. PrintUsage( "hreq" );
  292. return;
  293. }
  294. if ( *lpArgumentString == 'l' ) {
  295. DumpClientConnList( lpArgumentString[1],
  296. PrintHttpRequestThunk);
  297. return;
  298. }
  299. } // if
  300. //
  301. // Treat the argument as the address of an AtqContext
  302. //
  303. phreq = (HTTP_REQUEST * ) GetExpression( lpArgumentString );
  304. if ( !phreq )
  305. {
  306. dprintf( "inetdbg.hreq: Unable to evaluate \"%s\"\n",
  307. lpArgumentString );
  308. return;
  309. }
  310. move( hreq, phreq );
  311. PrintHttpRequest( phreq, GET_CPP_VAR_PTR( HTTP_REQUEST, hreq), '2');
  312. return;
  313. } // DECLARE_API( hreq )
  314. VOID
  315. PrintHttpRequestThunk(
  316. PVOID pccDebuggee,
  317. PVOID pccDebugger,
  318. CHAR verbosity,
  319. DWORD iCount)
  320. /*++
  321. Description:
  322. This is the callback function for printing the HTTP_REQUEST object.
  323. Arguments:
  324. pccDebuggee - pointer to client conn object in the debuggee process
  325. pccDebugger - pointer to client conn object in the debugger process
  326. verbosity - character indicating the verbosity level desired
  327. Returns:
  328. None
  329. --*/
  330. {
  331. DEFINE_CPP_VAR( HTTP_REQUEST, hreq);
  332. HTTP_REQUEST * phreq;
  333. CLIENT_CONN * pcc = (CLIENT_CONN *) pccDebugger;
  334. if ( pcc->_Signature != CLIENT_CONN_SIGNATURE) {
  335. dprintf( "ClientConn(%08lp) signature %08lx doesn't"
  336. " match expected %08lx\n",
  337. pccDebuggee,
  338. pcc->_Signature,
  339. CLIENT_CONN_SIGNATURE
  340. );
  341. return;
  342. }
  343. //
  344. // Obtain the pointer for HTTP_REQUEST object from CLIENT_CONN object
  345. // and make local copy of the HTTP_REQUEST object inside debugger process
  346. //
  347. phreq = (HTTP_REQUEST *) pcc->_phttpReq;
  348. move( hreq, phreq);
  349. // Print out the http request object
  350. PrintHttpRequest( phreq,
  351. GET_CPP_VAR_PTR( HTTP_REQUEST, hreq),
  352. verbosity);
  353. } // PrintHttpRequestThunk()
  354. VOID
  355. PrintHttpRequest( HTTP_REQUEST * phreqOriginal,
  356. HTTP_REQUEST * phreq,
  357. CHAR Verbosity )
  358. /*++
  359. Description:
  360. This function takes the HTTP_REQUEST object and prints out
  361. the details for the same in the debugger. The granularity of the
  362. deatils are controlled by the verbosity flag
  363. Arguments:
  364. phreqOriginal - pointer to the location where the original HTTP_REQUEST
  365. object is located.
  366. Note: phreqOriginal points to object inside debuggee process
  367. phreq - pointer to the HTTP_REQUEST object that is a copy
  368. of the contents located at [phreqOriginal]
  369. Note: phreq points to object inside the debugger process
  370. Verbostiy - level of details requested.
  371. Returns:
  372. None
  373. --*/
  374. {
  375. if ( Verbosity >= '0') {
  376. //
  377. // print Brief information about the client connection
  378. //
  379. dprintf( "HTTP_REQUEST:%08p State = %15s\n"
  380. "\t CLIENT_CONN = %08p WamReq = %08p\n"
  381. ,
  382. phreqOriginal,
  383. LookupHREQState( phreq->_htrState),
  384. phreq->_pClientConn,
  385. phreq->_pWamRequest
  386. );
  387. }
  388. if ( Verbosity >= '1' ) {
  389. //
  390. // Print all details for the Client Connection object
  391. //
  392. dprintf( "\t _fKeepConn = %8s _fLoggedOn = %8s\n"
  393. "\t _fChunked = %8s Client Ver = %d.%d\n"
  394. "\t _tcpauth = %08p _Filter = %p \n"
  395. "\t _cbClientRequest = %8d _cbOldData = %8d\n"
  396. "\t _cbEntityBody = %8d _cbTotalEntBody = %8d\n"
  397. "\t _cbChunkHeader = %8d _cbChunkBytesRead=%8d\n"
  398. "\t _cbExtraData = %8d _pchExtraData = %08p\n"
  399. "\t _pMetaData = %08p _pURIInfo = %08p\n"
  400. "\t _pGetFile = %08p _Exec = %08p\n"
  401. "\t _pW3Stats = %08p\n"
  402. "\t _dwLogHttpResponse= %8d _dwLogWinError = %8d\n"
  403. ,
  404. BoolValue(phreq->_fKeepConn),
  405. BoolValue(phreq->_fLoggedOn),
  406. BoolValue(phreq->_fChunked),
  407. (int) phreq->_VersionMajor, (int) phreq->_VersionMinor,
  408. (BYTE *) phreqOriginal + ((BYTE *) &phreq->_tcpauth - (BYTE *) phreq),
  409. (BYTE *) phreqOriginal + ((BYTE *) &phreq->_Filter - (BYTE *) phreq),
  410. phreq->_cbClientRequest,
  411. phreq->_cbOldData,
  412. phreq->_cbEntityBody,
  413. phreq->_cbTotalEntityBody,
  414. phreq->_cbChunkHeader,
  415. phreq->_cbChunkBytesRead,
  416. phreq->_cbExtraData,
  417. phreq->_pchExtraData,
  418. phreq->_pMetaData,
  419. phreq->_pURIInfo,
  420. phreq->_pGetFile,
  421. (BYTE *) phreqOriginal + ((BYTE *) &phreq->_Exec - (BYTE *) phreq),
  422. phreq->_pW3Stats,
  423. phreq->_dwLogHttpResponse,
  424. phreq->_dwLogWinError
  425. );
  426. }
  427. if ( Verbosity >= '2' ) {
  428. //
  429. // Print state specific data
  430. //
  431. dprintf( "\t _putstate = %8s _pFileNameLock = %8p\n"
  432. , LookupHreqPutState( phreq->_putstate)
  433. , phreq->_pFileNameLock
  434. );
  435. }
  436. return;
  437. } // PrintHttpRequest()
  438. VOID
  439. PrintW3Statistics( W3_SERVER_STATISTICS * pw3statsDebuggee );
  440. /*++
  441. NAME: wstats
  442. SYNOPSIS: Displays the w3svc statistics.
  443. By default print the global w3svc statistics.
  444. If given an argument treat that argument as a pointer to the
  445. W3_SERVER_STATISITCS structure and print it out
  446. --*/
  447. DECLARE_API( wstats )
  448. {
  449. W3_SERVER_STATISTICS * pw3stats;
  450. W3_IIS_SERVICE * pw3s;
  451. INIT_API();
  452. while (*lpArgumentString == ' ')
  453. lpArgumentString++;
  454. //
  455. // Capture the statistics.
  456. //
  457. if ( !*lpArgumentString ) {
  458. dprintf( "OffsetOfGlobalStats from W3_IIS_SERVICE = %d (0x%x)\n",
  459. FIELD_OFFSET( W3_IIS_SERVICE, m_GlobalStats),
  460. FIELD_OFFSET( W3_IIS_SERVICE, m_GlobalStats)
  461. );
  462. dprintf( "OffsetOfStats from W3_SERVER_INSTANCE = %d (0x%x)\n",
  463. FIELD_OFFSET( W3_SERVER_INSTANCE, m_pW3Stats),
  464. FIELD_OFFSET( W3_SERVER_INSTANCE, m_pW3Stats)
  465. );
  466. //
  467. // In IIS 4.0, the global statistics structure is part of
  468. // the W3_IIS_SERVICE structure - obtain the address indirectly.
  469. //
  470. W3_IIS_SERVICE ** ppw3s;
  471. ppw3s = (W3_IIS_SERVICE **) GetExpression( "w3svc!g_pInetSvc");
  472. if ( !ppw3s) {
  473. dprintf( "Unable to get w3svc!g_pInetSvc to fetch global stats\n");
  474. return;
  475. }
  476. //
  477. // From the pointer to pointer to W3_IIS_SERVICE,
  478. // obtain the pointer to the W3_IIS_SERVICE
  479. //
  480. moveBlock( pw3s, ppw3s, sizeof(W3_IIS_SERVICE * ));
  481. pw3stats = &pw3s->m_GlobalStats;
  482. } else {
  483. //
  484. // extract the address from the argument given
  485. //
  486. pw3stats = (W3_SERVER_STATISTICS * ) GetExpression( lpArgumentString );
  487. }
  488. PrintW3Statistics( pw3stats);
  489. return;
  490. } // stats
  491. # define P2DWORDS( a, b) \
  492. Print2Dwords( #a, \
  493. pw3statsDebugger->m_W3Stats. ## a, \
  494. #b, \
  495. pw3statsDebugger->m_W3Stats. ## b \
  496. )
  497. VOID
  498. PrintW3Statistics( W3_SERVER_STATISTICS * pw3statsDebuggee )
  499. /*++
  500. Description:
  501. This function takes the W3_SERVER_STATISTICS object and prints out
  502. the details for the same in the debugger.
  503. Arguments:
  504. pw3statsDebuggee - pointer to the location where the original structure
  505. is found inside the debuggee process.
  506. pw3statsDebugger - pointer to the copy of the data in the debugger process.
  507. Returns:
  508. None
  509. --*/
  510. {
  511. DEFINE_CPP_VAR( W3_SERVER_STATISTICS, w3stats);
  512. W3_SERVER_STATISTICS * pw3statsDebugger =
  513. (W3_SERVER_STATISTICS *) &w3stats;
  514. CHAR szLargeInt[64];
  515. //
  516. // copy the statistics data into the local buffer inside the debugger
  517. // process so we can play with it
  518. //
  519. move( w3stats, pw3statsDebuggee);
  520. dprintf( " %30s = 0x%08p\n",
  521. "W3_SERVER_STATISTICS",
  522. pw3statsDebuggee);
  523. PrintLargeInteger( "TotalBytesSent",
  524. &pw3statsDebugger->m_W3Stats.TotalBytesSent);
  525. PrintLargeInteger( "TotalBytesReceived",
  526. &pw3statsDebugger->m_W3Stats.TotalBytesReceived);
  527. P2DWORDS( TotalFilesSent, TotalFilesReceived);
  528. dprintf("\n");
  529. P2DWORDS( CurrentAnonymousUsers, CurrentNonAnonymousUsers);
  530. P2DWORDS( TotalAnonymousUsers, TotalNonAnonymousUsers);
  531. P2DWORDS( MaxAnonymousUsers, MaxNonAnonymousUsers);
  532. P2DWORDS( CurrentConnections, MaxConnections);
  533. P2DWORDS( ConnectionAttempts, LogonAttempts);
  534. dprintf( "\n");
  535. P2DWORDS( TotalGets, TotalPosts);
  536. P2DWORDS( TotalHeads, TotalPuts);
  537. P2DWORDS( TotalDeletes, TotalTraces);
  538. P2DWORDS( TotalOthers, TotalNotFoundErrors);
  539. P2DWORDS( TotalCGIRequests, TotalBGIRequests);
  540. dprintf( "\n");
  541. P2DWORDS( CurrentCGIRequests, MaxCGIRequests);
  542. P2DWORDS( CurrentBGIRequests, MaxBGIRequests);
  543. return;
  544. } // PrintW3Statistics()
  545.