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.

877 lines
22 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. w3wplisthttpreq.cxx
  5. Abstract:
  6. implementation of class W3wpListHttpReq.
  7. This class reads in all the relevant info
  8. from the http_request.
  9. Author:
  10. Hamid Mahmood (t-hamidm) 08-13-2001
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. CHAR W3wpListHttpReq::sm_chHttpHeaderVerbosityLevel[HttpHeaderMaximum] =
  15. { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  16. 4,4,4,3,4,4,4,4,4,4,4,4,4,4,3,4,4,4,3
  17. };
  18. W3wpListHttpReq::W3wpListHttpReq()
  19. /*++
  20. Routine Description:
  21. Constructor
  22. Arguments:
  23. None
  24. Return Value:
  25. none
  26. --*/
  27. {
  28. m_httpRequestId = 0;
  29. m_dwNumUnknownHeaders = 0;
  30. m_httpVerb = HttpVerbMaximum;
  31. m_majorVersion = 0;
  32. m_minorVersion = 0;
  33. m_fIsHeaderPresent = FALSE;
  34. m_pszURI = NULL;
  35. m_pszHostName = NULL;
  36. m_pszUnknownVerb = NULL;
  37. m_pszQueryString = NULL;
  38. m_pszDateTime = NULL;
  39. m_pszClientIP = NULL;
  40. for (DWORD i = 0; i < HttpHeaderMaximum; i++)
  41. {
  42. m_ppszKnownHeaders[i] = NULL;
  43. }
  44. m_ppszUnknownHeaderNames = NULL;
  45. m_ppszUnknownHeaderValues = NULL;
  46. m_dwSignature = W3WPLIST_HTTP_REQ_SIGNATURE;
  47. }
  48. W3wpListHttpReq::~W3wpListHttpReq()
  49. /*++
  50. Routine Description:
  51. Destructor
  52. Arguments:
  53. None
  54. Return Value:
  55. none
  56. --*/
  57. {
  58. DBG_ASSERT (m_dwSignature == W3WPLIST_HTTP_REQ_SIGNATURE);
  59. m_dwSignature = W3WPLIST_HTTP_REQ_SIGNATURE_FREE;
  60. DBG_ASSERT(m_httpRequestId == 0);
  61. DBG_ASSERT(m_dwNumUnknownHeaders == 0);
  62. DBG_ASSERT(m_httpVerb == HttpVerbMaximum);
  63. DBG_ASSERT(m_majorVersion == 0);
  64. DBG_ASSERT(m_minorVersion == 0);
  65. DBG_ASSERT(m_fIsHeaderPresent == FALSE);
  66. DBG_ASSERT(m_pszURI == NULL);
  67. DBG_ASSERT(m_pszHostName == NULL);
  68. DBG_ASSERT(m_pszUnknownVerb == NULL);
  69. DBG_ASSERT(m_pszQueryString == NULL);
  70. DBG_ASSERT(m_pszDateTime == NULL);
  71. DBG_ASSERT(m_pszClientIP == NULL);
  72. for (DWORD i = 0; i < HttpHeaderMaximum; i++)
  73. {
  74. DBG_ASSERT(m_ppszKnownHeaders[i] == NULL);
  75. }
  76. DBG_ASSERT(m_ppszUnknownHeaderNames == NULL);
  77. DBG_ASSERT(m_ppszUnknownHeaderValues == NULL);
  78. };
  79. VOID
  80. W3wpListHttpReq::Terminate()
  81. /*++
  82. Routine Description:
  83. Deallocates memory
  84. Arguments:
  85. None
  86. Return Value:
  87. none
  88. --*/
  89. {
  90. m_httpRequestId = 0;
  91. m_httpVerb = HttpVerbMaximum;
  92. m_fIsHeaderPresent = FALSE;
  93. m_minorVersion = 0;
  94. m_majorVersion = 0;
  95. delete[] m_pszURI;
  96. m_pszURI = NULL;
  97. delete[] m_pszHostName;
  98. m_pszHostName = NULL;
  99. delete[] m_pszUnknownVerb;
  100. m_pszUnknownVerb = NULL;
  101. delete[] m_pszQueryString;
  102. m_pszQueryString = NULL;
  103. delete[] m_pszDateTime;
  104. m_pszDateTime = NULL;
  105. delete[] m_pszClientIP;
  106. m_pszClientIP = NULL;
  107. for (DWORD i = 0; i < HttpHeaderMaximum; i++)
  108. {
  109. delete[] m_ppszKnownHeaders[i];
  110. m_ppszKnownHeaders[i] = NULL;
  111. }
  112. for (DWORD i = 0; i < m_dwNumUnknownHeaders; i++)
  113. {
  114. delete[] m_ppszUnknownHeaderNames[i];
  115. m_ppszUnknownHeaderNames[i] = NULL;
  116. delete[] m_ppszUnknownHeaderValues[i];
  117. m_ppszUnknownHeaderValues[i] = NULL;
  118. }
  119. m_ppszUnknownHeaderNames = NULL;
  120. m_ppszUnknownHeaderValues = NULL;
  121. m_dwNumUnknownHeaders = 0;
  122. }
  123. HRESULT
  124. W3wpListHttpReq::ReadFromWorkerProcess( HANDLE hProcess,
  125. HTTP_REQUEST* pHttpRequest,
  126. CHAR chVerbosity
  127. )
  128. /*++
  129. Routine Description:
  130. Reads in the relevant info from the input
  131. http_request *.
  132. Arguments:
  133. hProcess -- input PID
  134. pHttpRequest -- * to HTTP_REQEUST obj in worker process
  135. chVerbosity -- verbosity level
  136. Return Value:
  137. HRESULT -- S_OK if success, otherwise E_FAIL
  138. --*/
  139. {
  140. BOOL fReadMemStatus = FALSE;
  141. SIZE_T stNumBytesRead;
  142. DWORD dwStrSize = 0;
  143. PHTTP_UNKNOWN_HEADER pUnknownHeadersInRemoteProcess = NULL;
  144. HTTP_UNKNOWN_HEADER unknownHeader;
  145. HRESULT hr = S_OK;
  146. //
  147. // check for Ctrl+C, Ctrl+Break, etc
  148. //
  149. if ( CONSOLE_HANDLER_VAR::g_HAS_CONSOLE_EVENT_OCCURED == TRUE )
  150. {
  151. hr = E_FAIL;
  152. goto end;
  153. }
  154. m_httpRequestId = pHttpRequest->RequestId;
  155. m_httpVerb = pHttpRequest->Verb;
  156. //
  157. // read in the unknown verb
  158. //
  159. dwStrSize = pHttpRequest->UnknownVerbLength;
  160. if ( dwStrSize != 0 )
  161. {
  162. m_pszUnknownVerb = new CHAR[dwStrSize + 1];
  163. if ( m_pszUnknownVerb == NULL ) // new failed
  164. {
  165. hr = E_FAIL;
  166. goto end;
  167. }
  168. fReadMemStatus = ReadProcessMemory( hProcess,
  169. pHttpRequest->pUnknownVerb,
  170. m_pszUnknownVerb,
  171. pHttpRequest->UnknownVerbLength,
  172. &stNumBytesRead
  173. );
  174. if ( fReadMemStatus == FALSE )
  175. {
  176. hr = E_FAIL;
  177. goto end;
  178. }
  179. m_pszUnknownVerb[dwStrSize] = '\0';
  180. }
  181. //
  182. // read in the Hostname
  183. //
  184. dwStrSize = pHttpRequest->CookedUrl.HostLength / sizeof(WCHAR);
  185. if ( dwStrSize != 0 )
  186. {
  187. m_pszHostName = new WCHAR[dwStrSize + 1];
  188. if ( m_pszHostName == NULL ) // new failed
  189. {
  190. hr = E_FAIL;
  191. goto end;
  192. }
  193. fReadMemStatus = ReadProcessMemory( hProcess,
  194. pHttpRequest->CookedUrl.pHost,
  195. m_pszHostName,
  196. pHttpRequest->CookedUrl.HostLength,
  197. &stNumBytesRead
  198. );
  199. if ( fReadMemStatus == FALSE )
  200. {
  201. hr = E_FAIL;
  202. goto end;
  203. }
  204. m_pszHostName[dwStrSize] = L'\0';
  205. }
  206. //
  207. // read in the AbsPath
  208. //
  209. dwStrSize = pHttpRequest->CookedUrl.AbsPathLength / sizeof(WCHAR);
  210. if ( dwStrSize != 0 )
  211. {
  212. m_pszURI = new WCHAR[dwStrSize + 1];
  213. if ( m_pszURI == NULL ) // new failed
  214. {
  215. hr = E_FAIL;
  216. goto end;
  217. }
  218. fReadMemStatus = ReadProcessMemory( hProcess,
  219. pHttpRequest->CookedUrl.pAbsPath,
  220. m_pszURI,
  221. pHttpRequest->CookedUrl.AbsPathLength,
  222. &stNumBytesRead
  223. );
  224. if ( fReadMemStatus == FALSE )
  225. {
  226. hr = E_FAIL;
  227. goto end;
  228. }
  229. m_pszURI[dwStrSize] = L'\0';
  230. }
  231. //
  232. // The rest is read in only if verbosity level is high enough
  233. //
  234. if ( chVerbosity < 2 )
  235. {
  236. goto end;
  237. }
  238. //
  239. // save protocol info
  240. //
  241. m_majorVersion = pHttpRequest->Version.MajorVersion;
  242. m_minorVersion = pHttpRequest->Version.MinorVersion;
  243. //
  244. // read in the QueryString
  245. //
  246. dwStrSize = pHttpRequest->CookedUrl.QueryStringLength / sizeof(WCHAR);
  247. if ( dwStrSize != 0 )
  248. {
  249. m_pszQueryString = new WCHAR[dwStrSize + 1];
  250. if ( m_pszQueryString == NULL ) // new failed
  251. {
  252. hr = E_FAIL;
  253. goto end;
  254. }
  255. fReadMemStatus = ReadProcessMemory( hProcess,
  256. pHttpRequest->CookedUrl.pQueryString,
  257. m_pszQueryString,
  258. pHttpRequest->CookedUrl.QueryStringLength,
  259. &stNumBytesRead
  260. );
  261. if ( fReadMemStatus == FALSE )
  262. {
  263. hr = E_FAIL;
  264. goto end;
  265. }
  266. m_pszQueryString[dwStrSize] = L'\0';
  267. }
  268. // Read verbosity 3 stuff;
  269. if ( chVerbosity < 3 )
  270. {
  271. goto end;
  272. }
  273. //
  274. // Client - IP
  275. //
  276. if ( pHttpRequest->Address.pRemoteAddress != NULL )
  277. {
  278. SOCKADDR_STORAGE SockAddr;
  279. CHAR szNumericAddress[NI_MAXHOST];
  280. if( pHttpRequest->Address.pLocalAddress->sa_family == AF_INET )
  281. {
  282. SOCKADDR_IN * pSockaddr_In = ( SOCKADDR_IN * )&SockAddr;
  283. fReadMemStatus = ReadProcessMemory( hProcess,
  284. pHttpRequest->Address.pRemoteAddress,
  285. pSockaddr_In,
  286. sizeof(SOCKADDR_IN),
  287. &stNumBytesRead );
  288. if ( fReadMemStatus == FALSE )
  289. {
  290. hr = E_FAIL;
  291. goto end;
  292. }
  293. if( getnameinfo( ( LPSOCKADDR )&SockAddr,
  294. sizeof( SOCKADDR_IN ),
  295. szNumericAddress,
  296. sizeof( szNumericAddress ),
  297. NULL,
  298. 0,
  299. NI_NUMERICHOST ) != 0 )
  300. {
  301. hr = HRESULT_FROM_WIN32( WSAGetLastError() );
  302. goto end;
  303. }
  304. }
  305. else if( pHttpRequest->Address.pLocalAddress->sa_family == AF_INET6 )
  306. {
  307. SOCKADDR_IN6 * pSockaddr_In6 = ( SOCKADDR_IN6 * )&SockAddr;
  308. fReadMemStatus = ReadProcessMemory( hProcess,
  309. pHttpRequest->Address.pRemoteAddress,
  310. pSockaddr_In6,
  311. sizeof(SOCKADDR_IN6),
  312. &stNumBytesRead );
  313. if ( fReadMemStatus == FALSE )
  314. {
  315. hr = E_FAIL;
  316. goto end;
  317. }
  318. if( getnameinfo( ( LPSOCKADDR )&SockAddr,
  319. sizeof( SOCKADDR_IN6 ),
  320. szNumericAddress,
  321. sizeof( szNumericAddress ),
  322. NULL,
  323. 0,
  324. NI_NUMERICHOST ) != 0 )
  325. {
  326. hr = HRESULT_FROM_WIN32( WSAGetLastError() );
  327. goto end;
  328. }
  329. }
  330. else
  331. {
  332. DBG_ASSERT( FALSE );
  333. }
  334. m_pszClientIP = new CHAR[strlen( szNumericAddress ) + 1];
  335. if ( m_pszClientIP == NULL )
  336. {
  337. hr = E_FAIL;
  338. goto end;
  339. }
  340. strcpy( m_pszClientIP,
  341. szNumericAddress
  342. );
  343. }
  344. //
  345. // read headers, verbosity level for each header is
  346. // defined in sm_chHttpHeaderVerbosityLevel array
  347. //
  348. for( DWORD i = 0; i < HttpHeaderMaximum; i++)
  349. {
  350. //
  351. // match verbosity level from the static array
  352. //
  353. if ( sm_chHttpHeaderVerbosityLevel[i] <= chVerbosity )
  354. {
  355. dwStrSize = pHttpRequest->Headers.KnownHeaders[i].RawValueLength;
  356. if ( dwStrSize != 0 )
  357. {
  358. m_fIsHeaderPresent = TRUE;
  359. m_ppszKnownHeaders[i] = new CHAR[dwStrSize + 1];
  360. if (m_ppszKnownHeaders[i] == NULL)
  361. {
  362. hr = E_FAIL;
  363. goto end;;
  364. }
  365. fReadMemStatus = ReadProcessMemory( hProcess,
  366. pHttpRequest->Headers.KnownHeaders[i].pRawValue,
  367. m_ppszKnownHeaders[i],
  368. pHttpRequest->Headers.KnownHeaders[i].RawValueLength,
  369. &stNumBytesRead
  370. );
  371. if ( fReadMemStatus == FALSE )
  372. {
  373. hr = E_FAIL;
  374. goto end;
  375. }
  376. m_ppszKnownHeaders[i][dwStrSize] = '\0';
  377. }
  378. } // verbosity level check
  379. } // end for loop
  380. if ( chVerbosity < 4 )
  381. {
  382. goto end;
  383. }
  384. //
  385. // read in unknown headers
  386. //
  387. m_dwNumUnknownHeaders = pHttpRequest->Headers.UnknownHeaderCount;
  388. if ( m_dwNumUnknownHeaders > 0 ) // some unknown headers exist
  389. {
  390. m_fIsHeaderPresent = TRUE;
  391. pUnknownHeadersInRemoteProcess = pHttpRequest->Headers.pUnknownHeaders;
  392. //
  393. // allocate memory for unknown headers
  394. //
  395. m_ppszUnknownHeaderNames = new CHAR*[m_dwNumUnknownHeaders];
  396. if ( m_ppszUnknownHeaderNames == NULL )
  397. {
  398. hr = E_FAIL;
  399. goto end;
  400. }
  401. m_ppszUnknownHeaderValues = new CHAR*[m_dwNumUnknownHeaders];
  402. if ( m_ppszUnknownHeaderValues == NULL )
  403. {
  404. hr = E_FAIL;
  405. goto end;
  406. }
  407. //
  408. // read in all the unknown headers
  409. //
  410. for (DWORD i = 0 ; i < m_dwNumUnknownHeaders; i++ , pUnknownHeadersInRemoteProcess++)
  411. {
  412. //
  413. // read in the unknown header struct
  414. //
  415. fReadMemStatus = ReadProcessMemory( hProcess,
  416. pUnknownHeadersInRemoteProcess,
  417. &unknownHeader,
  418. sizeof(HTTP_UNKNOWN_HEADER),
  419. &stNumBytesRead
  420. );
  421. if (fReadMemStatus == FALSE)
  422. {
  423. hr = E_FAIL;
  424. goto end;
  425. }
  426. //
  427. // read in the name of the header
  428. //
  429. dwStrSize = unknownHeader.NameLength;
  430. m_ppszUnknownHeaderNames[i] = new CHAR[dwStrSize + 1];
  431. if ( m_ppszUnknownHeaderNames[i] == NULL)
  432. {
  433. hr = E_FAIL;
  434. goto end;
  435. }
  436. fReadMemStatus = ReadProcessMemory( hProcess,
  437. unknownHeader.pName,
  438. m_ppszUnknownHeaderNames[i],
  439. unknownHeader.NameLength,
  440. &stNumBytesRead
  441. );
  442. if (fReadMemStatus == FALSE)
  443. {
  444. hr = E_FAIL;
  445. goto end;
  446. }
  447. m_ppszUnknownHeaderNames[i][dwStrSize] = '\0';
  448. //
  449. // read in the value of the header
  450. //
  451. dwStrSize = unknownHeader.RawValueLength;
  452. m_ppszUnknownHeaderValues[i] = new CHAR[dwStrSize + 1];
  453. if ( m_ppszUnknownHeaderValues[i] == NULL)
  454. {
  455. hr = E_FAIL;
  456. goto end;
  457. }
  458. fReadMemStatus = ReadProcessMemory( hProcess,
  459. unknownHeader.pRawValue,
  460. m_ppszUnknownHeaderValues[i],
  461. unknownHeader.RawValueLength,
  462. &stNumBytesRead
  463. );
  464. if (fReadMemStatus == FALSE)
  465. {
  466. hr = E_FAIL;
  467. goto end;
  468. }
  469. m_ppszUnknownHeaderValues[i][dwStrSize] = '\0';
  470. } // for loop
  471. pUnknownHeadersInRemoteProcess = NULL;
  472. } // if unknown headers exists
  473. end:
  474. return hr;
  475. }
  476. VOID
  477. W3wpListHttpReq::Print(CHAR chVerbosity)
  478. /*++
  479. Routine Description:
  480. Outputs request info dependent on the
  481. verbosity level.
  482. Arguments:
  483. chVerbosity -- verbosity level
  484. Return Value:
  485. None
  486. --*/
  487. {
  488. #define MAX_TAG_WIDTH_1 12
  489. #define MAX_TAG_WIDTH_2 20
  490. enum{
  491. URI = 0,
  492. HOSTNAME,
  493. PROTOCOL,
  494. METHOD,
  495. QUERY,
  496. CLIENT_IP,
  497. REQUEST_ID,
  498. DATE_TIME,
  499. HEADERS
  500. };
  501. WCHAR* pOutputTags[] = { L"URI",
  502. L"Hostname",
  503. L"Protocol",
  504. L"Method",
  505. L"Query",
  506. L"Client-IP",
  507. L"Request Id",
  508. L"Date/Time",
  509. L"Headers"
  510. };
  511. WCHAR * pVerbs[] = {
  512. L"Unparsed",
  513. L"Unknown",
  514. L"Invalid",
  515. L"OPTIONS",
  516. L"GET",
  517. L"HEAD",
  518. L"POST",
  519. L"PUT",
  520. L"DELETE",
  521. L"TRACE",
  522. L"CONNECT",
  523. L"TRACK",
  524. L"MOVE",
  525. L"COPY",
  526. L"PROPFIND",
  527. L"PROPPATCH",
  528. L"MKCOL",
  529. L"LOCK",
  530. L"UNLOCK",
  531. L"SEARCH",
  532. };
  533. WCHAR* pOutputHeaderNames[] =
  534. {
  535. L"Cache-Control",
  536. L"Connection",
  537. L"Date",
  538. L"Keep-Alive",
  539. L"Pragma",
  540. L"Trailer",
  541. L"Transfer-Encoding",
  542. L"Upgrade",
  543. L"Via",
  544. L"Warning",
  545. L"Allow",
  546. L"Content-Length",
  547. L"Content-Type",
  548. L"Content-Encoding",
  549. L"Content-Language",
  550. L"Content-Location",
  551. L"Content-Md5",
  552. L"Content-Range",
  553. L"Expires",
  554. L"LastModified",
  555. L"Accept",
  556. L"Accept-Charset",
  557. L"Accept-Encoding",
  558. L"Accept-Language",
  559. L"Authorization",
  560. L"Cookie",
  561. L"Expect",
  562. L"From",
  563. L"Host",
  564. L"If-Match",
  565. L"If-Modified-Since",
  566. L"If-NoneMatch",
  567. L"If-Range",
  568. L"If-Unmodified-Since",
  569. L"Max-Forwards",
  570. L"Proxy-Authorization",
  571. L"Referer",
  572. L"Range",
  573. L"Te",
  574. L"Translate",
  575. L"UserAgent"
  576. };
  577. DBG_ASSERT (chVerbosity > 0);
  578. wprintf ( L"%-*s: %u\n",
  579. MAX_TAG_WIDTH_1,
  580. pOutputTags[REQUEST_ID],
  581. m_httpRequestId
  582. );
  583. wprintf ( L" %-*s: %s\n",
  584. MAX_TAG_WIDTH_1,
  585. pOutputTags[URI],
  586. m_pszURI
  587. );
  588. wprintf ( L" %-*s: %s\n",
  589. MAX_TAG_WIDTH_1,
  590. pOutputTags[HOSTNAME],
  591. m_pszHostName
  592. );
  593. if ( m_httpVerb != HttpVerbUnknown)
  594. {
  595. wprintf ( L" %-*s: %s\n",
  596. MAX_TAG_WIDTH_1,
  597. pOutputTags[METHOD],
  598. pVerbs[m_httpVerb]
  599. );
  600. }
  601. else
  602. {
  603. printf ( " %-*S: %s\n",
  604. MAX_TAG_WIDTH_1,
  605. pOutputTags[METHOD],
  606. m_pszUnknownVerb
  607. );
  608. }
  609. if ( chVerbosity < 2 )
  610. {
  611. goto end;
  612. }
  613. wprintf ( L" %-*s: HTTP/%d.%d\n",
  614. MAX_TAG_WIDTH_1,
  615. pOutputTags[PROTOCOL],
  616. m_majorVersion,
  617. m_minorVersion
  618. );
  619. if ( m_pszQueryString != NULL )
  620. {
  621. wprintf ( L" %-*s: %s\n",
  622. MAX_TAG_WIDTH_1,
  623. pOutputTags[QUERY],
  624. m_pszQueryString
  625. );
  626. }
  627. if ( chVerbosity < 3 )
  628. {
  629. goto end;
  630. }
  631. if ( m_pszClientIP != NULL )
  632. {
  633. printf ( " %-*S: %s\n",
  634. MAX_TAG_WIDTH_1,
  635. pOutputTags[CLIENT_IP],
  636. m_pszClientIP
  637. );
  638. }
  639. if ( m_fIsHeaderPresent != TRUE )
  640. {
  641. goto end;
  642. }
  643. wprintf ( L" %-*s:\n",
  644. MAX_TAG_WIDTH_1,
  645. pOutputTags[HEADERS]
  646. );
  647. if ( m_ppszKnownHeaders[HttpHeaderReferer] != NULL )
  648. {
  649. printf ( " %-*S: %s\n",
  650. MAX_TAG_WIDTH_2,
  651. pOutputHeaderNames[HttpHeaderReferer],
  652. m_ppszKnownHeaders[HttpHeaderReferer]
  653. );
  654. }
  655. if ( m_ppszKnownHeaders[HttpHeaderUserAgent] != NULL )
  656. {
  657. printf ( " %-*S: %s\n",
  658. MAX_TAG_WIDTH_2,
  659. pOutputHeaderNames[HttpHeaderUserAgent],
  660. m_ppszKnownHeaders[HttpHeaderUserAgent]
  661. );
  662. }
  663. if ( m_ppszKnownHeaders[HttpHeaderCookie] != NULL )
  664. {
  665. printf ( " %-*S: %s\n",
  666. MAX_TAG_WIDTH_2,
  667. pOutputHeaderNames[HttpHeaderCookie],
  668. m_ppszKnownHeaders[HttpHeaderCookie]
  669. );
  670. }
  671. if ( chVerbosity < 4 )
  672. {
  673. goto end;
  674. }
  675. for( DWORD i = 0; i < HttpHeaderMaximum; i++)
  676. {
  677. if ( ( i != HttpHeaderCookie ) &&
  678. ( i != HttpHeaderUserAgent ) &&
  679. ( i != HttpHeaderReferer )
  680. )
  681. {
  682. if ( m_ppszKnownHeaders[i] != NULL )
  683. {
  684. printf ( " %-*S: %s\n",
  685. MAX_TAG_WIDTH_2,
  686. pOutputHeaderNames[i],
  687. m_ppszKnownHeaders[i]
  688. );
  689. }
  690. }
  691. } // end for loop
  692. // for loop
  693. for ( DWORD i = 0; i < m_dwNumUnknownHeaders; i++)
  694. {
  695. printf ( " %-*s: %s\n",
  696. MAX_TAG_WIDTH_2,
  697. m_ppszUnknownHeaderNames[i],
  698. m_ppszUnknownHeaderValues[i]
  699. );
  700. }
  701. end:
  702. return;
  703. }