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.

2247 lines
66 KiB

  1. /*++
  2. Copyright (c) 1994-98 Microsoft Corporation
  3. Module Name:
  4. options.cxx
  5. Abstract:
  6. Contains the Internet*Option APIs
  7. Contents:
  8. InternetQueryOptionA
  9. InternetSetOptionA
  10. WinHttpQueryOption
  11. WinHttpSetOption
  12. (FValidCacheHandleType)
  13. Author:
  14. Richard L Firth (rfirth) 02-Mar-1995
  15. Environment:
  16. Win32 user-mode DLL
  17. Revision History:
  18. 02-Mar-1995 rfirth
  19. Created
  20. 07-Mar-1995 madana
  21. 07-Jul-1998 Forked by akabir
  22. --*/
  23. #include <wininetp.h>
  24. #include <perfdiag.hxx>
  25. #include "msident.h"
  26. //
  27. // private macros
  28. //
  29. //
  30. // IS_PER_THREAD_OPTION - options applicable to the thread (HINTERNET is NULL).
  31. // Subset of IS_VALID_OPTION()
  32. //
  33. #define IS_PER_THREAD_OPTION(option) (( \
  34. ((option) == WINHTTP_OPTION_EXTENDED_ERROR) \
  35. || ((option) == WINHTTP_OPTION_PER_CONNECTION_OPTION) \
  36. ) ? TRUE : FALSE)
  37. //
  38. // IS_PER_PROCESS_OPTION - options applicable to the process (HINTERNET is NULL).
  39. // Subset of IS_VALID_OPTION()
  40. //
  41. #define IS_PER_PROCESS_OPTION(option) \
  42. (( ((option) == WINHTTP_OPTION_GET_DEBUG_INFO) \
  43. || ((option) == WINHTTP_OPTION_SET_DEBUG_INFO) \
  44. || ((option) == WINHTTP_OPTION_GET_HANDLE_COUNT) \
  45. || ((option) == WINHTTP_OPTION_PROXY) \
  46. || ((option) == WINHTTP_OPTION_VERSION) \
  47. || ((option) == WINHTTP_OPTION_HTTP_VERSION) \
  48. || ((option) == WINHTTP_OPTION_DIGEST_AUTH_UNLOAD) \
  49. || ((option) == WINHTTP_OPTION_PER_CONNECTION_OPTION) \
  50. || ((option) == WINHTTP_OPTION_WORKER_THREAD_COUNT) \
  51. ) ? TRUE : FALSE)
  52. //
  53. // IS_DEBUG_OPTION - the set of debug-specific options
  54. //
  55. #define IS_DEBUG_OPTION(option) \
  56. (( ((option) >= INTERNET_FIRST_DEBUG_OPTION) \
  57. && ((option) <= INTERNET_LAST_DEBUG_OPTION) \
  58. ) ? TRUE : FALSE)
  59. //
  60. // IS_VALID_OPTION - the set of known option values, for a HINTERNET, thread, or
  61. // process. In the retail version, debug options are invalid
  62. //
  63. #if INET_DEBUG
  64. #define IS_VALID_OPTION(option) \
  65. (((((option) >= WINHTTP_FIRST_OPTION) \
  66. && ((option) <= WINHTTP_LAST_OPTION_INTERNAL)) \
  67. || IS_DEBUG_OPTION(option) \
  68. ) ? TRUE : FALSE)
  69. #else
  70. #define IS_VALID_OPTION(option) \
  71. (((((option) >= WINHTTP_FIRST_OPTION) \
  72. && ((option) <= WINHTTP_LAST_OPTION_INTERNAL)) \
  73. ) ? TRUE : FALSE)
  74. #endif // INET_DEBUG
  75. //
  76. // private prototypes
  77. //
  78. PRIVATE
  79. BOOL
  80. FValidCacheHandleType(
  81. HINTERNET_HANDLE_TYPE hType
  82. );
  83. PRIVATE
  84. VOID
  85. InitIPCOList(LPINTERNET_PER_CONN_OPTION_LISTW plistW, LPINTERNET_PER_CONN_OPTION_LISTA plistA)
  86. {
  87. plistA->dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA);
  88. plistA->dwOptionCount = plistW->dwOptionCount;
  89. if (plistW->pszConnection && *plistW->pszConnection)
  90. {
  91. SHUnicodeToAnsi(plistW->pszConnection, plistA->pszConnection, RAS_MaxEntryName + 1);
  92. }
  93. else
  94. {
  95. plistA->pszConnection = NULL;
  96. }
  97. }
  98. //
  99. // functions
  100. //
  101. INTERNETAPI
  102. BOOL
  103. WINAPI
  104. InternetQueryOptionA(
  105. IN HINTERNET hInternet OPTIONAL,
  106. IN DWORD dwOption,
  107. OUT LPVOID lpBuffer OPTIONAL,
  108. IN OUT LPDWORD lpdwBufferLength
  109. )
  110. /*++
  111. Routine Description:
  112. Returns information about various handle-specific variables
  113. Arguments:
  114. hInternet - handle of object for which information will be
  115. returned
  116. dwOption - the handle-specific WINHTTP_OPTION to query
  117. lpBuffer - pointer to a buffer which will receive results
  118. lpdwBufferLength - IN: number of bytes available in lpBuffer
  119. OUT: number of bytes returned in lpBuffer
  120. Return Value:
  121. BOOL
  122. Success - TRUE
  123. Failure - FALSE. Call GetLastError() for more info:
  124. ERROR_INVALID_HANDLE
  125. hInternet does not identify a valid Internet handle
  126. object
  127. ERROR_WINHTTP_INTERNAL_ERROR
  128. Shouldn't see this?
  129. ERROR_INVALID_PARAMETER
  130. One of the parameters was bad
  131. ERROR_INSUFFICIENT_BUFFER
  132. lpBuffer is not large enough to hold the requested
  133. information; *lpdwBufferLength contains the number of
  134. bytes needed
  135. ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
  136. The handle is the wrong type for the requested option
  137. ERROR_WINHTTP_INVALID_OPTION
  138. The option is unrecognized
  139. --*/
  140. {
  141. DEBUG_ENTER_API((DBG_API,
  142. Bool,
  143. "InternetQueryOptionA",
  144. "%#x, %s (%d), %#x, %#x [%d]",
  145. hInternet,
  146. InternetMapOption(dwOption),
  147. dwOption,
  148. lpBuffer,
  149. lpdwBufferLength,
  150. lpdwBufferLength
  151. ? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
  152. ? *lpdwBufferLength
  153. : 0)
  154. : 0
  155. ));
  156. DWORD error;
  157. BOOL success;
  158. HINTERNET_HANDLE_TYPE handleType;
  159. LPINTERNET_THREAD_INFO lpThreadInfo;
  160. DWORD requiredSize = 0;
  161. LPVOID lpSource;
  162. DWORD dwValue;
  163. DWORD_PTR dwPtrValue;
  164. HANDLE hValue;
  165. HINTERNET hObjectMapped = NULL;
  166. BOOL isString = FALSE;
  167. INTERNET_DIAGNOSTIC_SOCKET_INFO socketInfo;
  168. if (!GlobalDataInitialized) {
  169. error = GlobalDataInitialize();
  170. if (error != ERROR_SUCCESS) {
  171. goto done;
  172. }
  173. }
  174. lpThreadInfo = InternetGetThreadInfo();
  175. if (lpThreadInfo == NULL) {
  176. error = ERROR_WINHTTP_INTERNAL_ERROR;
  177. goto done;
  178. }
  179. //
  180. // validate parameters
  181. //
  182. INET_ASSERT(lpdwBufferLength);
  183. if (!ARGUMENT_PRESENT(lpBuffer)) {
  184. *lpdwBufferLength = 0;
  185. }
  186. //
  187. // validate the handle and get its type
  188. //
  189. HINTERNET hOriginal;
  190. hOriginal = hInternet;
  191. if (ARGUMENT_PRESENT(hInternet)) {
  192. //
  193. // map the handle
  194. //
  195. error = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
  196. if (error == ERROR_SUCCESS) {
  197. hInternet = hObjectMapped;
  198. error = RGetHandleType(hInternet, &handleType);
  199. }
  200. } else if (IS_PER_THREAD_OPTION(dwOption)) {
  201. //
  202. // this option updates the per-thread information block, so this is a
  203. // good point at which to get it
  204. //
  205. if (lpThreadInfo != NULL) {
  206. error = ERROR_SUCCESS;
  207. } else {
  208. DEBUG_PRINT(INET,
  209. ERROR,
  210. ("InternetGetThreadInfo() returns NULL\n"
  211. ));
  212. //
  213. // we never expect this - ERROR_WINHTTP_SPANISH_INQUISITION
  214. //
  215. INET_ASSERT(FALSE);
  216. error = ERROR_WINHTTP_INTERNAL_ERROR;
  217. }
  218. } else if (IS_PER_PROCESS_OPTION(dwOption)) {
  219. error = ERROR_SUCCESS;
  220. } else {
  221. //
  222. // catch any invalid options for the NULL handle. If the option is valid
  223. // then it is incorrect for this handle type, otherwise its an invalid
  224. // option, period
  225. //
  226. error = IS_VALID_OPTION(dwOption)
  227. ? ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
  228. : ERROR_WINHTTP_INVALID_OPTION
  229. ;
  230. }
  231. //
  232. // if the option and handle combination is valid then query the option value
  233. //
  234. if (error != ERROR_SUCCESS) {
  235. goto quit;
  236. }
  237. HTTP_REQUEST_HANDLE_OBJECT* pReq;
  238. switch (handleType)
  239. {
  240. case TypeHttpRequestHandle:
  241. pReq = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
  242. break;
  243. case TypeInternetHandle:
  244. pReq = NULL;
  245. break;
  246. default:
  247. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  248. goto quit;
  249. }
  250. // New fast path for request handle options.
  251. if (dwOption > WINHTTP_OPTION_MASK)
  252. {
  253. dwOption &= WINHTTP_OPTION_MASK;
  254. if (dwOption > MAX_INTERNET_STRING_OPTION)
  255. error = ERROR_INVALID_PARAMETER;
  256. else if (!pReq)
  257. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  258. else
  259. {
  260. lpSource = pReq->GetProp (dwOption);
  261. isString = TRUE;
  262. error = ERROR_SUCCESS;
  263. }
  264. goto quit;
  265. }
  266. switch (dwOption) {
  267. case WINHTTP_OPTION_CALLBACK:
  268. requiredSize = sizeof(WINHTTP_STATUS_CALLBACK);
  269. if (hInternet != NULL) {
  270. error = RGetStatusCallback(hInternet,
  271. (LPWINHTTP_STATUS_CALLBACK)&dwValue
  272. );
  273. lpSource = (LPVOID)&dwValue;
  274. } else {
  275. error = ERROR_INVALID_HANDLE;
  276. }
  277. break;
  278. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  279. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  280. case WINHTTP_OPTION_CONNECT_RETRIES:
  281. case WINHTTP_OPTION_SEND_TIMEOUT:
  282. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  283. requiredSize = sizeof(DWORD);
  284. //
  285. // remember hInternet in the INTERNET_THREAD_INFO then call
  286. // GetTimeoutValue(). If hInternet refers to a valid Internet
  287. // object handle, then the relevant timeout value will be
  288. // returned from that, else we will return the global value
  289. // corresponding to the requested option
  290. //
  291. InternetSetObjectHandle(hOriginal, hInternet);
  292. dwValue = GetTimeoutValue(dwOption);
  293. lpSource = (LPVOID)&dwValue;
  294. break;
  295. case WINHTTP_OPTION_HANDLE_TYPE:
  296. requiredSize = sizeof(dwValue);
  297. switch (handleType)
  298. {
  299. case TypeInternetHandle:
  300. dwValue = WINHTTP_HANDLE_TYPE_SESSION;
  301. break;
  302. case TypeHttpConnectHandle:
  303. dwValue = WINHTTP_HANDLE_TYPE_CONNECT;
  304. break;
  305. case TypeHttpRequestHandle:
  306. dwValue = WINHTTP_HANDLE_TYPE_REQUEST;
  307. break;
  308. default:
  309. error = ERROR_WINHTTP_INTERNAL_ERROR;
  310. break;
  311. }
  312. lpSource = (LPVOID)&dwValue;
  313. break;
  314. case WINHTTP_OPTION_CONTEXT_VALUE:
  315. requiredSize = sizeof(DWORD_PTR);
  316. error = RGetContext(hInternet, &dwPtrValue);
  317. lpSource = (LPVOID)&dwPtrValue;
  318. break;
  319. case WINHTTP_OPTION_READ_BUFFER_SIZE:
  320. case WINHTTP_OPTION_WRITE_BUFFER_SIZE:
  321. if (pReq)
  322. {
  323. requiredSize = sizeof(DWORD);
  324. error = ERROR_SUCCESS;
  325. dwValue = pReq->GetBufferSize(dwOption);
  326. lpSource = (LPVOID)&dwValue;
  327. }
  328. else
  329. {
  330. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  331. }
  332. break;
  333. case WINHTTP_OPTION_PARENT_HANDLE:
  334. hInternet = ((HANDLE_OBJECT *)hInternet)->GetParent();
  335. if (hInternet != NULL) {
  336. hInternet = ((HANDLE_OBJECT *)hInternet)->GetPseudoHandle();
  337. }
  338. requiredSize = sizeof(hInternet);
  339. lpSource = (LPVOID)&hInternet;
  340. break;
  341. case WINHTTP_OPTION_EXTENDED_ERROR:
  342. requiredSize = sizeof(lpThreadInfo->dwMappedErrorCode);
  343. lpSource = (LPVOID)&lpThreadInfo->dwMappedErrorCode;
  344. break;
  345. case WINHTTP_OPTION_SECURITY_FLAGS:
  346. if (handleType != TypeHttpRequestHandle)
  347. {
  348. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  349. }
  350. else
  351. {
  352. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  353. requiredSize = sizeof(dwValue);
  354. dwValue = 0;
  355. lpSource = (LPVOID)&dwValue;
  356. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  357. dwValue = lphHttpRqst->GetSecureFlags();
  358. DEBUG_PRINT(INET,
  359. INFO,
  360. ("SECURITY_FLAGS: %X\n",
  361. dwValue
  362. ));
  363. error = ERROR_SUCCESS;
  364. }
  365. break;
  366. case WINHTTP_OPTION_URL:
  367. //
  368. // return the URL associated with the request handle. This may be
  369. // different from the original URL due to redirections
  370. //
  371. if (pReq)
  372. {
  373. //
  374. // only these handle types (retrieved object handles) can have
  375. // associated URLs
  376. //
  377. lpSource = pReq->GetURL();
  378. isString = TRUE;
  379. INET_ASSERT(error == ERROR_SUCCESS);
  380. }
  381. else
  382. {
  383. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  384. }
  385. break;
  386. case WINHTTP_OPTION_SECURITY_CONNECTION_INFO:
  387. //
  388. // Caller is expected to pass in an INTERNET_SECURITY_CONNECTION_INFO structure.
  389. if (handleType != TypeHttpRequestHandle) {
  390. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  391. } else if (*lpdwBufferLength < (DWORD)sizeof(INTERNET_SECURITY_CONNECTION_INFO)) {
  392. requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
  393. *lpdwBufferLength = requiredSize;
  394. error = ERROR_INSUFFICIENT_BUFFER;
  395. } else {
  396. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  397. LPINTERNET_SECURITY_CONNECTION_INFO lpSecConnInfo;
  398. INTERNET_SECURITY_INFO ciInfo;
  399. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *)hInternet;
  400. lpSecConnInfo = (LPINTERNET_SECURITY_CONNECTION_INFO)lpBuffer;
  401. requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
  402. if ((error = lphHttpRqst->GetSecurityInfo(&ciInfo)) == ERROR_SUCCESS) {
  403. // Set up that data members in the structure passed in.
  404. lpSecConnInfo->fSecure = TRUE;
  405. lpSecConnInfo->dwProtocol = ciInfo.dwProtocol;
  406. lpSecConnInfo->aiCipher = ciInfo.aiCipher;
  407. lpSecConnInfo->dwCipherStrength = ciInfo.dwCipherStrength;
  408. lpSecConnInfo->aiHash = ciInfo.aiHash;
  409. lpSecConnInfo->dwHashStrength = ciInfo.dwHashStrength;
  410. lpSecConnInfo->aiExch = ciInfo.aiExch;
  411. lpSecConnInfo->dwExchStrength = ciInfo.dwExchStrength;
  412. if (ciInfo.pCertificate)
  413. {
  414. WRAP_REVERT_USER_VOID(CertFreeCertificateContext, (ciInfo.pCertificate));
  415. }
  416. } else if (error == ERROR_WINHTTP_INTERNAL_ERROR) {
  417. // This implies we are not secure.
  418. error = ERROR_SUCCESS;
  419. lpSecConnInfo->fSecure = FALSE;
  420. }
  421. lpSecConnInfo->dwSize = requiredSize;
  422. *lpdwBufferLength = requiredSize;
  423. }
  424. goto quit;
  425. case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
  426. //
  427. // Allocates memory that caller is expected to free.
  428. //
  429. if (handleType != TypeHttpRequestHandle) {
  430. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  431. } else {
  432. LPTSTR szResult = NULL;
  433. DWORD cchNeedLen = 0;
  434. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  435. INTERNET_SECURITY_INFO cInfo;
  436. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  437. requiredSize = sizeof(INTERNET_CERTIFICATE_INFO);
  438. if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
  439. {
  440. error = ConvertSecurityInfoIntoCertInfoStruct(&cInfo, (LPINTERNET_CERTIFICATE_INFO)lpBuffer, lpdwBufferLength);
  441. if(cInfo.pCertificate)
  442. {
  443. WRAP_REVERT_USER_VOID(CertFreeCertificateContext, (cInfo.pCertificate));
  444. }
  445. goto quit;
  446. }
  447. else
  448. {
  449. error = ERROR_INVALID_OPERATION;
  450. }
  451. }
  452. break;
  453. case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
  454. if (handleType != TypeHttpRequestHandle)
  455. {
  456. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  457. }
  458. else
  459. {
  460. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  461. INTERNET_SECURITY_INFO cInfo;
  462. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  463. requiredSize = sizeof(PCERT_CONTEXT);
  464. if (lpBuffer)
  465. {
  466. if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
  467. {
  468. // GetSecurityInfo calls CertDuplicateCertificateContext, so
  469. // the client app should call CertFreeCertificateContext when
  470. // finished in order to maintain the proper ref count.
  471. *((PCCERT_CONTEXT *) lpBuffer) = cInfo.pCertificate;
  472. }
  473. else
  474. {
  475. error = ERROR_INVALID_OPERATION;
  476. }
  477. }
  478. }
  479. case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
  480. if (handleType != TypeHttpRequestHandle)
  481. {
  482. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  483. }
  484. else
  485. {
  486. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  487. INTERNET_SECURITY_INFO secInfo;
  488. requiredSize = sizeof(dwValue);
  489. dwValue = 0;
  490. lpSource = (LPVOID)&dwValue;
  491. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  492. if (ERROR_SUCCESS != lphHttpRqst->GetSecurityInfo(&secInfo)) {
  493. error = ERROR_INVALID_OPERATION;
  494. } else {
  495. dwValue = secInfo.dwCipherStrength;
  496. WRAP_REVERT_USER_VOID(CertFreeCertificateContext,
  497. (secInfo.pCertificate));
  498. INET_ASSERT (error == ERROR_SUCCESS);
  499. DEBUG_PRINT(INET,
  500. INFO,
  501. ("SECURITY_KEY_BITNESS: %X\n",
  502. dwValue
  503. ));
  504. }
  505. }
  506. break;
  507. case WINHTTP_OPTION_PROXY:
  508. if (!ARGUMENT_PRESENT(hInternet)) {
  509. error = g_pGlobalProxyInfo->GetProxyStringInfo(lpBuffer, lpdwBufferLength);
  510. requiredSize = *lpdwBufferLength;
  511. goto quit;
  512. } else if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle)) {
  513. //
  514. // GetProxyInfo() will return the data, or calculate the buffer
  515. // length required
  516. //
  517. error = ((INTERNET_HANDLE_BASE *)hInternet)->GetProxyStringInfo(
  518. lpBuffer,
  519. lpdwBufferLength
  520. );
  521. requiredSize = *lpdwBufferLength;
  522. goto quit;
  523. } else {
  524. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  525. }
  526. break;
  527. case WINHTTP_OPTION_VERSION:
  528. requiredSize = sizeof(InternetVersionInfo);
  529. lpSource = (LPVOID)&InternetVersionInfo;
  530. break;
  531. case WINHTTP_OPTION_USER_AGENT:
  532. if (handleType == TypeInternetHandle) {
  533. lpSource = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetUserAgent();
  534. isString = TRUE;
  535. } else {
  536. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  537. }
  538. break;
  539. case WINHTTP_OPTION_REQUEST_PRIORITY:
  540. if (handleType == TypeHttpRequestHandle) {
  541. requiredSize = sizeof(dwValue);
  542. dwValue = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetPriority();
  543. lpSource = (LPVOID)&dwValue;
  544. } else {
  545. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  546. }
  547. break;
  548. case WINHTTP_OPTION_HTTP_VERSION:
  549. requiredSize = sizeof(HttpVersionInfo);
  550. lpSource = (LPVOID)&HttpVersionInfo;
  551. break;
  552. case WINHTTP_OPTION_DIAGNOSTIC_SOCKET_INFO:
  553. //
  554. // internal option
  555. //
  556. if (pReq) {
  557. requiredSize = sizeof(socketInfo);
  558. lpSource = (LPVOID)&socketInfo;
  559. socketInfo.Socket = pReq->GetSocket();
  560. socketInfo.SourcePort = pReq->GetSourcePort();
  561. socketInfo.DestPort = pReq->GetDestPort();
  562. socketInfo.Flags = (pReq->FromKeepAlivePool()
  563. ? IDSI_FLAG_KEEP_ALIVE : 0)
  564. | (pReq->IsSecure()
  565. ? IDSI_FLAG_SECURE : 0)
  566. | (pReq->IsRequestUsingProxy()
  567. ? IDSI_FLAG_PROXY : 0)
  568. | (pReq->IsTunnel()
  569. ? IDSI_FLAG_TUNNEL : 0);
  570. } else {
  571. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  572. }
  573. break;
  574. case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
  575. case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
  576. if (hInternet)
  577. {
  578. if (handleType == TypeInternetHandle)
  579. {
  580. requiredSize = sizeof(dwValue);
  581. dwValue = 0;
  582. lpSource = (LPVOID)&dwValue;
  583. dwValue = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetMaxConnectionsPerServer(dwOption);
  584. }
  585. else
  586. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  587. }
  588. else
  589. error = ERROR_INVALID_OPERATION;
  590. break;
  591. case WINHTTP_OPTION_PER_CONNECTION_OPTION:
  592. {
  593. if (handleType != TypeInternetHandle) {
  594. hInternet = NULL;
  595. }
  596. error = QueryPerConnOptions(hInternet,
  597. FALSE,
  598. (LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
  599. requiredSize = *lpdwBufferLength;
  600. goto quit;
  601. }
  602. case WINHTTP_OPTION_WORKER_THREAD_COUNT:
  603. requiredSize = sizeof(DWORD);
  604. dwValue = g_cNumIOCPThreads;
  605. lpSource = (LPVOID)&dwValue;
  606. break;
  607. #if INET_DEBUG
  608. case WINHTTP_OPTION_GET_DEBUG_INFO:
  609. error = InternetGetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
  610. lpdwBufferLength
  611. );
  612. //
  613. // everything updated, so quit without going through common buffer
  614. // processing
  615. //
  616. goto quit;
  617. break;
  618. case WINHTTP_OPTION_GET_HANDLE_COUNT:
  619. requiredSize = sizeof(DWORD);
  620. dwValue = InternetHandleCount();
  621. lpSource = (LPVOID)&dwValue;
  622. break;
  623. #endif // INET_DEBUG
  624. default:
  625. requiredSize = 0;
  626. error = ERROR_INVALID_PARAMETER;
  627. break;
  628. }
  629. //
  630. // if we have a buffer and enough space, then copy the data
  631. //
  632. if (error == ERROR_SUCCESS) {
  633. //
  634. // if we are returning a string, calculate the amount of space
  635. // required to hold it
  636. //
  637. if (isString) {
  638. if (lpSource != NULL) {
  639. requiredSize = lstrlen((LPCSTR)lpSource) + 1;
  640. } else {
  641. //
  642. // option string is NULL: return an empty string
  643. //
  644. lpSource = "";
  645. requiredSize = 1;
  646. }
  647. }
  648. INET_ASSERT(lpSource != NULL);
  649. if ((*lpdwBufferLength >= requiredSize)
  650. && ARGUMENT_PRESENT(lpBuffer)) {
  651. memcpy(lpBuffer, lpSource, requiredSize);
  652. if (isString) {
  653. //
  654. // string copied successfully. Returned length is string
  655. // length, not buffer length, i.e. drop 1 for '\0'
  656. //
  657. --requiredSize;
  658. }
  659. } else {
  660. error = ERROR_INSUFFICIENT_BUFFER;
  661. }
  662. }
  663. quit:
  664. //
  665. // return the amount the app needs to supply, or the amount of data in the
  666. // buffer, depending on success/failure status
  667. //
  668. *lpdwBufferLength = requiredSize;
  669. if (hObjectMapped != NULL) {
  670. DereferenceObject((LPVOID)hObjectMapped);
  671. }
  672. done:
  673. if (error == ERROR_SUCCESS) {
  674. success = TRUE;
  675. IF_DEBUG(API) {
  676. if (isString) {
  677. DEBUG_PRINT_API(API,
  678. INFO,
  679. ("returning %q (%d chars)\n",
  680. lpBuffer,
  681. requiredSize
  682. ));
  683. } else {
  684. DEBUG_DUMP_API(API,
  685. "option data:\n",
  686. lpBuffer,
  687. requiredSize
  688. );
  689. }
  690. }
  691. } else {
  692. DEBUG_ERROR(API, error);
  693. IF_DEBUG(API) {
  694. if (error == ERROR_INSUFFICIENT_BUFFER) {
  695. DEBUG_PRINT_API(API,
  696. INFO,
  697. ("*lpdwBufferLength (%#x)= %d\n",
  698. lpdwBufferLength,
  699. *lpdwBufferLength
  700. ));
  701. }
  702. }
  703. SetLastError(error);
  704. success = FALSE;
  705. }
  706. DEBUG_LEAVE_API(success);
  707. return success;
  708. }
  709. INTERNETAPI
  710. BOOL
  711. WINAPI
  712. WinHttpQueryOption(
  713. IN HINTERNET hInternet OPTIONAL,
  714. IN DWORD dwOption,
  715. OUT LPVOID lpBuffer OPTIONAL,
  716. IN OUT LPDWORD lpdwBufferLength
  717. )
  718. /*++
  719. Routine Description:
  720. description-of-function.
  721. Arguments:
  722. hInternet -
  723. dwOption -
  724. lpBuffer -
  725. lpdwBufferLength -
  726. Return Value:
  727. BOOL
  728. --*/
  729. {
  730. DEBUG_ENTER_API((DBG_API,
  731. Bool,
  732. "WinHttpQueryOption",
  733. "%#x, %s (%d), %#x, %#x [%d]",
  734. hInternet,
  735. InternetMapOption(dwOption),
  736. dwOption,
  737. lpBuffer,
  738. lpdwBufferLength,
  739. lpdwBufferLength
  740. ? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
  741. ? *lpdwBufferLength
  742. : 0)
  743. : 0
  744. ));
  745. DWORD dwErr = ERROR_SUCCESS;
  746. BOOL fResult = FALSE;
  747. MEMORYPACKET mpBuffer;
  748. if (!lpdwBufferLength
  749. || IsBadWritePtr(lpdwBufferLength, sizeof(*lpdwBufferLength))
  750. || (lpBuffer && *lpdwBufferLength && IsBadWritePtr(lpBuffer, *lpdwBufferLength)) )
  751. {
  752. dwErr = ERROR_INVALID_PARAMETER;
  753. goto cleanup;
  754. }
  755. switch (dwOption)
  756. {
  757. case WINHTTP_OPTION_USERNAME:
  758. case WINHTTP_OPTION_PASSWORD:
  759. case WINHTTP_OPTION_URL:
  760. case WINHTTP_OPTION_USER_AGENT:
  761. case WINHTTP_OPTION_PROXY_USERNAME:
  762. case WINHTTP_OPTION_PROXY_PASSWORD:
  763. if (lpBuffer)
  764. {
  765. mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwBufferLength;
  766. mpBuffer.psStr = (LPSTR)ALLOC_BYTES(mpBuffer.dwAlloc*sizeof(CHAR));
  767. if (!mpBuffer.psStr)
  768. {
  769. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  770. break;
  771. }
  772. }
  773. fResult = InternetQueryOptionA(hInternet,
  774. dwOption,
  775. (LPVOID)mpBuffer.psStr,
  776. &mpBuffer.dwSize
  777. );
  778. if (fResult)
  779. {
  780. *lpdwBufferLength = sizeof(WCHAR) *
  781. MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1, NULL, 0);
  782. if (*lpdwBufferLength <= mpBuffer.dwAlloc && lpBuffer)
  783. {
  784. MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize+1,
  785. (LPWSTR)lpBuffer, *lpdwBufferLength);
  786. (*lpdwBufferLength)-=sizeof(WCHAR);
  787. }
  788. else
  789. {
  790. fResult = FALSE;
  791. dwErr = ERROR_INSUFFICIENT_BUFFER;
  792. }
  793. }
  794. else
  795. {
  796. if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
  797. {
  798. *lpdwBufferLength = mpBuffer.dwSize*sizeof(WCHAR);
  799. }
  800. }
  801. break;
  802. case WINHTTP_OPTION_PER_CONNECTION_OPTION:
  803. {
  804. if (!lpBuffer)
  805. {
  806. dwErr = ERROR_INVALID_PARAMETER;
  807. break;
  808. }
  809. INTERNET_PER_CONN_OPTION_LISTA listA;
  810. LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
  811. CHAR szEntryA[RAS_MaxEntryName + 1];
  812. listA.pszConnection = szEntryA;
  813. InitIPCOList(plistW, &listA);
  814. listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
  815. for (DWORD i=0; i<listA.dwOptionCount; i++)
  816. {
  817. listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
  818. listA.pOptions[i].Value.pszValue = NULL;
  819. plistW->pOptions[i].Value.pszValue = NULL;
  820. }
  821. fResult = InternetQueryOptionA(hInternet,
  822. dwOption,
  823. (PVOID)&listA,
  824. lpdwBufferLength);
  825. // Now, convert from ansi to unicode
  826. if (fResult)
  827. {
  828. for (DWORD i=0; i<listA.dwOptionCount; i++)
  829. {
  830. switch (listA.pOptions[i].dwOption)
  831. {
  832. case INTERNET_PER_CONN_FLAGS:
  833. case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
  834. case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
  835. plistW->pOptions[i].Value.dwValue = listA.pOptions[i].Value.dwValue;
  836. break;
  837. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
  838. plistW->pOptions[i].Value.ftValue = listA.pOptions[i].Value.ftValue;
  839. break;
  840. case INTERNET_PER_CONN_PROXY_SERVER:
  841. case INTERNET_PER_CONN_PROXY_BYPASS:
  842. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  843. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  844. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  845. if (listA.pOptions[i].Value.pszValue && *listA.pOptions[i].Value.pszValue)
  846. {
  847. DWORD cc = MultiByteToWideChar(CP_ACP,
  848. 0,
  849. listA.pOptions[i].Value.pszValue,
  850. -1,
  851. NULL,
  852. 0);
  853. plistW->pOptions[i].Value.pszValue = (PWSTR)GlobalAlloc(GPTR, cc*sizeof(WCHAR));
  854. if (!plistW->pOptions[i].Value.pszValue)
  855. {
  856. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  857. goto iopco_cleanup;
  858. }
  859. MultiByteToWideChar(CP_ACP,
  860. 0,
  861. listA.pOptions[i].Value.pszValue,
  862. -1,
  863. plistW->pOptions[i].Value.pszValue,
  864. cc);
  865. }
  866. break;
  867. default:
  868. INET_ASSERT(FALSE);
  869. dwErr = ERROR_INVALID_PARAMETER;
  870. goto iopco_cleanup;
  871. break;
  872. }
  873. }
  874. }
  875. else
  876. {
  877. plistW->dwOptionError = listA.dwOptionError;
  878. }
  879. iopco_cleanup:
  880. // Free all the allocated buffers
  881. for (i=0; i<listA.dwOptionCount; i++)
  882. {
  883. switch (listA.pOptions[i].dwOption)
  884. {
  885. case INTERNET_PER_CONN_PROXY_SERVER:
  886. case INTERNET_PER_CONN_PROXY_BYPASS:
  887. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  888. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  889. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  890. // These should have been converted from ansi to unicode
  891. // and can be freed now
  892. if (listA.pOptions[i].Value.pszValue)
  893. {
  894. GlobalFree(listA.pOptions[i].Value.pszValue);
  895. }
  896. // No point in passing back buffers in the event of an error
  897. // condition
  898. if (dwErr && plistW->pOptions[i].Value.pszValue)
  899. {
  900. GlobalFree(plistW->pOptions[i].Value.pszValue);
  901. }
  902. break;
  903. default:
  904. // No need to do anything
  905. break;
  906. }
  907. }
  908. }
  909. break;
  910. case WINHTTP_OPTION_PROXY:
  911. {
  912. WINHTTP_PROXY_INFOW * pInfo = (WINHTTP_PROXY_INFOW *) lpBuffer;
  913. union
  914. {
  915. WINHTTP_PROXY_INFOA InfoA;
  916. char Buffer[1024];
  917. };
  918. char * pBuffer;
  919. DWORD dwBufferLen = sizeof(Buffer);
  920. bool fFreeBuffer = false;
  921. if (IsBadWritePtr(pInfo, sizeof(WINHTTP_PROXY_INFOW)) ||
  922. (*lpdwBufferLength < sizeof(WINHTTP_PROXY_INFOW)))
  923. {
  924. dwErr = ERROR_INVALID_PARAMETER;
  925. break;
  926. }
  927. fResult = InternetQueryOptionA(hInternet, WINHTTP_OPTION_PROXY,
  928. (void *) &Buffer,
  929. &dwBufferLen);
  930. if (!fResult && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  931. {
  932. pBuffer = New char[dwBufferLen];
  933. if (pBuffer)
  934. {
  935. fFreeBuffer = true;
  936. fResult = InternetQueryOptionA(hInternet, WINHTTP_OPTION_PROXY,
  937. (void *) pBuffer,
  938. &dwBufferLen);
  939. }
  940. else
  941. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  942. }
  943. if (fResult)
  944. {
  945. pInfo->dwAccessType = InfoA.dwAccessType;
  946. dwErr = AsciiToWideChar_UsingGlobalAlloc(InfoA.lpszProxy,
  947. &(pInfo->lpszProxy));
  948. if (dwErr == ERROR_SUCCESS)
  949. {
  950. dwErr = AsciiToWideChar_UsingGlobalAlloc(InfoA.lpszProxyBypass,
  951. &(pInfo->lpszProxyBypass));
  952. if ((dwErr != ERROR_SUCCESS) && (pInfo->lpszProxy != NULL))
  953. {
  954. GlobalFree(pInfo->lpszProxy);
  955. pInfo->lpszProxy = NULL;
  956. }
  957. }
  958. fResult = (dwErr == ERROR_SUCCESS);
  959. }
  960. if (fFreeBuffer)
  961. {
  962. delete [] pBuffer;
  963. }
  964. }
  965. break;
  966. default:
  967. fResult = InternetQueryOptionA(hInternet,
  968. dwOption,
  969. lpBuffer,
  970. lpdwBufferLength
  971. );
  972. }
  973. cleanup:
  974. if (dwErr!=ERROR_SUCCESS)
  975. {
  976. SetLastError(dwErr);
  977. DEBUG_ERROR(INET, dwErr);
  978. }
  979. DEBUG_LEAVE_API(fResult);
  980. return fResult;
  981. }
  982. INTERNETAPI
  983. BOOL
  984. WINAPI
  985. InternetSetOptionA(
  986. IN HINTERNET hInternet OPTIONAL,
  987. IN DWORD dwOption,
  988. IN LPVOID lpBuffer,
  989. IN DWORD dwBufferLength
  990. )
  991. /*++
  992. Routine Description:
  993. Sets a handle-specific variable, or a per-thread variable
  994. Arguments:
  995. hInternet - handle of object for which information will be set,
  996. or NULL if the option defines a per-thread variable
  997. dwOption - the handle-specific WINHTTP_OPTION to set
  998. lpBuffer - pointer to a buffer containing value to set
  999. dwBufferLength - size of lpBuffer
  1000. Return Value:
  1001. BOOL
  1002. Success - TRUE
  1003. Failure - FALSE. Call GetLastError() for more info:
  1004. ERROR_INVALID_HANDLE
  1005. hInternet does not identify a valid Internet handle
  1006. object
  1007. ERROR_WINHTTP_INTERNAL_ERROR
  1008. Shouldn't see this?
  1009. ERROR_INVALID_PARAMETER
  1010. One of the parameters was bad
  1011. ERROR_WINHTTP_INVALID_OPTION
  1012. The requested option cannot be set
  1013. ERROR_WINHTTP_OPTION_NOT_SETTABLE
  1014. Can't set this option, only query it
  1015. ERROR_INSUFFICIENT_BUFFER
  1016. The dwBufferLength parameter is incorrect for the
  1017. expected type of the option
  1018. --*/
  1019. {
  1020. DEBUG_ENTER_API((DBG_API,
  1021. Bool,
  1022. "InternetSetOptionA",
  1023. "%#x, %s (%d), %#x [%#x], %d",
  1024. hInternet,
  1025. InternetMapOption(dwOption),
  1026. dwOption,
  1027. lpBuffer,
  1028. lpBuffer
  1029. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  1030. ? *(LPDWORD)lpBuffer
  1031. : 0)
  1032. : 0,
  1033. dwBufferLength
  1034. ));
  1035. DWORD error;
  1036. BOOL success = TRUE;
  1037. HINTERNET_HANDLE_TYPE handleType;
  1038. LPINTERNET_THREAD_INFO lpThreadInfo;
  1039. DWORD requiredSize;
  1040. HINTERNET hObjectMapped = NULL;
  1041. INET_ASSERT(dwBufferLength != 0);
  1042. if (!GlobalDataInitialized) {
  1043. error = GlobalDataInitialize();
  1044. if (error != ERROR_SUCCESS) {
  1045. goto done;
  1046. }
  1047. }
  1048. //
  1049. // validate the handle and get its type
  1050. //
  1051. if (ARGUMENT_PRESENT(hInternet)) {
  1052. //
  1053. // map the handle
  1054. //
  1055. error = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
  1056. if (error == ERROR_SUCCESS) {
  1057. hInternet = hObjectMapped;
  1058. error = RGetHandleType(hInternet, &handleType);
  1059. }
  1060. } else if (IS_PER_THREAD_OPTION(dwOption)) {
  1061. //
  1062. // this option updates the per-thread information block, so this is a
  1063. // good point at which to get it
  1064. //
  1065. lpThreadInfo = InternetGetThreadInfo();
  1066. if (lpThreadInfo != NULL) {
  1067. error = ERROR_SUCCESS;
  1068. } else {
  1069. DEBUG_PRINT(INET,
  1070. ERROR,
  1071. ("InternetGetThreadInfo() returns NULL\n"
  1072. ));
  1073. //
  1074. // we never expect this - ERROR_WINHTTP_SPANISH_INQUISITION
  1075. //
  1076. INET_ASSERT(FALSE);
  1077. error = ERROR_WINHTTP_INTERNAL_ERROR;
  1078. }
  1079. } else if (IS_PER_PROCESS_OPTION(dwOption)) {
  1080. error = ERROR_SUCCESS;
  1081. } else {
  1082. //
  1083. // catch any invalid options for the NULL handle. If the option is valid
  1084. // then it is incorrect for this handle type, otherwise its an invalid
  1085. // option, period
  1086. //
  1087. error = IS_VALID_OPTION(dwOption)
  1088. ? ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
  1089. : ERROR_WINHTTP_INVALID_OPTION
  1090. ;
  1091. }
  1092. if (error != ERROR_SUCCESS) {
  1093. goto quit;
  1094. }
  1095. HTTP_REQUEST_HANDLE_OBJECT *pReq;
  1096. switch (handleType)
  1097. {
  1098. case TypeHttpRequestHandle:
  1099. pReq = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
  1100. break;
  1101. case TypeInternetHandle:
  1102. pReq = NULL;
  1103. break;
  1104. default:
  1105. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1106. goto quit;
  1107. }
  1108. // New fast path for request handle options.
  1109. if (dwOption > WINHTTP_OPTION_MASK)
  1110. {
  1111. dwOption &= WINHTTP_OPTION_MASK;
  1112. if (dwOption > MAX_INTERNET_STRING_OPTION)
  1113. error = ERROR_INVALID_PARAMETER;
  1114. else if (!pReq)
  1115. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1116. else if (pReq->SetProp (dwOption, (LPSTR) lpBuffer))
  1117. error = ERROR_SUCCESS;
  1118. else
  1119. error = ERROR_WINHTTP_INTERNAL_ERROR;
  1120. goto quit;
  1121. }
  1122. //
  1123. // if the option and handle combination is valid then set the option value
  1124. //
  1125. switch (dwOption) {
  1126. case WINHTTP_OPTION_CALLBACK:
  1127. case WINHTTP_OPTION_HANDLE_TYPE:
  1128. // these options cannot be set by this function
  1129. error = ERROR_WINHTTP_OPTION_NOT_SETTABLE;
  1130. break;
  1131. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  1132. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  1133. case WINHTTP_OPTION_CONNECT_RETRIES:
  1134. case WINHTTP_OPTION_SEND_TIMEOUT:
  1135. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  1136. requiredSize = sizeof(DWORD);
  1137. if (dwBufferLength != requiredSize)
  1138. {
  1139. error = ERROR_INSUFFICIENT_BUFFER;
  1140. break;
  1141. }
  1142. // For WinHttp, these options are per-handle, not per-process.
  1143. if (hInternet == NULL)
  1144. {
  1145. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1146. break;
  1147. }
  1148. // we have a non-NULL context handle: the app wants to set specific
  1149. // protocol timeouts
  1150. switch (handleType)
  1151. {
  1152. case TypeInternetHandle:
  1153. //only error possible is in allocing memory for OPTIONAL_PARAMS struct
  1154. if (! ((INTERNET_HANDLE_OBJECT*)hObjectMapped)->SetTimeout(dwOption, *(LPDWORD)lpBuffer) )
  1155. {
  1156. error = ERROR_NOT_ENOUGH_MEMORY;
  1157. }
  1158. break;
  1159. case TypeHttpRequestHandle:
  1160. // no errors possible here
  1161. ((HTTP_REQUEST_HANDLE_OBJECT*)hObjectMapped)->SetTimeout(dwOption, *(LPDWORD)lpBuffer);
  1162. break;
  1163. default:
  1164. // any other handle type (?) cannot have timeouts set for it
  1165. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1166. break;
  1167. }
  1168. break;
  1169. case WINHTTP_OPTION_CONTEXT_VALUE:
  1170. //
  1171. // BUGBUG - can't change context if async operation is pending
  1172. //
  1173. if (dwBufferLength == sizeof(LPVOID)) {
  1174. error = RSetContext(hInternet, *((DWORD_PTR *) lpBuffer));
  1175. } else {
  1176. error = ERROR_INSUFFICIENT_BUFFER;
  1177. }
  1178. break;
  1179. case WINHTTP_OPTION_READ_BUFFER_SIZE:
  1180. case WINHTTP_OPTION_WRITE_BUFFER_SIZE:
  1181. if (pReq)
  1182. {
  1183. if (dwBufferLength == sizeof(DWORD))
  1184. {
  1185. DWORD bufferSize;
  1186. bufferSize = *(LPDWORD)lpBuffer;
  1187. if (bufferSize > 0)
  1188. {
  1189. pReq->SetBufferSize(dwOption, bufferSize);
  1190. error = ERROR_SUCCESS;
  1191. }
  1192. else // the read/write buffer size cannot be set to 0
  1193. {
  1194. error = ERROR_INVALID_PARAMETER;
  1195. }
  1196. }
  1197. else
  1198. {
  1199. error = ERROR_INSUFFICIENT_BUFFER;
  1200. }
  1201. }
  1202. else
  1203. {
  1204. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1205. }
  1206. break;
  1207. case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
  1208. if (handleType != TypeHttpRequestHandle)
  1209. {
  1210. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1211. }
  1212. else if (dwBufferLength < sizeof(CERT_CONTEXT))
  1213. {
  1214. error = ERROR_INSUFFICIENT_BUFFER;
  1215. }
  1216. else
  1217. {
  1218. HTTP_REQUEST_HANDLE_OBJECT *pRequest =
  1219. (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1220. CERT_CONTEXT_ARRAY* pArray = pRequest->GetCertContextArray();
  1221. if (!pArray)
  1222. error = ERROR_WINHTTP_NOT_INITIALIZED;
  1223. else
  1224. {
  1225. pArray->Reset();
  1226. pArray->AddCertContext((PCCERT_CONTEXT) lpBuffer);
  1227. pArray->SelectCertContext(0);
  1228. error = ERROR_SUCCESS;
  1229. }
  1230. }
  1231. break;
  1232. case WINHTTP_OPTION_SECURITY_FLAGS:
  1233. if (handleType != TypeHttpRequestHandle)
  1234. {
  1235. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1236. }
  1237. else if (dwBufferLength < sizeof(DWORD))
  1238. {
  1239. error = ERROR_INSUFFICIENT_BUFFER;
  1240. }
  1241. else
  1242. {
  1243. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  1244. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1245. lphHttpRqst->SetSecureFlags(*(LPDWORD)lpBuffer);
  1246. error = ERROR_SUCCESS;
  1247. }
  1248. break;
  1249. case WINHTTP_OPTION_PROXY:
  1250. if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle))
  1251. {
  1252. WINHTTP_PROXY_INFOA * lpInfo = (WINHTTP_PROXY_INFOA *) lpBuffer;
  1253. //
  1254. // validate parameters
  1255. //
  1256. if (dwBufferLength != sizeof(*lpInfo))
  1257. {
  1258. error = ERROR_INSUFFICIENT_BUFFER;
  1259. }
  1260. else if (!((lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)
  1261. || (lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY))
  1262. || ((lpInfo->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
  1263. && ((lpInfo->lpszProxy == NULL) || (*lpInfo->lpszProxy == '\0'))))
  1264. {
  1265. error = ERROR_INVALID_PARAMETER;
  1266. }
  1267. else
  1268. {
  1269. error = ((INTERNET_HANDLE_BASE *)hInternet)->SetProxyInfo(
  1270. lpInfo->dwAccessType,
  1271. lpInfo->lpszProxy,
  1272. lpInfo->lpszProxyBypass
  1273. );
  1274. }
  1275. }
  1276. else
  1277. {
  1278. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1279. }
  1280. break;
  1281. case WINHTTP_OPTION_USER_AGENT:
  1282. if (*(LPSTR)lpBuffer == '\0') {
  1283. error = ERROR_INSUFFICIENT_BUFFER;
  1284. } else {
  1285. if ((handleType == TypeInternetHandle) || (handleType == TypeHttpRequestHandle))
  1286. {
  1287. ((INTERNET_HANDLE_BASE *)hInternet)->SetUserAgent((LPSTR)lpBuffer);
  1288. } else {
  1289. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1290. }
  1291. }
  1292. break;
  1293. case WINHTTP_OPTION_DIGEST_AUTH_UNLOAD:
  1294. if (DIGEST_CTX::g_pFuncTbl)
  1295. {
  1296. DIGEST_CTX::Logoff();
  1297. DIGEST_CTX::g_pFuncTbl = NULL;
  1298. }
  1299. break;
  1300. case WINHTTP_OPTION_REQUEST_PRIORITY:
  1301. if (handleType == TypeHttpRequestHandle) {
  1302. if (dwBufferLength == sizeof(LONG)) {
  1303. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  1304. SetPriority(*(LPLONG)lpBuffer);
  1305. } else {
  1306. error = ERROR_INSUFFICIENT_BUFFER;
  1307. }
  1308. } else {
  1309. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1310. }
  1311. break;
  1312. case WINHTTP_OPTION_HTTP_VERSION:
  1313. if (dwBufferLength == sizeof(HTTP_VERSION_INFO)) {
  1314. HttpVersionInfo = *(LPHTTP_VERSION_INFO)lpBuffer;
  1315. } else {
  1316. error = ERROR_INSUFFICIENT_BUFFER;
  1317. }
  1318. break;
  1319. case WINHTTP_OPTION_DISABLE_FEATURE:
  1320. if (handleType != TypeHttpRequestHandle)
  1321. {
  1322. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1323. }
  1324. else if (dwBufferLength < sizeof(DWORD))
  1325. {
  1326. error = ERROR_INVALID_PARAMETER;
  1327. }
  1328. else
  1329. {
  1330. HTTP_REQUEST_HANDLE_OBJECT *pRequest =
  1331. (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1332. DWORD dwDisable = *((LPDWORD) lpBuffer);
  1333. if (dwDisable & WINHTTP_DISABLE_KEEP_ALIVE)
  1334. {
  1335. DWORD dwFlags = pRequest->GetOpenFlags();
  1336. dwFlags &= ~INTERNET_FLAG_KEEP_CONNECTION;
  1337. pRequest->SetOpenFlags (dwFlags);
  1338. }
  1339. if (dwDisable & WINHTTP_DISABLE_REDIRECTS)
  1340. {
  1341. DWORD dwFlags = pRequest->GetOpenFlags();
  1342. dwFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT;
  1343. pRequest->SetOpenFlags (dwFlags);
  1344. }
  1345. if (dwDisable & WINHTTP_DISABLE_COOKIES)
  1346. {
  1347. DWORD dwFlags = pRequest->GetOpenFlags();
  1348. dwFlags |= INTERNET_FLAG_NO_COOKIES;
  1349. pRequest->SetOpenFlags (dwFlags);
  1350. }
  1351. if (dwDisable & WINHTTP_DISABLE_AUTHENTICATION)
  1352. {
  1353. DWORD dwFlags = pRequest->GetOpenFlags();
  1354. dwFlags |= INTERNET_FLAG_NO_AUTH;
  1355. pRequest->SetOpenFlags (dwFlags);
  1356. }
  1357. error = ERROR_SUCCESS;
  1358. }
  1359. break;
  1360. case WINHTTP_OPTION_ENABLE_FEATURE:
  1361. if (handleType != TypeHttpRequestHandle)
  1362. {
  1363. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1364. }
  1365. else if (dwBufferLength < sizeof(DWORD))
  1366. {
  1367. error = ERROR_INVALID_PARAMETER;
  1368. }
  1369. else
  1370. {
  1371. HTTP_REQUEST_HANDLE_OBJECT *pRequest =
  1372. (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1373. DWORD dwDisable = *((LPDWORD) lpBuffer);
  1374. pRequest->SetEnableFlags(*((LPDWORD) lpBuffer));
  1375. error = ERROR_SUCCESS;
  1376. }
  1377. break;
  1378. case WINHTTP_OPTION_CODEPAGE:
  1379. if ((hInternet == NULL) || (handleType == TypeHttpRequestHandle))
  1380. {
  1381. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1382. }
  1383. else
  1384. {
  1385. if (dwBufferLength == sizeof(DWORD))
  1386. {
  1387. ((INTERNET_HANDLE_BASE *)hInternet)->SetCodePage(*(LPDWORD)lpBuffer);
  1388. }
  1389. else
  1390. {
  1391. error = ERROR_INSUFFICIENT_BUFFER;
  1392. }
  1393. }
  1394. break;
  1395. case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
  1396. case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
  1397. if (handleType == TypeInternetHandle)
  1398. {
  1399. if (dwBufferLength == sizeof(DWORD))
  1400. {
  1401. ((INTERNET_HANDLE_OBJECT *)hInternet)->SetMaxConnectionsPerServer(dwOption, *(DWORD *)lpBuffer);
  1402. }
  1403. else
  1404. error = ERROR_INSUFFICIENT_BUFFER;
  1405. }
  1406. else
  1407. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1408. break;
  1409. case WINHTTP_OPTION_PER_CONNECTION_OPTION:
  1410. {
  1411. if (handleType != TypeInternetHandle) {
  1412. hInternet = NULL;
  1413. }
  1414. error = SetPerConnOptions(hInternet,
  1415. FALSE,
  1416. (LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
  1417. break;
  1418. }
  1419. case WINHTTP_OPTION_AUTOLOGON_POLICY:
  1420. if (handleType != TypeHttpRequestHandle)
  1421. {
  1422. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1423. }
  1424. else if (dwBufferLength < sizeof(DWORD))
  1425. {
  1426. error = ERROR_INSUFFICIENT_BUFFER;
  1427. }
  1428. else
  1429. {
  1430. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  1431. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1432. lphHttpRqst->SetSecurityLevel(*(LPDWORD)lpBuffer);
  1433. error = ERROR_SUCCESS;
  1434. }
  1435. break;
  1436. case WINHTTP_OPTION_WORKER_THREAD_COUNT:
  1437. if (dwBufferLength < sizeof(DWORD))
  1438. {
  1439. error = ERROR_INSUFFICIENT_BUFFER;
  1440. }
  1441. else
  1442. {
  1443. if (!g_cNumIOCPThreads)
  1444. {
  1445. g_cNumIOCPThreads = *(LPDWORD)lpBuffer;
  1446. error = ERROR_SUCCESS;
  1447. }
  1448. else
  1449. {
  1450. error = ERROR_WINHTTP_OPTION_NOT_SETTABLE;
  1451. }
  1452. }
  1453. break;
  1454. #if INET_DEBUG
  1455. case WINHTTP_OPTION_SET_DEBUG_INFO:
  1456. error = InternetSetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
  1457. dwBufferLength
  1458. );
  1459. break;
  1460. #endif // INET_DEBUG
  1461. default:
  1462. //
  1463. // this option is not recognized
  1464. //
  1465. error = ERROR_WINHTTP_INVALID_OPTION;
  1466. }
  1467. quit:
  1468. if (hObjectMapped != NULL) {
  1469. DereferenceObject((LPVOID)hObjectMapped);
  1470. }
  1471. done:
  1472. if (error != ERROR_SUCCESS) {
  1473. DEBUG_ERROR(API, error);
  1474. SetLastError(error);
  1475. success = FALSE;
  1476. }
  1477. DEBUG_LEAVE_API(success);
  1478. return success;
  1479. }
  1480. #define CHECK_MODIFY_TIMEOUT(nTimeout) \
  1481. { \
  1482. if (nTimeout <= 0) \
  1483. { \
  1484. if (nTimeout == 0) \
  1485. { \
  1486. nTimeout = (int)INFINITE; \
  1487. } \
  1488. else if (nTimeout < -1) \
  1489. { \
  1490. dwError = ERROR_INVALID_PARAMETER; \
  1491. goto quit; \
  1492. } \
  1493. } \
  1494. }
  1495. INTERNETAPI
  1496. BOOL
  1497. WINAPI
  1498. WinHttpSetTimeouts(
  1499. IN HINTERNET hInternet, // Session/Request handle.
  1500. IN int nResolveTimeout,
  1501. IN int nConnectTimeout,
  1502. IN int nSendTimeout,
  1503. IN int nReceiveTimeout
  1504. )
  1505. {
  1506. DEBUG_ENTER_API((DBG_API,
  1507. Bool,
  1508. "WinHttpSetTimeouts",
  1509. "%#x, %d, %d, %d, %d",
  1510. hInternet,
  1511. nResolveTimeout,
  1512. nConnectTimeout,
  1513. nSendTimeout,
  1514. nReceiveTimeout
  1515. ));
  1516. DWORD dwError = ERROR_SUCCESS;
  1517. BOOL bRetval = FALSE;
  1518. HINTERNET_HANDLE_TYPE handleType;
  1519. HINTERNET hObjectMapped = NULL;
  1520. if (!hInternet)
  1521. {
  1522. dwError = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1523. goto quit;
  1524. }
  1525. CHECK_MODIFY_TIMEOUT(nResolveTimeout);
  1526. CHECK_MODIFY_TIMEOUT(nConnectTimeout);
  1527. CHECK_MODIFY_TIMEOUT(nSendTimeout);
  1528. CHECK_MODIFY_TIMEOUT(nReceiveTimeout);
  1529. dwError = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
  1530. if (dwError != ERROR_SUCCESS)
  1531. {
  1532. goto quit;
  1533. }
  1534. dwError = RGetHandleType(hObjectMapped, &handleType);
  1535. if (dwError != ERROR_SUCCESS)
  1536. {
  1537. goto quit;
  1538. }
  1539. switch(handleType)
  1540. {
  1541. case TypeInternetHandle:
  1542. //only error possible is in allocing memory for OPTIONAL_PARAMS struct
  1543. bRetval = ((INTERNET_HANDLE_OBJECT*)hObjectMapped)->SetTimeouts(
  1544. nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
  1545. if (!bRetval)
  1546. {
  1547. dwError = ERROR_NOT_ENOUGH_MEMORY;
  1548. goto quit;
  1549. }
  1550. break;
  1551. case TypeHttpRequestHandle:
  1552. // no errors possible here
  1553. bRetval = ((HTTP_REQUEST_HANDLE_OBJECT*)hObjectMapped)->SetTimeouts(
  1554. nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
  1555. INET_ASSERT(bRetval);
  1556. break;
  1557. default:
  1558. // any other handle type cannot have timeouts set for it
  1559. dwError = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  1560. break;
  1561. }
  1562. quit:
  1563. if (hObjectMapped)
  1564. {
  1565. DereferenceObject((LPVOID)hObjectMapped);
  1566. }
  1567. if (dwError != ERROR_SUCCESS)
  1568. {
  1569. ::SetLastError(dwError);
  1570. INET_ASSERT(!bRetval);
  1571. }
  1572. DEBUG_LEAVE_API(bRetval);
  1573. return bRetval;
  1574. }
  1575. INTERNETAPI
  1576. BOOL
  1577. WINAPI
  1578. WinHttpSetOption(
  1579. IN HINTERNET hInternet OPTIONAL,
  1580. IN DWORD dwOption,
  1581. IN LPVOID lpBuffer,
  1582. IN DWORD dwBufferLength
  1583. )
  1584. /*++
  1585. Routine Description:
  1586. description-of-function.
  1587. Arguments:
  1588. hInternet -
  1589. dwOption -
  1590. lpBuffer -
  1591. dwBufferLength -
  1592. Return Value:
  1593. BOOL
  1594. --*/
  1595. {
  1596. DEBUG_ENTER_API((DBG_API,
  1597. Bool,
  1598. "WinHttpSetOption",
  1599. "%#x, %s (%d), %#x [%#x], %d",
  1600. hInternet,
  1601. InternetMapOption(dwOption),
  1602. dwOption,
  1603. lpBuffer,
  1604. lpBuffer
  1605. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  1606. ? *(LPDWORD)lpBuffer
  1607. : 0)
  1608. : 0,
  1609. dwBufferLength
  1610. ));
  1611. DWORD dwErr = ERROR_SUCCESS;
  1612. MEMORYPACKET mpBuffer;
  1613. BOOL fResult = FALSE;
  1614. //
  1615. // validate parameters
  1616. //
  1617. if ((dwBufferLength == 0) || IsBadReadPtr(lpBuffer, dwBufferLength))
  1618. {
  1619. switch (dwOption)
  1620. {
  1621. //
  1622. // these options don't require a buffer - don't fail request because
  1623. // no buffer supplied
  1624. //
  1625. case WINHTTP_OPTION_DIGEST_AUTH_UNLOAD:
  1626. if (dwBufferLength == 0)
  1627. break;
  1628. break;
  1629. default:
  1630. dwErr = ERROR_INVALID_PARAMETER;
  1631. goto cleanup;
  1632. }
  1633. }
  1634. switch (dwOption)
  1635. {
  1636. case WINHTTP_OPTION_USERNAME:
  1637. case WINHTTP_OPTION_PASSWORD:
  1638. case WINHTTP_OPTION_URL:
  1639. case WINHTTP_OPTION_USER_AGENT:
  1640. case WINHTTP_OPTION_PROXY_USERNAME:
  1641. case WINHTTP_OPTION_PROXY_PASSWORD:
  1642. ALLOC_MB((LPWSTR)lpBuffer, dwBufferLength, mpBuffer);
  1643. if (!mpBuffer.psStr)
  1644. {
  1645. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1646. goto cleanup;
  1647. }
  1648. UNICODE_TO_ANSI((LPWSTR)lpBuffer, mpBuffer);
  1649. fResult = InternetSetOptionA(hInternet,
  1650. dwOption,
  1651. mpBuffer.psStr,
  1652. mpBuffer.dwSize
  1653. );
  1654. break;
  1655. case WINHTTP_OPTION_PER_CONNECTION_OPTION:
  1656. {
  1657. if (!lpBuffer)
  1658. {
  1659. dwErr = ERROR_INVALID_PARAMETER;
  1660. goto cleanup;
  1661. }
  1662. INTERNET_PER_CONN_OPTION_LISTA listA;
  1663. LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
  1664. CHAR szEntryA[RAS_MaxEntryName + 1];
  1665. listA.pszConnection = szEntryA;
  1666. InitIPCOList(plistW, &listA);
  1667. listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
  1668. for (DWORD i=0; i<listA.dwOptionCount; i++)
  1669. {
  1670. listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
  1671. switch (listA.pOptions[i].dwOption)
  1672. {
  1673. case INTERNET_PER_CONN_FLAGS:
  1674. case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
  1675. case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
  1676. listA.pOptions[i].Value.dwValue = plistW->pOptions[i].Value.dwValue;
  1677. break;
  1678. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
  1679. listA.pOptions[i].Value.ftValue = plistW->pOptions[i].Value.ftValue;
  1680. break;
  1681. case INTERNET_PER_CONN_PROXY_SERVER:
  1682. case INTERNET_PER_CONN_PROXY_BYPASS:
  1683. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  1684. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  1685. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  1686. if (plistW->pOptions[i].Value.pszValue && *plistW->pOptions[i].Value.pszValue)
  1687. {
  1688. // ** WARNING ** NO UTF8 ENCODING HERE
  1689. DWORD cb = WideCharToMultiByte(CP_ACP,
  1690. 0,
  1691. plistW->pOptions[i].Value.pszValue,
  1692. -1,
  1693. 0,
  1694. 0,
  1695. NULL,
  1696. NULL);
  1697. listA.pOptions[i].Value.pszValue = (PSTR)_alloca(cb);
  1698. WideCharToMultiByte(CP_ACP,
  1699. 0,
  1700. plistW->pOptions[i].Value.pszValue,
  1701. -1,
  1702. listA.pOptions[i].Value.pszValue,
  1703. cb,
  1704. NULL,
  1705. NULL);
  1706. }
  1707. else
  1708. {
  1709. listA.pOptions[i].Value.pszValue = NULL;
  1710. }
  1711. break;
  1712. default:
  1713. dwErr = ERROR_INVALID_PARAMETER;
  1714. goto cleanup;
  1715. break;
  1716. }
  1717. }
  1718. fResult = InternetSetOptionA(hInternet,
  1719. dwOption,
  1720. (PVOID)&listA,
  1721. dwBufferLength);
  1722. plistW->dwOptionError = listA.dwOptionError;
  1723. }
  1724. break;
  1725. case WINHTTP_OPTION_PROXY:
  1726. {
  1727. WINHTTP_PROXY_INFOW * pInfo = (WINHTTP_PROXY_INFOW *) lpBuffer;
  1728. WINHTTP_PROXY_INFOA InfoA;
  1729. if (IsBadReadPtr(pInfo, sizeof(WINHTTP_PROXY_INFOW)) || (dwBufferLength < sizeof(WINHTTP_PROXY_INFOW)))
  1730. {
  1731. dwErr = ERROR_INVALID_PARAMETER;
  1732. break;
  1733. }
  1734. InfoA.dwAccessType = pInfo->dwAccessType;
  1735. dwErr = WideCharToAscii(pInfo->lpszProxy, &InfoA.lpszProxy);
  1736. if (dwErr == ERROR_SUCCESS)
  1737. {
  1738. dwErr = WideCharToAscii(pInfo->lpszProxyBypass, &InfoA.lpszProxyBypass);
  1739. if (dwErr == ERROR_SUCCESS)
  1740. {
  1741. fResult = InternetSetOptionA(hInternet, WINHTTP_OPTION_PROXY, &InfoA, sizeof(InfoA));
  1742. if (InfoA.lpszProxyBypass)
  1743. {
  1744. delete [] InfoA.lpszProxyBypass;
  1745. }
  1746. }
  1747. if (InfoA.lpszProxy)
  1748. {
  1749. delete [] InfoA.lpszProxy;
  1750. }
  1751. }
  1752. }
  1753. break;
  1754. default:
  1755. fResult = InternetSetOptionA(hInternet,
  1756. dwOption,
  1757. lpBuffer,
  1758. dwBufferLength
  1759. );
  1760. }
  1761. cleanup:
  1762. if (dwErr!=ERROR_SUCCESS)
  1763. {
  1764. SetLastError(dwErr);
  1765. DEBUG_ERROR(INET, dwErr);
  1766. }
  1767. DEBUG_LEAVE_API(fResult);
  1768. return fResult;
  1769. }
  1770. PRIVATE
  1771. BOOL
  1772. FValidCacheHandleType(
  1773. HINTERNET_HANDLE_TYPE hType
  1774. )
  1775. {
  1776. return ((hType != TypeInternetHandle) &&
  1777. (hType != TypeHttpConnectHandle));
  1778. }
  1779. #ifdef ENABLE_DEBUG
  1780. #define CASE_OF(constant) case constant: return # constant
  1781. LPSTR
  1782. InternetMapOption(
  1783. IN DWORD Option
  1784. )
  1785. /*++
  1786. Routine Description:
  1787. Convert WINHTTP_OPTION_ value to symbolic name
  1788. Arguments:
  1789. Option - to map
  1790. Return Value:
  1791. LPSTR - pointer to symbolic name, or "?" if unknown
  1792. --*/
  1793. {
  1794. switch (Option) {
  1795. CASE_OF(WINHTTP_OPTION_CALLBACK);
  1796. CASE_OF(WINHTTP_OPTION_RESOLVE_TIMEOUT);
  1797. CASE_OF(WINHTTP_OPTION_CONNECT_TIMEOUT);
  1798. CASE_OF(WINHTTP_OPTION_CONNECT_RETRIES);
  1799. CASE_OF(WINHTTP_OPTION_SEND_TIMEOUT);
  1800. CASE_OF(WINHTTP_OPTION_RECEIVE_TIMEOUT);
  1801. CASE_OF(WINHTTP_OPTION_HANDLE_TYPE);
  1802. CASE_OF(WINHTTP_OPTION_READ_BUFFER_SIZE);
  1803. CASE_OF(WINHTTP_OPTION_WRITE_BUFFER_SIZE);
  1804. CASE_OF(WINHTTP_OPTION_PARENT_HANDLE);
  1805. CASE_OF(WINHTTP_OPTION_EXTENDED_ERROR);
  1806. CASE_OF(WINHTTP_OPTION_USERNAME);
  1807. CASE_OF(WINHTTP_OPTION_PASSWORD);
  1808. CASE_OF(WINHTTP_OPTION_SECURITY_FLAGS);
  1809. CASE_OF(WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT);
  1810. CASE_OF(WINHTTP_OPTION_URL);
  1811. CASE_OF(WINHTTP_OPTION_SECURITY_KEY_BITNESS);
  1812. CASE_OF(WINHTTP_OPTION_PROXY);
  1813. CASE_OF(WINHTTP_OPTION_VERSION);
  1814. CASE_OF(WINHTTP_OPTION_USER_AGENT);
  1815. CASE_OF(WINHTTP_OPTION_PROXY_USERNAME);
  1816. CASE_OF(WINHTTP_OPTION_PROXY_PASSWORD);
  1817. CASE_OF(WINHTTP_OPTION_CONTEXT_VALUE);
  1818. CASE_OF(WINHTTP_OPTION_CLIENT_CERT_CONTEXT);
  1819. CASE_OF(WINHTTP_OPTION_REQUEST_PRIORITY);
  1820. CASE_OF(WINHTTP_OPTION_HTTP_VERSION);
  1821. CASE_OF(WINHTTP_OPTION_SECURITY_CONNECTION_INFO);
  1822. CASE_OF(WINHTTP_OPTION_DIAGNOSTIC_SOCKET_INFO);
  1823. CASE_OF(WINHTTP_OPTION_SERVER_CERT_CONTEXT);
  1824. }
  1825. return "?";
  1826. }
  1827. #endif // ENABLE_DEBUG