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.

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