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.

691 lines
18 KiB

  1. // ===========================================================================
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. // PARTICULAR PURPOSE.
  6. //
  7. // Copyright 1996 Microsoft Corporation. All Rights Reserved.
  8. // ===========================================================================
  9. #include <windows.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include <stdlib.h>
  14. #include <io.h>
  15. #include <winhttp.h>
  16. #define _UNICODE
  17. #include <tchar.h>
  18. //==============================================================================
  19. //#define GLOBAL_SESSION 1
  20. #ifdef GLOBAL_SESSION
  21. HINTERNET g_hInternet = NULL;
  22. #endif
  23. #ifndef ASSERT
  24. #define ASSERT( exp ) \
  25. ((!(exp)) ? \
  26. DebugBreak() : \
  27. ((void)0))
  28. #endif
  29. typedef enum
  30. {
  31. HTTP_INIT = 0,
  32. HTTP_OPEN = 1,
  33. HTTP_SEND = 2,
  34. HTTP_QDA = 3,
  35. HTTP_READ = 4,
  36. HTTP_READ_PASS_SYNC = 5,
  37. HTTP_READ_PASS_ASYNC = 6,
  38. HTTP_READ_FAIL_SYNC = 7,
  39. HTTP_READ_FAIL_ASYNC = 8,
  40. HTTP_SEND_FAIL_SYNC = 9,
  41. HTTP_SEND_FAIL_ASYNC = 10
  42. } HTTP_STATE;
  43. typedef struct
  44. {
  45. HTTP_STATE state;
  46. BOOL bQDA;
  47. DWORD dwTotal;
  48. DWORD_PTR dwResult;
  49. DWORD dwError;
  50. HANDLE hEvent;
  51. DWORD dwSignature;
  52. BOOL bCallbackDelete;
  53. } TestContext;
  54. VOID CALLBACK Callback(IN HINTERNET hInternet, IN DWORD_PTR dwContext,
  55. IN DWORD dwStatus, IN LPVOID pvInfo, IN DWORD dwStatusLen)
  56. {
  57. #if 0
  58. fprintf(stderr, "callback!!!!!! dwStatus %d\n", dwStatus);
  59. #endif
  60. TestContext* pContext = (TestContext*)dwContext;
  61. if ((dwStatus == WINHTTP_CALLBACK_STATUS_REQUEST_COMPLETE) && pContext)
  62. {
  63. ASSERT (pContext->dwSignature == 0);
  64. if (pContext->bCallbackDelete)
  65. {
  66. delete pContext;
  67. goto end;
  68. }
  69. DWORD_PTR dwResult = ((LPWINHTTP_ASYNC_RESULT)(pvInfo))->dwResult;
  70. DWORD dwError = ((LPWINHTTP_ASYNC_RESULT) (pvInfo) )->dwError;
  71. pContext->dwResult = dwResult;
  72. pContext->dwError = dwError;
  73. SetEvent(pContext->hEvent);
  74. #if 0
  75. OutputDebugString("\n\tWINHTTP_CALLBACK_STATUS_REQUEST_COMPLETE for QDA\n");
  76. fprintf(stderr, "\n\tWINHTTP_CALLBACK_STATUS_REQUEST_COMPLETE for QDA with %d result and %d error.\n", dwResult, dwBytes);
  77. #endif
  78. }
  79. end:
  80. return;
  81. }
  82. #define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
  83. //==============================================================================
  84. int RequestLoop (int argc, char **argv)
  85. {
  86. #ifndef GLOBAL_SESSION
  87. HINTERNET g_hInternet = NULL;
  88. #endif
  89. HINTERNET hConnect = NULL;
  90. HINTERNET hRequest = NULL;
  91. DWORD dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
  92. WCHAR szProxyServer[256];
  93. WCHAR szProxyBypass[256];
  94. DWORD dwConnectFlags = 0;
  95. BOOL fPreAuth = FALSE;
  96. PSTR pPostData = NULL;
  97. DWORD cbPostData = 0;
  98. PSTR pszErr = NULL;
  99. BOOL fRet;
  100. DWORD dwErr = ERROR_SUCCESS;
  101. DWORD dwTarget = WINHTTP_AUTH_TARGET_SERVER;
  102. LPVOID pAuthParams = NULL;
  103. DWORD option = WINHTTP_OPTION_RESOLVE_TIMEOUT;
  104. DWORD dwTimeout = 1000;
  105. HANDLE hEvent = NULL;
  106. PSTR pszObject = NULL;
  107. PSTR pszPostFile = NULL;
  108. char pszHost[128];
  109. PSTR pszColon = NULL;
  110. BOOL bDeleteContext = TRUE;
  111. TestContext* pContext = new TestContext();
  112. CHECK_ERROR(pContext, "new TestContext");
  113. memset(pContext, 0, sizeof(TestContext));
  114. // Parse options.
  115. while (argc && argv[0][0] == '-')
  116. {
  117. switch (tolower(argv[0][1]))
  118. {
  119. case 'p':
  120. dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  121. dwTarget = WINHTTP_AUTH_TARGET_PROXY;
  122. ::MultiByteToWideChar(CP_ACP, 0, argv[1], -1, &szProxyServer[0], 256);
  123. // pszProxyServer = argv[1];
  124. ::MultiByteToWideChar(CP_ACP, 0, "<local>", -1, &szProxyBypass[0], 256);
  125. // pszProxyBypass = "<local>";
  126. argv++;
  127. argc--;
  128. break;
  129. case 's':
  130. dwConnectFlags = WINHTTP_FLAG_SECURE;
  131. break;
  132. case 'a':
  133. fPreAuth = TRUE;
  134. break;
  135. default:
  136. fprintf (stderr, "\nUsage: httpauth [-p <proxy>] [-s] <server> [<object> [<user> [<pass> [<POST-file>]]]]");
  137. fprintf (stderr, "\n -s: Secure connection (ssl or pct)");
  138. fprintf (stderr, "\n -p: specify proxy server. (\"<local>\" assumed for bypass.)");
  139. exit (1);
  140. }
  141. argv++;
  142. argc--;
  143. }
  144. // Parse host:port
  145. {
  146. int nlen = strlen(argv[0]);
  147. if (nlen > sizeof(pszHost))
  148. goto done;
  149. strcpy(pszHost, argv[0]);
  150. }
  151. DWORD dwPort;
  152. pszColon = strchr(pszHost, ':');
  153. if (!pszColon)
  154. dwPort = INTERNET_DEFAULT_PORT;
  155. else
  156. {
  157. *pszColon++ = 0;
  158. dwPort = atol (pszColon);
  159. }
  160. pszObject = argc >= 2 ? argv[1] : "/";
  161. pszPostFile = argc >= 3 ? argv[2] : NULL;
  162. // Read any POST data into a buffer.
  163. if (pszPostFile)
  164. {
  165. HANDLE hf =
  166. CreateFile
  167. (
  168. pszPostFile,
  169. GENERIC_READ,
  170. FILE_SHARE_READ,
  171. NULL,
  172. OPEN_EXISTING,
  173. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  174. NULL
  175. );
  176. if (hf != INVALID_HANDLE_VALUE)
  177. {
  178. cbPostData = GetFileSize (hf, NULL);
  179. pPostData = (PSTR) LocalAlloc (LMEM_FIXED, cbPostData + 1);
  180. if (pPostData)
  181. ReadFile (hf, pPostData, cbPostData, &cbPostData, NULL);
  182. pPostData[cbPostData] = 0;
  183. CloseHandle (hf);
  184. }
  185. }
  186. // Initialize wininet.
  187. #ifdef GLOBAL_SESSION
  188. if (!g_hInternet)
  189. #endif
  190. g_hInternet = WinHttpOpen
  191. (
  192. _T("HttpAuth Sample"), // user agent
  193. // "Mozilla/4.0 (compatible; MSIE 4.0b2; Windows 95",
  194. dwAccessType, // access type
  195. szProxyServer, // proxy server
  196. szProxyBypass, // proxy bypass
  197. WINHTTP_FLAG_ASYNC // flags
  198. );
  199. CHECK_ERROR (g_hInternet, "WinHttpOpen");
  200. WCHAR szHost[256];
  201. ::MultiByteToWideChar(CP_ACP, 0, pszHost, -1, &szHost[0], 256);
  202. WinHttpSetStatusCallback(g_hInternet, Callback, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, NULL);
  203. dwTimeout = 1000;
  204. WinHttpSetOption(
  205. g_hInternet,
  206. WINHTTP_OPTION_RESOLVE_TIMEOUT,
  207. (LPVOID)&dwTimeout,
  208. sizeof(DWORD)
  209. );
  210. dwTimeout = 1000;
  211. WinHttpSetOption(
  212. g_hInternet,
  213. WINHTTP_OPTION_CONNECT_TIMEOUT,
  214. (LPVOID)&dwTimeout,
  215. sizeof(DWORD)
  216. );
  217. dwTimeout = 100;
  218. WinHttpSetOption(
  219. g_hInternet,
  220. WINHTTP_OPTION_SEND_TIMEOUT,
  221. (LPVOID)&dwTimeout,
  222. sizeof(DWORD)
  223. );
  224. dwTimeout = 100;
  225. WinHttpSetOption(
  226. g_hInternet,
  227. WINHTTP_OPTION_RECEIVE_TIMEOUT,
  228. (LPVOID)&dwTimeout,
  229. sizeof(DWORD)
  230. );
  231. hEvent = CreateEvent(NULL, FALSE /*want auto-reset*/, FALSE /*non-signaled init.*/, NULL);
  232. CHECK_ERROR(hEvent, "CreateEvent");
  233. pContext->hEvent = hEvent;
  234. // Connect to host.
  235. hConnect = WinHttpConnect
  236. (
  237. g_hInternet, // session handle,
  238. szHost, // host
  239. (INTERNET_PORT) dwPort, // port
  240. dwConnectFlags // flags
  241. );
  242. CHECK_ERROR (hConnect, "WinHttpConnect");
  243. WCHAR szObject[256];
  244. ::MultiByteToWideChar(CP_ACP, 0, pszObject, -1, &szObject[0], 256);
  245. // Create request.
  246. pContext->state = HTTP_OPEN;
  247. hRequest = WinHttpOpenRequest
  248. (
  249. hConnect, // connect handle
  250. pszPostFile? _T("POST") : _T("GET"), // request method
  251. szObject, // object name
  252. NULL, // version
  253. NULL, // referer
  254. NULL, // accept types
  255. dwConnectFlags // flags
  256. );
  257. CHECK_ERROR (hRequest, "WinHttpOpenRequest");
  258. // Send request.
  259. pContext->state = HTTP_SEND;
  260. fRet = WinHttpSendRequest
  261. (
  262. hRequest, // request handle
  263. _T(""), // header string
  264. 0, // header length
  265. pPostData, // post data
  266. cbPostData, // post data length
  267. cbPostData, // total post length
  268. (DWORD_PTR)pContext // context
  269. );
  270. if (!fRet)
  271. {
  272. dwErr = GetLastError();
  273. switch (dwErr)
  274. {
  275. case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
  276. break;
  277. case ERROR_IO_PENDING:
  278. fRet = WinHttpReceiveResponse(hRequest, NULL);
  279. if (!fRet)
  280. {
  281. dwErr = GetLastError();
  282. if (dwErr != ERROR_IO_PENDING)
  283. {
  284. fprintf (stderr, "WinHttpReceiveResponse failed err=%d\n", dwErr);
  285. break;
  286. }
  287. }
  288. goto async;
  289. default:
  290. fprintf (stderr, "HttpSendRequest failed err=%d\n", dwErr);
  291. }
  292. pContext->state = HTTP_SEND_FAIL_SYNC;
  293. goto done;
  294. }
  295. else
  296. {
  297. fRet = WinHttpReceiveResponse(hRequest, NULL);
  298. if (!fRet)
  299. {
  300. dwErr = GetLastError();
  301. fprintf (stderr, "WinHttpReceiveResponse failed err=%d\n", dwErr);
  302. pContext->state = HTTP_SEND_FAIL_SYNC;
  303. }
  304. goto sync;
  305. }
  306. async:
  307. #if 0
  308. fprintf(stderr, "\nERROR_IO_PENDING on HSR...\n");
  309. #endif
  310. WaitForSingleObject(hEvent, INFINITE);
  311. ASSERT( pContext->state == HTTP_SEND );
  312. if (! (pContext->dwResult) )
  313. {
  314. pContext->state = HTTP_SEND_FAIL_ASYNC;
  315. SetLastError (pContext->dwError);
  316. goto done;
  317. }
  318. sync:
  319. // Get status code.
  320. DWORD dwStatus, cbStatus;
  321. cbStatus = sizeof(dwStatus);
  322. WinHttpQueryHeaders
  323. (
  324. hRequest,
  325. WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY_STATUS_CODE,
  326. NULL,
  327. &dwStatus,
  328. &cbStatus,
  329. NULL
  330. );
  331. fprintf (stderr, "Status: %d\n", dwStatus);
  332. // Dump some bytes.
  333. BYTE bBuf[1024];
  334. DWORD cbBuf;
  335. #define QDA 1
  336. #ifdef QDA
  337. while (TRUE)
  338. {
  339. BOOL bAsyncRead = FALSE;
  340. pContext->state = HTTP_QDA;
  341. fRet = WinHttpQueryDataAvailable (hRequest, &(pContext->dwError));
  342. if (!fRet)
  343. {
  344. if (GetLastError() == ERROR_IO_PENDING)
  345. {
  346. #if 0
  347. OutputDebugString("\nERROR_IO_PENDING on QDA\n");
  348. fprintf(stderr, "\nERROR_IO_PENDING on QDA...\n");
  349. #endif
  350. WaitForSingleObject(hEvent, INFINITE);
  351. ASSERT (pContext->state = HTTP_QDA);
  352. if (!(pContext->dwResult))
  353. {
  354. // Done
  355. pContext->state = HTTP_READ_FAIL_ASYNC;
  356. SetLastError(pContext->dwError);
  357. goto done;
  358. }
  359. else if (!(pContext->dwError))
  360. {
  361. pContext->state = HTTP_READ_PASS_ASYNC;
  362. goto done;
  363. }
  364. bAsyncRead = TRUE;
  365. }
  366. else
  367. {
  368. pContext->state = HTTP_READ_FAIL_SYNC;
  369. goto done;
  370. }
  371. }
  372. else if (!(pContext->dwError))
  373. {
  374. //Done sync
  375. pContext->state = HTTP_READ_PASS_SYNC;
  376. goto done;
  377. }
  378. DWORD dwRead = pContext->dwError;
  379. DWORD dwActuallyRead = 0;
  380. while (dwRead > 0)
  381. {
  382. cbBuf = (dwRead > sizeof(bBuf)) ? sizeof(bBuf) : dwRead;
  383. pContext->state = HTTP_READ;
  384. fRet = WinHttpReadData(hRequest, bBuf, cbBuf, &dwActuallyRead);
  385. if (!fRet)
  386. {
  387. ASSERT ( GetLastError() != ERROR_IO_PENDING );
  388. fprintf(stderr, "\nError in WinHttpReadData = %d\n", GetLastError());
  389. goto done;
  390. }
  391. ASSERT((cbBuf == dwActuallyRead));
  392. #if 0
  393. ASSERT(fRet);
  394. fwrite (bBuf, 1, dwActuallyRead, stdout);
  395. #endif
  396. pContext->dwTotal += dwActuallyRead;
  397. dwRead -= dwActuallyRead;
  398. }
  399. }
  400. #else
  401. cbBuf = sizeof(bBuf);
  402. while (WinHttpReadData (hRequest, bBuf, cbBuf, &(pContext->dwRead)) && pContext->dwRead)
  403. fwrite (bBuf, 1, pContext->dwRead, stdout);
  404. #endif
  405. done: // Clean up.
  406. if (pszErr)
  407. fprintf (stderr, "Failed on %s, last error %d\n", pszErr, GetLastError());
  408. if (hRequest)
  409. WinHttpCloseHandle (hRequest);
  410. if (hConnect)
  411. WinHttpCloseHandle (hConnect);
  412. #ifndef GLOBAL_SESSION
  413. if (g_hInternet)
  414. WinHttpCloseHandle (g_hInternet);
  415. #endif
  416. if (pPostData)
  417. LocalFree (pPostData);
  418. if (hEvent)
  419. CloseHandle(hEvent);
  420. if (pContext && bDeleteContext)
  421. {
  422. pContext->dwSignature = 0x41414141;
  423. delete pContext;
  424. }
  425. return 0;
  426. }
  427. //==============================================================================
  428. void ParseArguments
  429. (
  430. LPSTR InBuffer,
  431. LPSTR* CArgv,
  432. DWORD* CArgc
  433. )
  434. {
  435. LPSTR CurrentPtr = InBuffer;
  436. DWORD i = 0;
  437. DWORD Cnt = 0;
  438. for ( ;; ) {
  439. //
  440. // skip blanks.
  441. //
  442. while( *CurrentPtr == ' ' ) {
  443. CurrentPtr++;
  444. }
  445. if( *CurrentPtr == '\0' ) {
  446. break;
  447. }
  448. CArgv[i++] = CurrentPtr;
  449. //
  450. // go to next space.
  451. //
  452. while( (*CurrentPtr != '\0') &&
  453. (*CurrentPtr != '\n') ) {
  454. if( *CurrentPtr == '"' ) { // Deal with simple quoted args
  455. if( Cnt == 0 )
  456. CArgv[i-1] = ++CurrentPtr; // Set arg to after quote
  457. else
  458. *CurrentPtr = '\0'; // Remove end quote
  459. Cnt = !Cnt;
  460. }
  461. if( (Cnt == 0) && (*CurrentPtr == ' ') || // If we hit a space and no quotes yet we are done with this arg
  462. (*CurrentPtr == '\0') )
  463. break;
  464. CurrentPtr++;
  465. }
  466. if( *CurrentPtr == '\0' ) {
  467. break;
  468. }
  469. *CurrentPtr++ = '\0';
  470. }
  471. *CArgc = i;
  472. return;
  473. }
  474. DWORD WINAPI WorkThread1(LPVOID lpParameter)
  475. {
  476. int nCount = 0;
  477. char* pargv[] = {"dennisch", "venkatk/large.html", 0};
  478. while (nCount++ < 500000)
  479. {
  480. fprintf (stderr, "\nLARGE Iteration #%d\n", nCount);
  481. RequestLoop( 2, pargv);
  482. }
  483. fprintf (stderr, "\nLARGE DONE!\n");
  484. return 0;
  485. }
  486. DWORD WINAPI WorkThread2(LPVOID lpParameter)
  487. {
  488. int nCount = 0;
  489. char* pargv[] = {"dennisch", "venkatk/small.html", 0};
  490. while (nCount++ < 3000000)
  491. {
  492. fprintf (stderr, "\nSMALL Iteration #%d\n", nCount);
  493. RequestLoop( 2, pargv);
  494. }
  495. fprintf (stderr, "\nSMALL DONE!\n");
  496. return 0;
  497. }
  498. DWORD WINAPI WorkThread3(LPVOID lpParameter)
  499. {
  500. int nCount = 0;
  501. char* pargv[] = {"venkatk:180", 0};
  502. while (nCount++ < 10000)
  503. {
  504. fprintf (stderr, "\n180 Iteration #%d\n", nCount);
  505. RequestLoop( 1, pargv);
  506. }
  507. fprintf (stderr, "\n180 DONE!\n");
  508. return 0;
  509. }
  510. //==============================================================================
  511. int __cdecl main (int argc, char **argv)
  512. {
  513. char * port;
  514. int nCount = 0;
  515. // Discard program arg.
  516. argv++;
  517. argc--;
  518. #if 1
  519. DWORD dwThreadId;
  520. HANDLE hThread1 = CreateThread(NULL, 0, &WorkThread1,
  521. NULL, 0, &dwThreadId);
  522. Sleep(1000);
  523. HANDLE hThread2 = CreateThread(NULL, 0, &WorkThread2,
  524. NULL, 0, &dwThreadId);
  525. HANDLE hThread3 = CreateThread(NULL, 0, &WorkThread3,
  526. NULL, 0, &dwThreadId);
  527. {
  528. char* pargv[] = {"pmidge", 0};
  529. while (nCount++ < 2000000)
  530. {
  531. fprintf (stderr, "\nPMIDGE Iteration #%d\n", nCount);
  532. RequestLoop( 1, pargv);
  533. }
  534. fprintf (stderr, "\n180 DONE!\n");
  535. }
  536. WaitForSingleObject( hThread1, INFINITE );
  537. WaitForSingleObject( hThread2, INFINITE );
  538. WaitForSingleObject( hThread3, INFINITE );
  539. #endif
  540. #if 0
  541. char* argv_large[] = {"dennisch", "venkatk/large.html", 0};
  542. char* argv_small[] = {"dennisch", "venkatk/small.html", 0};
  543. char* argv_delay[] = {"venkatk:180", 0};
  544. while(nCount++ < 30)
  545. {
  546. RequestLoop( 1, argv_delay );
  547. }
  548. while(nCount++ < 100)
  549. {
  550. #if 0
  551. fprintf (stderr, "\nIteration #%d\n", nCount);
  552. #endif
  553. RequestLoop( 2, argv_large);
  554. RequestLoop( 2, argv_small);
  555. RequestLoop( 1, argv_delay);
  556. }
  557. #endif
  558. fprintf (stderr, "\nIteration #%d\n", nCount);
  559. #if 0
  560. if (argc)
  561. RequestLoop (argc, argv);
  562. else // Enter command prompt loop
  563. {
  564. fprintf (stderr, "\nUsage: [-p <proxy>] [-s] <host>[:port] [<object> [<POST-file>]]");
  565. fprintf (stderr, "\n -s: use secure sockets layer");
  566. fprintf (stderr, "\n -p: specify proxy server. (\"<local>\" assumed for bypass.)");
  567. fprintf (stderr, "\nTo exit input loop, enter no params");
  568. while (1)
  569. {
  570. char szIn[1024];
  571. DWORD argcIn;
  572. LPSTR argvIn[10];
  573. fprintf (stderr, "\nhttpauth> ");
  574. gets (szIn);
  575. argcIn = 0;
  576. ParseArguments (szIn, argvIn, &argcIn);
  577. if (!argcIn)
  578. break;
  579. RequestLoop (argcIn, argvIn);
  580. //g_cbRead=0;
  581. }
  582. }
  583. #endif
  584. #ifdef GLOBAL_SESSION
  585. if (g_hInternet)
  586. WinHttpCloseHandle (g_hInternet);
  587. g_hInternet = NULL;
  588. #endif
  589. }