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.

3215 lines
99 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. InternetSetOptionExA
  11. InternetQueryOptionW
  12. InternetSetOptionW
  13. InternetSetOptionExW
  14. (FValidCacheHandleType)
  15. Author:
  16. Richard L Firth (rfirth) 02-Mar-1995
  17. Environment:
  18. Win32 user-mode DLL
  19. Revision History:
  20. 02-Mar-1995 rfirth
  21. Created
  22. 07-Mar-1995 madana
  23. 07-Jul-1998 Forked by akabir
  24. --*/
  25. #include <wininetp.h>
  26. #include <perfdiag.hxx>
  27. #include "inetapiu.h"
  28. #include "autodial.h"
  29. #include "msident.h"
  30. #include "secinit.h"
  31. extern HANDLE g_hDialEvent;
  32. //
  33. // private macros
  34. //
  35. //
  36. // IS_PER_THREAD_OPTION - options applicable to the thread (HINTERNET is NULL).
  37. // Subset of IS_VALID_OPTION()
  38. //
  39. //#define IS_PER_THREAD_OPTION(option) \
  40. // (( ((option) == INTERNET_OPTION_SERVER_ERROR_CALLBACK) \
  41. // || ((option) == INTERNET_OPTION_ASYNC_ID) \
  42. // || ((option) == INTERNET_OPTION_EXTENDED_ERROR) \
  43. // ) ? TRUE : FALSE)
  44. #define IS_PER_THREAD_OPTION(option) \
  45. (( ((option) == INTERNET_OPTION_ASYNC_ID) \
  46. || ((option) == INTERNET_OPTION_EXTENDED_ERROR) \
  47. || ((option) == INTERNET_OPTION_PER_CONNECTION_OPTION) \
  48. ) ? TRUE : FALSE)
  49. //
  50. // IS_PER_PROCESS_OPTION - options applicable to the process (HINTERNET is NULL).
  51. // Subset of IS_VALID_OPTION()
  52. //
  53. #define IS_PER_PROCESS_OPTION(option) \
  54. (( ((option) == INTERNET_OPTION_GET_DEBUG_INFO) \
  55. || ((option) == INTERNET_OPTION_SET_DEBUG_INFO) \
  56. || ((option) == INTERNET_OPTION_GET_HANDLE_COUNT) \
  57. || ((option) == INTERNET_OPTION_CONNECT_TIMEOUT) \
  58. || ((option) == INTERNET_OPTION_CONNECT_RETRIES) \
  59. || ((option) == INTERNET_OPTION_CONNECT_BACKOFF) \
  60. || ((option) == INTERNET_OPTION_SEND_TIMEOUT) \
  61. || ((option) == INTERNET_OPTION_RECEIVE_TIMEOUT) \
  62. || ((option) == INTERNET_OPTION_DATA_SEND_TIMEOUT) \
  63. || ((option) == INTERNET_OPTION_DATA_RECEIVE_TIMEOUT) \
  64. || ((option) == INTERNET_OPTION_FROM_CACHE_TIMEOUT) \
  65. || ((option) == INTERNET_OPTION_REFRESH) \
  66. || ((option) == INTERNET_OPTION_PROXY) \
  67. || ((option) == INTERNET_OPTION_SETTINGS_CHANGED) \
  68. || ((option) == INTERNET_OPTION_PROXY_SETTINGS_CHANGED) \
  69. || ((option) == INTERNET_OPTION_VERSION) \
  70. || ((option) == INTERNET_OPTION_END_BROWSER_SESSION) \
  71. || ((option) == INTERNET_OPTION_RESET_URLCACHE_SESSION) \
  72. || ((option) == INTERNET_OPTION_OFFLINE_TIMEOUT) \
  73. || ((option) == INTERNET_OPTION_LINE_STATE) \
  74. || ((option) == INTERNET_OPTION_IDLE_STATE) \
  75. || ((option) == INTERNET_OPTION_OFFLINE_SEMANTICS) \
  76. || ((option) == INTERNET_OPTION_HTTP_VERSION) \
  77. || ((option) == INTERNET_OPTION_BYPASS_EDITED_ENTRY) \
  78. || ((option) == INTERNET_OPTION_MAX_CONNS_PER_SERVER) \
  79. || ((option) == INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER) \
  80. || ((option) == INTERNET_OPTION_DIGEST_AUTH_UNLOAD) \
  81. || ((option) == INTERNET_OPTION_IDENTITY) \
  82. || ((option) == INTERNET_OPTION_REMOVE_IDENTITY) \
  83. || ((option) == INTERNET_OPTION_ALTER_IDENTITY) \
  84. || ((option) == INTERNET_OPTION_SUPPRESS_BEHAVIOR) \
  85. || ((option) == INTERNET_OPTION_PER_CONNECTION_OPTION) \
  86. || ((option) == INTERNET_OPTION_AUTODIAL_CONNECTION) \
  87. || ((option) == INTERNET_OPTION_AUTODIAL_MODE) \
  88. || ((option) == INTERNET_OPTION_USERNAME) \
  89. || ((option) == INTERNET_OPTION_PASSWORD) \
  90. || ((option) == INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS) \
  91. || ((option) == INTERNET_OPTION_ACTIVATE_WORKER_THREADS) \
  92. || ((option) == INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS) \
  93. ) ? TRUE : FALSE)
  94. //
  95. // IS_DEBUG_OPTION - the set of debug-specific options
  96. //
  97. #define IS_DEBUG_OPTION(option) \
  98. (( ((option) >= INTERNET_FIRST_DEBUG_OPTION) \
  99. && ((option) <= INTERNET_LAST_DEBUG_OPTION) \
  100. ) ? TRUE : FALSE)
  101. //
  102. // IS_VALID_OPTION - the set of known option values, for a HINTERNET, thread, or
  103. // process. In the retail version, debug options are invalid
  104. //
  105. #if INET_DEBUG
  106. #define IS_VALID_OPTION(option) \
  107. (((((option) >= INTERNET_FIRST_OPTION) \
  108. && ((option) <= INTERNET_LAST_OPTION_INTERNAL)) \
  109. || IS_DEBUG_OPTION(option) \
  110. ) ? TRUE : FALSE)
  111. #else
  112. #define IS_VALID_OPTION(option) \
  113. (((((option) >= INTERNET_FIRST_OPTION) \
  114. && ((option) <= INTERNET_LAST_OPTION_INTERNAL)) \
  115. ) ? TRUE : FALSE)
  116. #endif // INET_DEBUG
  117. //
  118. // IS_CONNECT_HANDLE_TYPE - TRUE if handle type contains INTERNET_CONNECT_HANDLE_OBJECT
  119. //
  120. #define IS_CONNECT_HANDLE_TYPE(handleType) \
  121. ((handleType == TypeHttpRequestHandle) \
  122. || (handleType == TypeHttpConnectHandle) \
  123. || (handleType == TypeFtpConnectHandle) \
  124. || (handleType == TypeFtpFileHandle) \
  125. || (handleType == TypeFtpFindHandle) \
  126. || (handleType == TypeFtpFileHandleHtml) \
  127. || (handleType == TypeFtpFindHandleHtml) \
  128. || (handleType == TypeGopherConnectHandle) \
  129. || (handleType == TypeGopherFileHandle) \
  130. || (handleType == TypeGopherFindHandle) \
  131. || (handleType == TypeGopherFileHandleHtml) \
  132. || (handleType == TypeGopherFindHandleHtml))
  133. //
  134. // private prototypes
  135. //
  136. PRIVATE
  137. BOOL
  138. FValidCacheHandleType(
  139. HINTERNET_HANDLE_TYPE hType
  140. );
  141. PRIVATE
  142. VOID
  143. InitIPCOList(LPINTERNET_PER_CONN_OPTION_LISTW plistW, LPINTERNET_PER_CONN_OPTION_LISTA plistA)
  144. {
  145. plistA->dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA);
  146. plistA->dwOptionCount = plistW->dwOptionCount;
  147. if (plistW->pszConnection && *plistW->pszConnection)
  148. {
  149. SHUnicodeToAnsi(plistW->pszConnection, plistA->pszConnection, RAS_MaxEntryName + 1);
  150. }
  151. else
  152. {
  153. plistA->pszConnection = NULL;
  154. }
  155. }
  156. //
  157. // functions
  158. //
  159. INTERNETAPI_(BOOL) InternetQueryOptionA(
  160. IN HINTERNET hInternet OPTIONAL,
  161. IN DWORD dwOption,
  162. OUT LPVOID lpBuffer OPTIONAL,
  163. IN OUT LPDWORD lpdwBufferLength
  164. )
  165. /*++
  166. Routine Description:
  167. Returns information about various handle-specific variables
  168. Arguments:
  169. hInternet - handle of object for which information will be
  170. returned
  171. dwOption - the handle-specific INTERNET_OPTION to query
  172. lpBuffer - pointer to a buffer which will receive results
  173. lpdwBufferLength - IN: number of bytes available in lpBuffer
  174. OUT: number of bytes returned in lpBuffer
  175. Return Value:
  176. BOOL
  177. Success - TRUE
  178. Failure - FALSE. Call GetLastError() for more info:
  179. ERROR_INVALID_HANDLE
  180. hInternet does not identify a valid Internet handle
  181. object
  182. ERROR_INTERNET_INTERNAL_ERROR
  183. Shouldn't see this?
  184. ERROR_INVALID_PARAMETER
  185. One of the parameters was bad
  186. ERROR_INSUFFICIENT_BUFFER
  187. lpBuffer is not large enough to hold the requested
  188. information; *lpdwBufferLength contains the number of
  189. bytes needed
  190. ERROR_INTERNET_INCORRECT_HANDLE_TYPE
  191. The handle is the wrong type for the requested option
  192. ERROR_INTERNET_INVALID_OPTION
  193. The option is unrecognized
  194. --*/
  195. {
  196. DEBUG_ENTER_API((DBG_API,
  197. Bool,
  198. "InternetQueryOptionA",
  199. "%#x, %s (%d), %#x, %#x [%d]",
  200. hInternet,
  201. InternetMapOption(dwOption),
  202. dwOption,
  203. lpBuffer,
  204. lpdwBufferLength,
  205. lpdwBufferLength
  206. ? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
  207. ? *lpdwBufferLength
  208. : 0)
  209. : 0
  210. ));
  211. DWORD error;
  212. BOOL success;
  213. HINTERNET_HANDLE_TYPE handleType;
  214. LPINTERNET_THREAD_INFO lpThreadInfo;
  215. DWORD requiredSize = 0;
  216. LPVOID lpSource;
  217. DWORD dwValue;
  218. DWORD_PTR dwPtrValue;
  219. HANDLE hValue;
  220. HINTERNET hObjectMapped = NULL;
  221. INTERNET_CONNECT_HANDLE_OBJECT * lphRequest;
  222. BOOL isString = FALSE;
  223. BOOL freeString = FALSE;
  224. INTERNET_DIAGNOSTIC_SOCKET_INFO socketInfo;
  225. if (!GlobalDataInitialized) {
  226. error = GlobalDataInitialize();
  227. if (error != ERROR_SUCCESS) {
  228. goto done;
  229. }
  230. }
  231. lpThreadInfo = InternetGetThreadInfo();
  232. if (lpThreadInfo == NULL) {
  233. error = ERROR_INTERNET_INTERNAL_ERROR;
  234. goto done;
  235. }
  236. //
  237. // validate parameters
  238. //
  239. if (!ARGUMENT_PRESENT(lpdwBufferLength)) {
  240. error = ERROR_INVALID_PARAMETER;
  241. goto done;
  242. }
  243. if (!ARGUMENT_PRESENT(lpBuffer)) {
  244. *lpdwBufferLength = 0;
  245. }
  246. //
  247. // validate the handle and get its type
  248. //
  249. HINTERNET hOriginal;
  250. hOriginal = hInternet;
  251. if (ARGUMENT_PRESENT(hInternet)) {
  252. //
  253. // map the handle
  254. //
  255. error = MapHandleToAddress(hInternet, (LPVOID *)&hInternet, FALSE);
  256. if (error == ERROR_SUCCESS) {
  257. hObjectMapped = hInternet;
  258. lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
  259. error = RGetHandleType(hInternet, &handleType);
  260. }
  261. } else if (IS_PER_THREAD_OPTION(dwOption)) {
  262. //
  263. // this option updates the per-thread information block, so this is a
  264. // good point at which to get it
  265. //
  266. if (lpThreadInfo != NULL) {
  267. error = ERROR_SUCCESS;
  268. } else {
  269. DEBUG_PRINT(INET,
  270. ERROR,
  271. ("InternetGetThreadInfo() returns NULL\n"
  272. ));
  273. //
  274. // we never expect this - ERROR_INTERNET_SPANISH_INQUISITION
  275. //
  276. INET_ASSERT(FALSE);
  277. error = ERROR_INTERNET_INTERNAL_ERROR;
  278. }
  279. } else if (IS_PER_PROCESS_OPTION(dwOption)) {
  280. error = ERROR_SUCCESS;
  281. } else {
  282. //
  283. // catch any invalid options for the NULL handle. If the option is valid
  284. // then it is incorrect for this handle type, otherwise its an invalid
  285. // option, period
  286. //
  287. error = IS_VALID_OPTION(dwOption)
  288. ? ERROR_INTERNET_INCORRECT_HANDLE_TYPE
  289. : ERROR_INTERNET_INVALID_OPTION
  290. ;
  291. }
  292. //
  293. // if the option and handle combination is valid then query the option value
  294. //
  295. if (error != ERROR_SUCCESS) {
  296. goto quit;
  297. }
  298. switch (dwOption) {
  299. case INTERNET_OPTION_CALLBACK:
  300. requiredSize = sizeof(INTERNET_STATUS_CALLBACK);
  301. if (hInternet != NULL) {
  302. error = RGetStatusCallback(hInternet,
  303. (LPINTERNET_STATUS_CALLBACK)&dwValue
  304. );
  305. lpSource = (LPVOID)&dwValue;
  306. } else {
  307. error = ERROR_INVALID_HANDLE;
  308. }
  309. break;
  310. case INTERNET_OPTION_CONNECT_TIMEOUT:
  311. case INTERNET_OPTION_CONNECT_RETRIES:
  312. case INTERNET_OPTION_CONNECT_BACKOFF:
  313. case INTERNET_OPTION_SEND_TIMEOUT:
  314. case INTERNET_OPTION_RECEIVE_TIMEOUT:
  315. case INTERNET_OPTION_DATA_SEND_TIMEOUT:
  316. case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
  317. case INTERNET_OPTION_FROM_CACHE_TIMEOUT:
  318. requiredSize = sizeof(DWORD);
  319. //
  320. // remember hInternet in the INTERNET_THREAD_INFO then call
  321. // GetTimeoutValue(). If hInternet refers to a valid Internet
  322. // object handle, then the relevant timeout value will be
  323. // returned from that, else we will return the global value
  324. // corresponding to the requested option
  325. //
  326. InternetSetObjectHandle(hOriginal, hInternet);
  327. dwValue = GetTimeoutValue(dwOption);
  328. lpSource = (LPVOID)&dwValue;
  329. break;
  330. case INTERNET_OPTION_HANDLE_TYPE:
  331. requiredSize = sizeof(dwValue);
  332. switch (handleType) {
  333. case TypeInternetHandle:
  334. dwValue = INTERNET_HANDLE_TYPE_INTERNET;
  335. break;
  336. case TypeFtpConnectHandle:
  337. dwValue = INTERNET_HANDLE_TYPE_CONNECT_FTP;
  338. break;
  339. case TypeFtpFindHandle:
  340. dwValue = INTERNET_HANDLE_TYPE_FTP_FIND;
  341. break;
  342. case TypeFtpFindHandleHtml:
  343. dwValue = INTERNET_HANDLE_TYPE_FTP_FIND_HTML;
  344. break;
  345. case TypeFtpFileHandle:
  346. dwValue = INTERNET_HANDLE_TYPE_FTP_FILE;
  347. break;
  348. case TypeFtpFileHandleHtml:
  349. dwValue = INTERNET_HANDLE_TYPE_FTP_FILE_HTML;
  350. break;
  351. case TypeGopherConnectHandle:
  352. dwValue = INTERNET_HANDLE_TYPE_CONNECT_GOPHER;
  353. break;
  354. case TypeGopherFindHandle:
  355. dwValue = INTERNET_HANDLE_TYPE_GOPHER_FIND;
  356. break;
  357. case TypeGopherFindHandleHtml:
  358. dwValue = INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML;
  359. break;
  360. case TypeGopherFileHandle:
  361. dwValue = INTERNET_HANDLE_TYPE_GOPHER_FILE;
  362. break;
  363. case TypeGopherFileHandleHtml:
  364. dwValue = INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML;
  365. break;
  366. case TypeHttpConnectHandle:
  367. dwValue = INTERNET_HANDLE_TYPE_CONNECT_HTTP;
  368. break;
  369. case TypeHttpRequestHandle:
  370. dwValue = INTERNET_HANDLE_TYPE_HTTP_REQUEST;
  371. break;
  372. case TypeFileRequestHandle:
  373. dwValue = INTERNET_HANDLE_TYPE_FILE_REQUEST;
  374. break;
  375. default:
  376. error = ERROR_INTERNET_INTERNAL_ERROR;
  377. break;
  378. }
  379. lpSource = (LPVOID)&dwValue;
  380. break;
  381. case INTERNET_OPTION_CONTEXT_VALUE:
  382. case INTERNET_OPTION_CONTEXT_VALUE_OLD: // see InternetSetOption
  383. requiredSize = sizeof(DWORD_PTR);
  384. error = RGetContext(hInternet, &dwPtrValue);
  385. lpSource = (LPVOID)&dwPtrValue;
  386. break;
  387. //case INTERNET_OPTION_NAME_RES_THREAD:
  388. // requiredSize = sizeof(BOOL);
  389. // lpSource = (LPVOID)&MultiThreadedNameResolution;
  390. // break;
  391. case INTERNET_OPTION_READ_BUFFER_SIZE:
  392. case INTERNET_OPTION_WRITE_BUFFER_SIZE:
  393. if (IS_CONNECT_HANDLE_TYPE(handleType)) {
  394. requiredSize = sizeof(DWORD);
  395. error = RGetBufferSize(hInternet, dwOption, &dwValue);
  396. lpSource = (LPVOID)&dwValue;
  397. } else {
  398. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  399. }
  400. break;
  401. //case INTERNET_OPTION_GATEWAY_NAME:
  402. // error = ERROR_CALL_NOT_IMPLEMENTED;
  403. // break;
  404. case INTERNET_OPTION_ASYNC_ID:
  405. error = ERROR_CALL_NOT_IMPLEMENTED;
  406. break;
  407. case INTERNET_OPTION_ASYNC_PRIORITY:
  408. error = ERROR_CALL_NOT_IMPLEMENTED;
  409. break;
  410. //case INTERNET_OPTION_ASYNC_REQUEST_COUNT:
  411. // requiredSize = sizeof(dwValue);
  412. // error = RGetAsyncRequestCount(hInternet, &dwValue);
  413. // lpSource = (LPVOID)&dwValue;
  414. // break;
  415. case INTERNET_OPTION_PARENT_HANDLE:
  416. hInternet = ((HANDLE_OBJECT *)hInternet)->GetParent();
  417. if (hInternet != NULL) {
  418. hInternet = ((HANDLE_OBJECT *)hInternet)->GetPseudoHandle();
  419. }
  420. requiredSize = sizeof(hInternet);
  421. lpSource = (LPVOID)&hInternet;
  422. break;
  423. case INTERNET_OPTION_KEEP_CONNECTION:
  424. if (handleType == TypeHttpConnectHandle) {
  425. requiredSize = sizeof(BOOL);
  426. //
  427. // we return TRUE or FALSE based on whether the connect
  428. // object believes the server supports Keep-Alive
  429. //
  430. //dwValue = RGetKeepAliveState(hInternet);
  431. lpSource = (LPVOID)&dwValue;
  432. } else {
  433. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  434. }
  435. break;
  436. case INTERNET_OPTION_REQUEST_FLAGS:
  437. requiredSize = sizeof(dwValue);
  438. if (FValidCacheHandleType(handleType)) {
  439. dwValue = 0;
  440. if (lphRequest->IsFromCache()) {
  441. dwValue |= INTERNET_REQFLAG_FROM_CACHE;
  442. if (lphRequest->IsNetFailed()) {
  443. dwValue |= INTERNET_REQFLAG_NET_TIMEOUT;
  444. }
  445. }
  446. if (lphRequest->IsViaProxy()) {
  447. dwValue |= INTERNET_REQFLAG_VIA_PROXY;
  448. }
  449. if (lphRequest->IsNoHeaders()) {
  450. dwValue |= INTERNET_REQFLAG_NO_HEADERS;
  451. }
  452. if (lphRequest->IsCacheWriteDisabled()) {
  453. dwValue |= INTERNET_REQFLAG_CACHE_WRITE_DISABLED;
  454. }
  455. lpSource = (LPVOID)&dwValue;
  456. } else {
  457. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  458. }
  459. break;
  460. case INTERNET_OPTION_EXTENDED_ERROR:
  461. requiredSize = sizeof(lpThreadInfo->dwMappedErrorCode);
  462. lpSource = (LPVOID)&lpThreadInfo->dwMappedErrorCode;
  463. break;
  464. case INTERNET_OPTION_OFFLINE_MODE:
  465. error = ERROR_CALL_NOT_IMPLEMENTED;
  466. break;
  467. case INTERNET_OPTION_CACHE_STREAM_HANDLE:
  468. requiredSize = sizeof(HANDLE);
  469. if (FValidCacheHandleType(handleType)) {
  470. error = lphRequest->GetCacheStream((LPBYTE)&hValue,
  471. sizeof(hValue)
  472. );
  473. lpSource = (LPVOID)&hValue;
  474. } else {
  475. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  476. }
  477. break;
  478. BOOL fUser, fProxy;
  479. case INTERNET_OPTION_USERNAME:
  480. fUser = IS_USER;
  481. fProxy = IS_SERVER;
  482. goto callGetUserOrPass;
  483. case INTERNET_OPTION_PASSWORD:
  484. fUser = IS_PASS;
  485. fProxy = IS_SERVER;
  486. goto callGetUserOrPass;
  487. case INTERNET_OPTION_PROXY_USERNAME:
  488. fUser = IS_USER;
  489. fProxy = IS_PROXY;
  490. goto callGetUserOrPass;
  491. case INTERNET_OPTION_PROXY_PASSWORD:
  492. fUser = IS_PASS;
  493. fProxy = IS_PROXY;
  494. goto callGetUserOrPass;
  495. callGetUserOrPass:
  496. if (hInternet && (handleType != TypeInternetHandle)
  497. && (handleType != TypeFileRequestHandle)) {
  498. lpSource = lphRequest->GetUserOrPass(fUser, fProxy);
  499. isString = TRUE;
  500. freeString = (lpSource != NULL && fUser == IS_PASS); // password string must be freed
  501. error = ERROR_SUCCESS;
  502. } else {
  503. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  504. }
  505. break;
  506. case INTERNET_OPTION_ASYNC:
  507. error = ERROR_CALL_NOT_IMPLEMENTED;
  508. break;
  509. case INTERNET_OPTION_IDENTITY:
  510. lpSource = (LPVOID)&GlobalIdentityGuid;
  511. requiredSize = sizeof(GlobalIdentityGuid);
  512. break;
  513. case INTERNET_OPTION_SECURITY_FLAGS:
  514. if (handleType != TypeHttpRequestHandle)
  515. {
  516. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  517. }
  518. else
  519. {
  520. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  521. requiredSize = sizeof(dwValue);
  522. dwValue = 0;
  523. lpSource = (LPVOID)&dwValue;
  524. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  525. dwValue = lphHttpRqst->GetSecureFlags();
  526. DEBUG_PRINT(INET,
  527. INFO,
  528. ("SECURITY_FLAGS: %X\n",
  529. dwValue
  530. ));
  531. error = ERROR_SUCCESS;
  532. }
  533. break;
  534. case INTERNET_OPTION_DATAFILE_NAME:
  535. if ((handleType == TypeHttpRequestHandle)
  536. || (handleType == TypeFtpFindHandle)
  537. || (handleType == TypeFtpFindHandleHtml)
  538. || (handleType == TypeFtpFileHandle)
  539. || (handleType == TypeFtpFileHandleHtml)
  540. || (handleType == TypeGopherFindHandle)
  541. || (handleType == TypeGopherFindHandleHtml)
  542. || (handleType == TypeGopherFileHandle)
  543. || (handleType == TypeGopherFileHandleHtml)
  544. || (handleType == TypeFileRequestHandle )) {
  545. //
  546. // DATAFILE_NAME is slightly different from the other string
  547. // options: if the name is not present then we return an error
  548. // to the effect that we couldn't find it. The others just
  549. // return an empty string
  550. //
  551. if ( handleType != TypeFileRequestHandle ) {
  552. lpSource = lphRequest->GetDataFileName();
  553. }
  554. else {
  555. lpSource =
  556. ((INTERNET_FILE_HANDLE_OBJECT *)lphRequest)->GetDataFileName();
  557. }
  558. if (lpSource != NULL) {
  559. isString = TRUE;
  560. INET_ASSERT(error == ERROR_SUCCESS);
  561. } else {
  562. error = ERROR_INTERNET_ITEM_NOT_FOUND;
  563. }
  564. } else {
  565. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  566. }
  567. break;
  568. case INTERNET_OPTION_URL:
  569. //
  570. // return the URL associated with the request handle. This may be
  571. // different from the original URL due to redirections
  572. //
  573. if ((handleType == TypeHttpRequestHandle)
  574. || (handleType == TypeFtpFindHandle)
  575. || (handleType == TypeFtpFindHandleHtml)
  576. || (handleType == TypeFtpFileHandle)
  577. || (handleType == TypeFtpFileHandleHtml)
  578. || (handleType == TypeGopherFindHandle)
  579. || (handleType == TypeGopherFindHandleHtml)
  580. || (handleType == TypeGopherFileHandle)
  581. || (handleType == TypeGopherFileHandleHtml)) {
  582. //
  583. // only these handle types (retrieved object handles) can have
  584. // associated URLs
  585. //
  586. lpSource = lphRequest->GetURL();
  587. isString = TRUE;
  588. INET_ASSERT(error == ERROR_SUCCESS);
  589. } else {
  590. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  591. }
  592. break;
  593. case INTERNET_OPTION_SECURITY_CERTIFICATE:
  594. if (handleType != TypeHttpRequestHandle) {
  595. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  596. } else {
  597. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  598. INTERNET_SECURITY_INFO siInfo;
  599. INTERNET_CERTIFICATE_INFO ciInfo;
  600. DWORD dwciInfoSize = sizeof(INTERNET_CERTIFICATE_INFO);
  601. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  602. if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&siInfo))
  603. {
  604. error = ConvertSecurityInfoIntoCertInfoStruct(&siInfo, &ciInfo, &dwciInfoSize);
  605. if(siInfo.pCertificate)
  606. {
  607. CertFreeCertificateContext(siInfo.pCertificate);
  608. }
  609. if ( error == ERROR_SUCCESS )
  610. {
  611. LPTSTR szResult = NULL;
  612. DWORD cchNeedLen = 0;
  613. szResult = FormatCertInfo(
  614. &ciInfo
  615. );
  616. if (NULL == szResult)
  617. {
  618. error = ERROR_INTERNET_INVALID_OPERATION;
  619. goto secOptEnd;
  620. }
  621. cchNeedLen = lstrlen(szResult) + 1;
  622. if (*lpdwBufferLength < cchNeedLen)
  623. {
  624. error = ERROR_INSUFFICIENT_BUFFER;
  625. goto secOptEnd;
  626. }
  627. if (ARGUMENT_PRESENT(lpBuffer))
  628. {
  629. memcpy(
  630. lpBuffer,
  631. szResult,
  632. (cchNeedLen) * sizeof(TCHAR));
  633. cchNeedLen--;
  634. }
  635. secOptEnd:
  636. if (NULL != szResult) {
  637. FREE_MEMORY(szResult);
  638. }
  639. if (NULL != ciInfo.lpszSubjectInfo) {
  640. LocalFree(ciInfo.lpszSubjectInfo);
  641. }
  642. if (NULL != ciInfo.lpszIssuerInfo) {
  643. LocalFree(ciInfo.lpszIssuerInfo);
  644. }
  645. if (NULL != ciInfo.lpszSignatureAlgName) {
  646. LocalFree(ciInfo.lpszSignatureAlgName);
  647. }
  648. if (NULL != ciInfo.lpszEncryptionAlgName) {
  649. LocalFree(ciInfo.lpszEncryptionAlgName);
  650. }
  651. if (NULL != ciInfo.lpszProtocolName) {
  652. LocalFree(ciInfo.lpszProtocolName);
  653. }
  654. *lpdwBufferLength = cchNeedLen;
  655. requiredSize = *lpdwBufferLength;
  656. }
  657. goto quit;
  658. }
  659. else
  660. {
  661. error = ERROR_INTERNET_INVALID_OPERATION;
  662. }
  663. }
  664. break;
  665. case INTERNET_OPTION_SECURITY_CONNECTION_INFO:
  666. //
  667. // Caller is expected to pass in an INTERNET_SECURITY_CONNECTION_INFO structure.
  668. if (handleType != TypeHttpRequestHandle) {
  669. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  670. } else if (*lpdwBufferLength < (DWORD)sizeof(INTERNET_SECURITY_CONNECTION_INFO)) {
  671. requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
  672. *lpdwBufferLength = requiredSize;
  673. error = ERROR_INSUFFICIENT_BUFFER;
  674. } else {
  675. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  676. LPINTERNET_SECURITY_CONNECTION_INFO lpSecConnInfo;
  677. INTERNET_SECURITY_INFO ciInfo;
  678. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *)hInternet;
  679. lpSecConnInfo = (LPINTERNET_SECURITY_CONNECTION_INFO)lpBuffer;
  680. requiredSize = sizeof(INTERNET_SECURITY_CONNECTION_INFO);
  681. if ((error = lphHttpRqst->GetSecurityInfo(&ciInfo)) == ERROR_SUCCESS) {
  682. // Set up that data members in the structure passed in.
  683. lpSecConnInfo->fSecure = TRUE;
  684. lpSecConnInfo->dwProtocol = ciInfo.dwProtocol;
  685. lpSecConnInfo->aiCipher = ciInfo.aiCipher;
  686. lpSecConnInfo->dwCipherStrength = ciInfo.dwCipherStrength;
  687. lpSecConnInfo->aiHash = ciInfo.aiHash;
  688. lpSecConnInfo->dwHashStrength = ciInfo.dwHashStrength;
  689. lpSecConnInfo->aiExch = ciInfo.aiExch;
  690. lpSecConnInfo->dwExchStrength = ciInfo.dwExchStrength;
  691. if (ciInfo.pCertificate)
  692. {
  693. CertFreeCertificateContext(ciInfo.pCertificate);
  694. }
  695. } else if (error == ERROR_INTERNET_INTERNAL_ERROR) {
  696. // This implies we are not secure.
  697. error = ERROR_SUCCESS;
  698. lpSecConnInfo->fSecure = FALSE;
  699. }
  700. lpSecConnInfo->dwSize = requiredSize;
  701. *lpdwBufferLength = requiredSize;
  702. }
  703. goto quit;
  704. case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT:
  705. //
  706. // Allocates memory that caller is expected to free.
  707. //
  708. if (handleType != TypeHttpRequestHandle) {
  709. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  710. } else {
  711. LPTSTR szResult = NULL;
  712. DWORD cchNeedLen = 0;
  713. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  714. INTERNET_SECURITY_INFO cInfo;
  715. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  716. requiredSize = sizeof(INTERNET_CERTIFICATE_INFO);
  717. if (ERROR_SUCCESS == lphHttpRqst->GetSecurityInfo(&cInfo))
  718. {
  719. error = ConvertSecurityInfoIntoCertInfoStruct(&cInfo, (LPINTERNET_CERTIFICATE_INFO)lpBuffer, lpdwBufferLength);
  720. if(cInfo.pCertificate)
  721. {
  722. CertFreeCertificateContext(cInfo.pCertificate);
  723. }
  724. goto quit;
  725. }
  726. else
  727. {
  728. error = ERROR_INTERNET_INVALID_OPERATION;
  729. }
  730. }
  731. break;
  732. case INTERNET_OPTION_SECURITY_KEY_BITNESS:
  733. if (handleType != TypeHttpRequestHandle)
  734. {
  735. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  736. }
  737. else
  738. {
  739. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  740. INTERNET_SECURITY_INFO secInfo;
  741. requiredSize = sizeof(dwValue);
  742. dwValue = 0;
  743. lpSource = (LPVOID)&dwValue;
  744. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  745. if (ERROR_SUCCESS != lphHttpRqst->GetSecurityInfo(&secInfo)) {
  746. error = ERROR_INTERNET_INVALID_OPERATION;
  747. } else {
  748. dwValue = secInfo.dwCipherStrength;
  749. CertFreeCertificateContext(secInfo.pCertificate);
  750. INET_ASSERT (error == ERROR_SUCCESS);
  751. DEBUG_PRINT(INET,
  752. INFO,
  753. ("SECURITY_KEY_BITNESS: %X\n",
  754. dwValue
  755. ));
  756. }
  757. }
  758. break;
  759. case INTERNET_OPTION_PROXY:
  760. if (!ARGUMENT_PRESENT(hInternet)) {
  761. if (!GlobalProxyInfo.IsModifiedInProcess())
  762. {
  763. FixProxySettingsForCurrentConnection(
  764. FALSE
  765. );
  766. }
  767. error = GlobalProxyInfo.GetProxyStringInfo(lpBuffer, lpdwBufferLength);
  768. requiredSize = *lpdwBufferLength;
  769. goto quit;
  770. } else if (handleType == TypeInternetHandle) {
  771. //
  772. // GetProxyInfo() will return the data, or calculate the buffer
  773. // length required
  774. //
  775. error = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetProxyStringInfo(
  776. lpBuffer,
  777. lpdwBufferLength
  778. );
  779. requiredSize = *lpdwBufferLength;
  780. goto quit;
  781. } else {
  782. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  783. }
  784. break;
  785. case INTERNET_OPTION_VERSION:
  786. requiredSize = sizeof(InternetVersionInfo);
  787. lpSource = (LPVOID)&InternetVersionInfo;
  788. break;
  789. case INTERNET_OPTION_USER_AGENT:
  790. if (handleType == TypeInternetHandle) {
  791. lpSource = ((INTERNET_HANDLE_OBJECT *)hInternet)->GetUserAgent();
  792. isString = TRUE;
  793. } else {
  794. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  795. }
  796. break;
  797. case INTERNET_OPTION_LINE_STATE:
  798. if(InternetSettingsChanged())
  799. {
  800. ChangeGlobalSettings(); // refreshes GlobalDllState
  801. }
  802. requiredSize = sizeof(DWORD);
  803. lpSource = (LPVOID)&dwValue;
  804. dwValue = GlobalDllState
  805. & (INTERNET_LINE_STATE_MASK | INTERNET_STATE_OFFLINE_USER);
  806. break;
  807. case INTERNET_OPTION_IDLE_STATE:
  808. requiredSize = sizeof(DWORD);
  809. lpSource = (LPVOID)&dwValue;
  810. dwValue = GlobalDllState & INTERNET_STATE_IDLE;
  811. break;
  812. case INTERNET_OPTION_OFFLINE_SEMANTICS:
  813. requiredSize = sizeof(DWORD);
  814. dwValue = FALSE;
  815. lpSource = (LPVOID)&dwValue;
  816. break;
  817. case INTERNET_OPTION_SECONDARY_CACHE_KEY:
  818. if (handleType == TypeHttpRequestHandle) {
  819. lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
  820. lpSource = lphRequest->GetSecondaryCacheKey();
  821. isString = TRUE;
  822. } else {
  823. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  824. }
  825. break;
  826. case INTERNET_OPTION_CALLBACK_FILTER:
  827. error = ERROR_NOT_SUPPORTED;
  828. break;
  829. case INTERNET_OPTION_CONNECT_TIME:
  830. error = ERROR_NOT_SUPPORTED;
  831. break;
  832. case INTERNET_OPTION_SEND_THROUGHPUT:
  833. error = ERROR_NOT_SUPPORTED;
  834. break;
  835. case INTERNET_OPTION_RECEIVE_THROUGHPUT:
  836. error = ERROR_NOT_SUPPORTED;
  837. break;
  838. case INTERNET_OPTION_REQUEST_PRIORITY:
  839. if (handleType == TypeHttpRequestHandle) {
  840. requiredSize = sizeof(dwValue);
  841. dwValue = ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->GetPriority();
  842. lpSource = (LPVOID)&dwValue;
  843. } else {
  844. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  845. }
  846. break;
  847. case INTERNET_OPTION_HTTP_VERSION:
  848. requiredSize = sizeof(HttpVersionInfo);
  849. lpSource = (LPVOID)&HttpVersionInfo;
  850. break;
  851. case INTERNET_OPTION_NET_SPEED:
  852. break;
  853. case INTERNET_OPTION_BYPASS_EDITED_ENTRY:
  854. requiredSize = sizeof(BOOL);
  855. dwValue = GlobalBypassEditedEntry;
  856. lpSource = (LPVOID)&dwValue;
  857. break;
  858. case INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO:
  859. //
  860. // internal option
  861. //
  862. if (handleType == TypeHttpRequestHandle) {
  863. requiredSize = sizeof(socketInfo);
  864. lpSource = (LPVOID)&socketInfo;
  865. HTTP_REQUEST_HANDLE_OBJECT * pReq;
  866. pReq = (HTTP_REQUEST_HANDLE_OBJECT *)hInternet;
  867. socketInfo.Socket = pReq->GetSocket();
  868. socketInfo.SourcePort = pReq->GetSourcePort();
  869. socketInfo.DestPort = pReq->GetDestPort();
  870. socketInfo.Flags = (pReq->FromKeepAlivePool()
  871. ? IDSI_FLAG_KEEP_ALIVE : 0)
  872. | (pReq->IsSecure()
  873. ? IDSI_FLAG_SECURE : 0)
  874. | (pReq->IsRequestUsingProxy()
  875. ? IDSI_FLAG_PROXY : 0)
  876. | (pReq->IsTunnel()
  877. ? IDSI_FLAG_TUNNEL : 0);
  878. } else {
  879. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  880. }
  881. break;
  882. case INTERNET_OPTION_CACHE_TIMESTAMPS:
  883. if (handleType == TypeHttpRequestHandle) {
  884. if (*lpdwBufferLength == sizeof(INTERNET_CACHE_TIMESTAMPS)) {
  885. INTERNET_CACHE_TIMESTAMPS* ts =
  886. (INTERNET_CACHE_TIMESTAMPS*)lpBuffer;
  887. BOOL bU1;
  888. BOOL bU2;
  889. BOOL bU3;
  890. FILETIME ftPostCheck;
  891. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  892. GetTimeStampsForCache(
  893. &(ts->ftExpires),
  894. &(ts->ftLastModified),
  895. &ftPostCheck,
  896. &bU1, &bU2, &bU3 );
  897. } else {
  898. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  899. }
  900. } else {
  901. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  902. }
  903. goto quit;
  904. break;
  905. case INTERNET_OPTION_DISABLE_AUTODIAL:
  906. error = ERROR_NOT_SUPPORTED;
  907. break;
  908. case INTERNET_OPTION_AUTODIAL_MODE:
  909. requiredSize = sizeof(DWORD);
  910. dwValue = GetAutodialMode();
  911. lpSource = (LPVOID)&dwValue;
  912. break;
  913. case INTERNET_OPTION_AUTODIAL_CONNECTION:
  914. error = GetAutodialConnection((LPSTR)lpBuffer, *lpdwBufferLength);
  915. isString = TRUE;
  916. lpSource = lpBuffer;
  917. requiredSize = *lpdwBufferLength;
  918. break;
  919. // IE5 #23845: Wininet: Various auth related feature requests for FP
  920. // This will return TRUE if post data will be sent on a request.
  921. case INTERNET_OPTION_DETECT_POST_SEND:
  922. if (handleType == TypeHttpRequestHandle)
  923. {
  924. requiredSize = sizeof(DWORD);
  925. lpSource = (LPVOID)&dwValue;
  926. HTTP_REQUEST_HANDLE_OBJECT *pRequest;
  927. pRequest = (HTTP_REQUEST_HANDLE_OBJECT*) hInternet;
  928. if (pRequest->GetAuthState() == AUTHSTATE_NEGOTIATE
  929. && !((PLUG_CTX*)(pRequest->GetAuthCtx()))->_fNTLMProxyAuth
  930. && !(pRequest->GetAuthCtx()->GetSchemeType() == AUTHCTX::SCHEME_DPA))
  931. {
  932. dwValue = 0;
  933. }
  934. else
  935. {
  936. dwValue = 1;
  937. }
  938. }
  939. else
  940. {
  941. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  942. }
  943. break;
  944. case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
  945. if( !hInternet ) {
  946. requiredSize = sizeof(dwValue);
  947. dwValue = 0;
  948. lpSource = (LPVOID)&dwValue;
  949. dwValue = GlobalMaxConnectionsPerServer;
  950. }
  951. else
  952. error = ERROR_INTERNET_INVALID_OPERATION;
  953. break;
  954. case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER:
  955. if( !hInternet ) {
  956. requiredSize = sizeof(dwValue);
  957. dwValue = 0;
  958. lpSource = (LPVOID)&dwValue;
  959. dwValue = GlobalMaxConnectionsPer1_0Server;
  960. }
  961. else
  962. error = ERROR_INTERNET_INVALID_OPERATION;
  963. break;
  964. case INTERNET_OPTION_PER_CONNECTION_OPTION:
  965. {
  966. if (handleType != TypeInternetHandle) {
  967. hInternet = NULL;
  968. }
  969. error = QueryPerConnOptions(hInternet,
  970. lpThreadInfo->IsAutoProxyProxyThread,
  971. (LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
  972. requiredSize = *lpdwBufferLength;
  973. goto quit;
  974. }
  975. case INTERNET_OPTION_COOKIES_3RD_PARTY:
  976. if (handleType == TypeHttpRequestHandle)
  977. {
  978. requiredSize = sizeof(DWORD);
  979. lpSource = (LPVOID)&dwValue;
  980. dwValue = (DWORD) ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->Is3rdPartyCookies();
  981. }
  982. else
  983. {
  984. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  985. }
  986. break;
  987. #if INET_DEBUG
  988. case INTERNET_OPTION_GET_DEBUG_INFO:
  989. error = InternetGetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
  990. lpdwBufferLength
  991. );
  992. //
  993. // everything updated, so quit without going through common buffer
  994. // processing
  995. //
  996. goto quit;
  997. break;
  998. case INTERNET_OPTION_GET_HANDLE_COUNT:
  999. requiredSize = sizeof(DWORD);
  1000. dwValue = InternetHandleCount();
  1001. lpSource = (LPVOID)&dwValue;
  1002. break;
  1003. #endif // INET_DEBUG
  1004. default:
  1005. requiredSize = 0;
  1006. error = ERROR_INVALID_PARAMETER;
  1007. break;
  1008. }
  1009. //
  1010. // if we have a buffer and enough space, then copy the data
  1011. //
  1012. if (error == ERROR_SUCCESS) {
  1013. //
  1014. // if we are returning a string, calculate the amount of space
  1015. // required to hold it
  1016. //
  1017. if (isString) {
  1018. if (lpSource != NULL) {
  1019. requiredSize = lstrlen((LPCSTR)lpSource) + 1;
  1020. } else {
  1021. //
  1022. // option string is NULL: return an empty string
  1023. //
  1024. lpSource = "";
  1025. requiredSize = 1;
  1026. }
  1027. }
  1028. INET_ASSERT(lpSource != NULL);
  1029. if ((*lpdwBufferLength >= requiredSize)
  1030. && ARGUMENT_PRESENT(lpBuffer)) {
  1031. memcpy(lpBuffer, lpSource, requiredSize);
  1032. if (isString) {
  1033. //
  1034. // string copied successfully. Returned length is string
  1035. // length, not buffer length, i.e. drop 1 for '\0'
  1036. //
  1037. --requiredSize;
  1038. }
  1039. } else {
  1040. error = ERROR_INSUFFICIENT_BUFFER;
  1041. }
  1042. // Scrub and free password string from GetUserOrPass().
  1043. switch (dwOption)
  1044. {
  1045. case INTERNET_OPTION_PASSWORD:
  1046. case INTERNET_OPTION_PROXY_PASSWORD:
  1047. if (freeString)
  1048. {
  1049. INET_ASSERT(isString);
  1050. SecureZeroMemory(lpSource, requiredSize);
  1051. FREE_MEMORY(lpSource);
  1052. }
  1053. break;
  1054. }
  1055. }
  1056. quit:
  1057. //
  1058. // return the amount the app needs to supply, or the amount of data in the
  1059. // buffer, depending on success/failure status
  1060. //
  1061. *lpdwBufferLength = requiredSize;
  1062. if (hObjectMapped != NULL) {
  1063. DereferenceObject((LPVOID)hObjectMapped);
  1064. }
  1065. done:
  1066. if (error == ERROR_SUCCESS) {
  1067. success = TRUE;
  1068. IF_DEBUG(API) {
  1069. if (isString) {
  1070. DEBUG_PRINT_API(API,
  1071. INFO,
  1072. ("returning %q (%d chars)\n",
  1073. lpBuffer,
  1074. requiredSize
  1075. ));
  1076. } else {
  1077. DEBUG_DUMP_API(API,
  1078. "option data:\n",
  1079. lpBuffer,
  1080. requiredSize
  1081. );
  1082. }
  1083. }
  1084. } else {
  1085. DEBUG_ERROR(API, error);
  1086. IF_DEBUG(API) {
  1087. if (error == ERROR_INSUFFICIENT_BUFFER) {
  1088. DEBUG_PRINT_API(API,
  1089. INFO,
  1090. ("*lpdwBufferLength (%#x)= %d\n",
  1091. lpdwBufferLength,
  1092. *lpdwBufferLength
  1093. ));
  1094. }
  1095. }
  1096. SetLastError(error);
  1097. success = FALSE;
  1098. }
  1099. DEBUG_LEAVE_API(success);
  1100. return success;
  1101. }
  1102. INTERNETAPI_(BOOL) InternetQueryOptionW(
  1103. IN HINTERNET hInternet OPTIONAL,
  1104. IN DWORD dwOption,
  1105. OUT LPVOID lpBuffer OPTIONAL,
  1106. IN OUT LPDWORD lpdwBufferLength
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. description-of-function.
  1111. Arguments:
  1112. hInternet -
  1113. dwOption -
  1114. lpBuffer -
  1115. lpdwBufferLength -
  1116. Return Value:
  1117. BOOL
  1118. --*/
  1119. {
  1120. DEBUG_ENTER_API((DBG_API,
  1121. Bool,
  1122. "InternetQueryOptionW",
  1123. "%#x, %s (%d), %#x, %#x [%d]",
  1124. hInternet,
  1125. InternetMapOption(dwOption),
  1126. dwOption,
  1127. lpBuffer,
  1128. lpdwBufferLength,
  1129. lpdwBufferLength
  1130. ? (!IsBadReadPtr(lpdwBufferLength, sizeof(DWORD))
  1131. ? *lpdwBufferLength
  1132. : 0)
  1133. : 0
  1134. ));
  1135. DWORD dwErr = ERROR_SUCCESS;
  1136. BOOL fResult = FALSE;
  1137. MEMORYPACKET mpBuffer;
  1138. switch (dwOption)
  1139. {
  1140. case INTERNET_OPTION_USERNAME:
  1141. case INTERNET_OPTION_PASSWORD:
  1142. case INTERNET_OPTION_DATAFILE_NAME:
  1143. case INTERNET_OPTION_URL:
  1144. case INTERNET_OPTION_USER_AGENT:
  1145. case INTERNET_OPTION_PROXY_USERNAME:
  1146. case INTERNET_OPTION_PROXY_PASSWORD:
  1147. case INTERNET_OPTION_SECONDARY_CACHE_KEY:
  1148. case INTERNET_OPTION_AUTODIAL_CONNECTION:
  1149. if (lpBuffer)
  1150. {
  1151. mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwBufferLength;
  1152. mpBuffer.psStr = (LPSTR)ALLOC_BYTES(mpBuffer.dwAlloc*sizeof(CHAR));
  1153. if (!mpBuffer.psStr)
  1154. {
  1155. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1156. break;
  1157. }
  1158. }
  1159. fResult = InternetQueryOptionA(hInternet,
  1160. dwOption,
  1161. (LPVOID)mpBuffer.psStr,
  1162. &mpBuffer.dwSize
  1163. );
  1164. if (fResult)
  1165. {
  1166. *lpdwBufferLength = MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
  1167. NULL, 0);
  1168. if (*lpdwBufferLength*sizeof(WCHAR)<=mpBuffer.dwAlloc && lpBuffer)
  1169. {
  1170. MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize+1,
  1171. (LPWSTR)lpBuffer, *lpdwBufferLength);
  1172. (*lpdwBufferLength)--;
  1173. }
  1174. else
  1175. {
  1176. *lpdwBufferLength *= sizeof(WCHAR);
  1177. fResult = FALSE;
  1178. dwErr = ERROR_INSUFFICIENT_BUFFER;
  1179. }
  1180. }
  1181. else
  1182. {
  1183. if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
  1184. {
  1185. *lpdwBufferLength = mpBuffer.dwSize*sizeof(WCHAR);
  1186. }
  1187. }
  1188. break;
  1189. case INTERNET_OPTION_PER_CONNECTION_OPTION:
  1190. {
  1191. if (!lpBuffer)
  1192. {
  1193. dwErr = ERROR_INVALID_PARAMETER;
  1194. break;
  1195. }
  1196. INTERNET_PER_CONN_OPTION_LISTA listA;
  1197. LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
  1198. CHAR szEntryA[RAS_MaxEntryName + 1];
  1199. listA.pszConnection = szEntryA;
  1200. InitIPCOList(plistW, &listA);
  1201. listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
  1202. for (DWORD i=0; i<listA.dwOptionCount; i++)
  1203. {
  1204. listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
  1205. listA.pOptions[i].Value.pszValue = NULL;
  1206. plistW->pOptions[i].Value.pszValue = NULL;
  1207. }
  1208. fResult = InternetQueryOptionA(hInternet,
  1209. dwOption,
  1210. (PVOID)&listA,
  1211. lpdwBufferLength);
  1212. // Now, convert from ansi to unicode
  1213. if (fResult)
  1214. {
  1215. for (DWORD i=0; i<listA.dwOptionCount; i++)
  1216. {
  1217. switch (listA.pOptions[i].dwOption)
  1218. {
  1219. case INTERNET_PER_CONN_FLAGS:
  1220. case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
  1221. case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
  1222. plistW->pOptions[i].Value.dwValue = listA.pOptions[i].Value.dwValue;
  1223. break;
  1224. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
  1225. plistW->pOptions[i].Value.ftValue = listA.pOptions[i].Value.ftValue;
  1226. break;
  1227. case INTERNET_PER_CONN_PROXY_SERVER:
  1228. case INTERNET_PER_CONN_PROXY_BYPASS:
  1229. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  1230. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  1231. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  1232. if (listA.pOptions[i].Value.pszValue && *listA.pOptions[i].Value.pszValue)
  1233. {
  1234. DWORD cc = MultiByteToWideChar(CP_ACP,
  1235. 0,
  1236. listA.pOptions[i].Value.pszValue,
  1237. -1,
  1238. NULL,
  1239. 0);
  1240. plistW->pOptions[i].Value.pszValue = (PWSTR)GlobalAlloc(GPTR, cc*sizeof(WCHAR));
  1241. if (!plistW->pOptions[i].Value.pszValue)
  1242. {
  1243. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1244. goto iopco_cleanup;
  1245. }
  1246. MultiByteToWideChar(CP_ACP,
  1247. 0,
  1248. listA.pOptions[i].Value.pszValue,
  1249. -1,
  1250. plistW->pOptions[i].Value.pszValue,
  1251. cc);
  1252. }
  1253. break;
  1254. default:
  1255. INET_ASSERT(FALSE);
  1256. dwErr = ERROR_INVALID_PARAMETER;
  1257. goto iopco_cleanup;
  1258. break;
  1259. }
  1260. }
  1261. }
  1262. else
  1263. {
  1264. plistW->dwOptionError = listA.dwOptionError;
  1265. }
  1266. iopco_cleanup:
  1267. // Free all the allocated buffers
  1268. for (i=0; i<listA.dwOptionCount; i++)
  1269. {
  1270. switch (listA.pOptions[i].dwOption)
  1271. {
  1272. case INTERNET_PER_CONN_PROXY_SERVER:
  1273. case INTERNET_PER_CONN_PROXY_BYPASS:
  1274. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  1275. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  1276. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  1277. // These should have been converted from ansi to unicode
  1278. // and can be freed now
  1279. if (listA.pOptions[i].Value.pszValue)
  1280. {
  1281. GlobalFree(listA.pOptions[i].Value.pszValue);
  1282. }
  1283. // No point in passing back buffers in the event of an error
  1284. // condition
  1285. if (dwErr && plistW->pOptions[i].Value.pszValue)
  1286. {
  1287. GlobalFree(plistW->pOptions[i].Value.pszValue);
  1288. }
  1289. break;
  1290. default:
  1291. // No need to do anything
  1292. break;
  1293. }
  1294. }
  1295. }
  1296. break;
  1297. default:
  1298. fResult = InternetQueryOptionA(hInternet,
  1299. dwOption,
  1300. lpBuffer,
  1301. lpdwBufferLength
  1302. );
  1303. }
  1304. if (dwErr!=ERROR_SUCCESS)
  1305. {
  1306. SetLastError(dwErr);
  1307. DEBUG_ERROR(INET, dwErr);
  1308. }
  1309. DEBUG_LEAVE_API(fResult);
  1310. return fResult;
  1311. }
  1312. INTERNETAPI_(BOOL) InternetSetOptionA(
  1313. IN HINTERNET hInternet OPTIONAL,
  1314. IN DWORD dwOption,
  1315. IN LPVOID lpBuffer,
  1316. IN DWORD dwBufferLength
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. Sets a handle-specific variable, or a per-thread variable
  1321. Arguments:
  1322. hInternet - handle of object for which information will be set,
  1323. or NULL if the option defines a per-thread variable
  1324. dwOption - the handle-specific INTERNET_OPTION to set
  1325. lpBuffer - pointer to a buffer containing value to set
  1326. dwBufferLength - size of lpBuffer
  1327. Return Value:
  1328. BOOL
  1329. Success - TRUE
  1330. Failure - FALSE. Call GetLastError() for more info:
  1331. ERROR_INVALID_HANDLE
  1332. hInternet does not identify a valid Internet handle
  1333. object
  1334. ERROR_INTERNET_INTERNAL_ERROR
  1335. Shouldn't see this?
  1336. ERROR_INVALID_PARAMETER
  1337. One of the parameters was bad
  1338. ERROR_INTERNET_INVALID_OPTION
  1339. The requested option cannot be set
  1340. ERROR_INTERNET_OPTION_NOT_SETTABLE
  1341. Can't set this option, only query it
  1342. ERROR_INTERNET_BAD_OPTION_LENGTH
  1343. The dwBufferLength parameter is incorrect for the
  1344. expected type of the option
  1345. --*/
  1346. {
  1347. DEBUG_ENTER_API((DBG_API,
  1348. Bool,
  1349. "InternetSetOptionA",
  1350. "%#x, %s (%d), %#x [%#x], %d",
  1351. hInternet,
  1352. InternetMapOption(dwOption),
  1353. dwOption,
  1354. lpBuffer,
  1355. lpBuffer
  1356. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  1357. ? *(LPDWORD)lpBuffer
  1358. : 0)
  1359. : 0,
  1360. dwBufferLength
  1361. ));
  1362. DWORD error;
  1363. BOOL success = TRUE;
  1364. HINTERNET_HANDLE_TYPE handleType;
  1365. LPINTERNET_THREAD_INFO lpThreadInfo = NULL;
  1366. DWORD requiredSize;
  1367. HINTERNET hObjectMapped = NULL;
  1368. INTERNET_CONNECT_HANDLE_OBJECT *lphRequest;
  1369. //
  1370. // Auth code can query on connect handle by walking up from request handle,
  1371. // unbeknownst to the client, who might try to set the option concurrently.
  1372. // Ideally access would be serialized only for the four combinations of
  1373. // {user,pass} and {server,proxy}, but unconditional keeps the code simple.
  1374. //
  1375. //AuthLock();
  1376. //
  1377. // validate parameters
  1378. //
  1379. if ((dwBufferLength == 0) || IsBadReadPtr(lpBuffer, dwBufferLength)) {
  1380. switch (dwOption) {
  1381. //
  1382. // these options don't require a buffer - don't fail request because
  1383. // no buffer supplied
  1384. //
  1385. case INTERNET_OPTION_SETTINGS_CHANGED:
  1386. case INTERNET_OPTION_PROXY_SETTINGS_CHANGED:
  1387. case INTERNET_OPTION_END_BROWSER_SESSION:
  1388. case INTERNET_OPTION_RESET_URLCACHE_SESSION:
  1389. case INTERNET_OPTION_REFRESH:
  1390. case INTERNET_OPTION_DIGEST_AUTH_UNLOAD:
  1391. case INTERNET_OPTION_IGNORE_OFFLINE:
  1392. case INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT:
  1393. case INTERNET_OPTION_DISABLE_PASSPORT_AUTH:
  1394. case INTERNET_OPTION_ENABLE_PASSPORT_AUTH:
  1395. case INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS:
  1396. case INTERNET_OPTION_ACTIVATE_WORKER_THREADS:
  1397. case INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS:
  1398. break;
  1399. default:
  1400. error = ERROR_INVALID_PARAMETER;
  1401. goto quit;
  1402. }
  1403. }
  1404. if (!GlobalDataInitialized) {
  1405. error = GlobalDataInitialize();
  1406. if (error != ERROR_SUCCESS) {
  1407. goto done;
  1408. }
  1409. }
  1410. //
  1411. // validate the handle and get its type
  1412. //
  1413. if (ARGUMENT_PRESENT(hInternet)) {
  1414. //
  1415. // map the handle
  1416. //
  1417. error = MapHandleToAddress(hInternet, (LPVOID *)&hInternet, FALSE);
  1418. if (error == ERROR_SUCCESS) {
  1419. hObjectMapped = hInternet;
  1420. error = RGetHandleType(hInternet, &handleType);
  1421. }
  1422. } else if (IS_PER_THREAD_OPTION(dwOption)) {
  1423. //
  1424. // this option updates the per-thread information block, so this is a
  1425. // good point at which to get it
  1426. //
  1427. lpThreadInfo = InternetGetThreadInfo();
  1428. if (lpThreadInfo != NULL) {
  1429. error = ERROR_SUCCESS;
  1430. } else {
  1431. DEBUG_PRINT(INET,
  1432. ERROR,
  1433. ("InternetGetThreadInfo() returns NULL\n"
  1434. ));
  1435. //
  1436. // we never expect this - ERROR_INTERNET_SPANISH_INQUISITION
  1437. //
  1438. INET_ASSERT(FALSE);
  1439. error = ERROR_INTERNET_INTERNAL_ERROR;
  1440. }
  1441. } else if (IS_PER_PROCESS_OPTION(dwOption)) {
  1442. error = ERROR_SUCCESS;
  1443. } else {
  1444. //
  1445. // catch any invalid options for the NULL handle. If the option is valid
  1446. // then it is incorrect for this handle type, otherwise its an invalid
  1447. // option, period
  1448. //
  1449. error = IS_VALID_OPTION(dwOption)
  1450. ? ERROR_INTERNET_INCORRECT_HANDLE_TYPE
  1451. : ERROR_INTERNET_INVALID_OPTION
  1452. ;
  1453. }
  1454. if (error != ERROR_SUCCESS) {
  1455. goto quit;
  1456. }
  1457. //
  1458. // if the option and handle combination is valid then set the option value
  1459. //
  1460. switch (dwOption) {
  1461. case INTERNET_OPTION_CALLBACK:
  1462. case INTERNET_OPTION_HANDLE_TYPE:
  1463. //case INTERNET_OPTION_GATEWAY_NAME:
  1464. case INTERNET_OPTION_KEEP_CONNECTION:
  1465. case INTERNET_OPTION_ASYNC_ID:
  1466. case INTERNET_OPTION_ASYNC_REQUEST_COUNT:
  1467. case INTERNET_OPTION_ASYNC_QUEUE_DEPTH:
  1468. case INTERNET_OPTION_WORKER_THREAD_TIMEOUT:
  1469. case INTERNET_OPTION_IDLE_STATE:
  1470. case INTERNET_OPTION_CONNECT_TIME:
  1471. case INTERNET_OPTION_SEND_THROUGHPUT:
  1472. case INTERNET_OPTION_RECEIVE_THROUGHPUT:
  1473. case INTERNET_OPTION_NET_SPEED:
  1474. //
  1475. // these options cannot be set by this function
  1476. //
  1477. error = ERROR_INTERNET_OPTION_NOT_SETTABLE;
  1478. break;
  1479. case INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS:
  1480. if (!g_bDisableHibernation)
  1481. {
  1482. g_bHibernating = TRUE;
  1483. }
  1484. break;
  1485. case INTERNET_OPTION_ACTIVATE_WORKER_THREADS:
  1486. if (g_bHibernating)
  1487. {
  1488. InterruptSelect();
  1489. GlobalProxyInfo.ActivateAutoproxyThread();
  1490. }
  1491. break;
  1492. case INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS:
  1493. if (g_bHibernating)
  1494. {
  1495. g_bHibernating = FALSE;
  1496. InterruptSelect();
  1497. GlobalProxyInfo.ActivateAutoproxyThread();
  1498. }
  1499. break;
  1500. case INTERNET_OPTION_BYPASS_EDITED_ENTRY:
  1501. requiredSize = sizeof(BOOL);
  1502. if (dwBufferLength != requiredSize) {
  1503. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1504. break;
  1505. }
  1506. // Only support global, not per handle yet
  1507. if (hInternet != NULL) {
  1508. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1509. break;
  1510. }
  1511. // Made it this far, so buffer is right size and handle is NULL
  1512. GlobalBypassEditedEntry = *(LPBOOL)lpBuffer;
  1513. break;
  1514. case INTERNET_OPTION_CONNECT_TIMEOUT:
  1515. case INTERNET_OPTION_CONNECT_RETRIES:
  1516. case INTERNET_OPTION_CONNECT_BACKOFF:
  1517. case INTERNET_OPTION_SEND_TIMEOUT:
  1518. case INTERNET_OPTION_RECEIVE_TIMEOUT:
  1519. case INTERNET_OPTION_DATA_SEND_TIMEOUT:
  1520. case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
  1521. case INTERNET_OPTION_FROM_CACHE_TIMEOUT:
  1522. requiredSize = sizeof(DWORD);
  1523. if (dwBufferLength != requiredSize) {
  1524. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1525. break;
  1526. }
  1527. //
  1528. // if hInternet is NULL then the app is requesting that we set the
  1529. // global timeout values, not handle-specific ones
  1530. //
  1531. if (hInternet == NULL) {
  1532. switch (dwOption) {
  1533. case INTERNET_OPTION_CONNECT_TIMEOUT:
  1534. GlobalConnectTimeout = *(LPDWORD)lpBuffer;
  1535. break;
  1536. case INTERNET_OPTION_CONNECT_RETRIES:
  1537. GlobalConnectRetries = *(LPDWORD)lpBuffer;
  1538. break;
  1539. case INTERNET_OPTION_SEND_TIMEOUT:
  1540. GlobalSendTimeout = *(LPDWORD)lpBuffer;
  1541. break;
  1542. case INTERNET_OPTION_RECEIVE_TIMEOUT:
  1543. GlobalReceiveTimeout = *(LPDWORD)lpBuffer;
  1544. break;
  1545. case INTERNET_OPTION_DATA_SEND_TIMEOUT:
  1546. GlobalDataSendTimeout = *(LPDWORD)lpBuffer;
  1547. break;
  1548. case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT:
  1549. GlobalDataReceiveTimeout = *(LPDWORD)lpBuffer;
  1550. break;
  1551. case INTERNET_OPTION_FROM_CACHE_TIMEOUT:
  1552. GlobalFromCacheTimeout = *(LPDWORD)lpBuffer;
  1553. break;
  1554. }
  1555. break;
  1556. }
  1557. //
  1558. // we have a non-NULL context handle: the app wants to set specific
  1559. // protocol timeouts
  1560. //
  1561. switch (handleType) {
  1562. case TypeInternetHandle:
  1563. case TypeFtpConnectHandle:
  1564. case TypeFtpFindHandle:
  1565. case TypeFtpFindHandleHtml:
  1566. case TypeFtpFileHandle:
  1567. case TypeFtpFileHandleHtml:
  1568. case TypeGopherConnectHandle:
  1569. case TypeGopherFindHandle:
  1570. case TypeGopherFindHandleHtml:
  1571. case TypeGopherFileHandle:
  1572. case TypeGopherFileHandleHtml:
  1573. case TypeHttpConnectHandle:
  1574. case TypeHttpRequestHandle:
  1575. //
  1576. // N.B. For some of these handle types, setting a timeout etc.
  1577. // value will have absolutely no affect (we have already gotten
  1578. // the information after connecting, sending etc.), but we'll
  1579. // allow the app to go ahead anyway (its benign)
  1580. //
  1581. error = RSetTimeout(hInternet,
  1582. dwOption,
  1583. *(LPDWORD)lpBuffer
  1584. );
  1585. break;
  1586. default:
  1587. //
  1588. // any other handle type (?) cannot have timeouts set for it
  1589. //
  1590. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1591. break;
  1592. }
  1593. break;
  1594. case INTERNET_OPTION_CONTEXT_VALUE:
  1595. //
  1596. // BUGBUG - can't change context if async operation is pending
  1597. //
  1598. if (dwBufferLength == sizeof(lpThreadInfo->Context)) {
  1599. error = RSetContext(hInternet, *((DWORD*) lpBuffer));
  1600. } else {
  1601. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1602. }
  1603. break;
  1604. case INTERNET_OPTION_NAME_RES_THREAD:
  1605. //if (dwBufferLength == sizeof(MultiThreadedNameResolution)) {
  1606. // MultiThreadedNameResolution = (BOOL)(*(LPDWORD)lpBuffer != 0);
  1607. //} else {
  1608. // error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1609. //}
  1610. break;
  1611. case INTERNET_OPTION_READ_BUFFER_SIZE:
  1612. case INTERNET_OPTION_WRITE_BUFFER_SIZE:
  1613. if (IS_CONNECT_HANDLE_TYPE(handleType)) {
  1614. if (dwBufferLength == sizeof(DWORD)) {
  1615. DWORD bufferSize;
  1616. bufferSize = *(LPDWORD)lpBuffer;
  1617. if (bufferSize > 0) {
  1618. error = RSetBufferSize(hInternet, dwOption, bufferSize);
  1619. } else {
  1620. //
  1621. // the read/write buffer size cannot be set to 0
  1622. //
  1623. error = ERROR_INVALID_PARAMETER;
  1624. }
  1625. } else {
  1626. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1627. }
  1628. } else {
  1629. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1630. }
  1631. break;
  1632. BOOL fUser, fProxy;
  1633. case INTERNET_OPTION_ASYNC_PRIORITY:
  1634. error = ERROR_CALL_NOT_IMPLEMENTED;
  1635. break;
  1636. case INTERNET_OPTION_AUTH_FLAGS:
  1637. if (handleType != TypeHttpRequestHandle)
  1638. {
  1639. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1640. }
  1641. else if (dwBufferLength < sizeof(DWORD))
  1642. {
  1643. error = ERROR_INSUFFICIENT_BUFFER;
  1644. }
  1645. else
  1646. {
  1647. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  1648. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1649. lphHttpRqst->SetAuthFlag(*(LPDWORD)lpBuffer);
  1650. error = ERROR_SUCCESS;
  1651. }
  1652. break;
  1653. case INTERNET_OPTION_USERNAME:
  1654. fUser = IS_USER;
  1655. fProxy = IS_SERVER;
  1656. goto callSetUserOrPass;
  1657. case INTERNET_OPTION_PASSWORD:
  1658. fUser = IS_PASS;
  1659. fProxy = IS_SERVER;
  1660. goto callSetUserOrPass;
  1661. case INTERNET_OPTION_PROXY_USERNAME:
  1662. fUser = IS_USER;
  1663. fProxy = IS_PROXY;
  1664. goto callSetUserOrPass;
  1665. case INTERNET_OPTION_PROXY_PASSWORD:
  1666. fUser = IS_PASS;
  1667. fProxy = IS_PROXY;
  1668. goto callSetUserOrPass;
  1669. callSetUserOrPass:
  1670. if (hInternet == 0)
  1671. {
  1672. if (!fProxy)
  1673. {
  1674. AuthLock();
  1675. SetUserOrPass ((LPSTR)lpBuffer, fUser);
  1676. TimeStampCreds();
  1677. AuthUnlock();
  1678. }
  1679. else
  1680. {
  1681. error = ERROR_INVALID_PARAMETER;
  1682. }
  1683. error = ERROR_SUCCESS;
  1684. }
  1685. else if (handleType != TypeInternetHandle) {
  1686. AuthLock();
  1687. lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
  1688. lphRequest->SetUserOrPass ((LPSTR)lpBuffer, fUser, fProxy);
  1689. lphRequest->TimeStampCreds();
  1690. AuthUnlock();
  1691. error = ERROR_SUCCESS;
  1692. } else {
  1693. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1694. }
  1695. break;
  1696. case INTERNET_OPTION_DISABLE_PASSPORT_AUTH:
  1697. if (handleType != TypeInternetHandle)
  1698. {
  1699. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1700. }
  1701. else
  1702. {
  1703. ((INTERNET_HANDLE_OBJECT *)hInternet)->DisableTweener();
  1704. error = ERROR_SUCCESS;
  1705. }
  1706. break;
  1707. case INTERNET_OPTION_ENABLE_PASSPORT_AUTH:
  1708. if (handleType != TypeInternetHandle)
  1709. {
  1710. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1711. }
  1712. else
  1713. {
  1714. ((INTERNET_HANDLE_OBJECT *)hInternet)->EnableTweener();
  1715. error = ERROR_SUCCESS;
  1716. }
  1717. break;
  1718. case INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT:
  1719. if (handleType != TypeInternetHandle)
  1720. {
  1721. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1722. }
  1723. else
  1724. {
  1725. ((INTERNET_HANDLE_OBJECT *)hInternet)->ExemptConnLimit();
  1726. error = ERROR_SUCCESS;
  1727. }
  1728. break;
  1729. case INTERNET_OPTION_CLIENT_CERT_CONTEXT:
  1730. if (handleType != TypeHttpRequestHandle)
  1731. {
  1732. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1733. }
  1734. else if (dwBufferLength < sizeof(CERT_CONTEXT))
  1735. {
  1736. error = ERROR_INSUFFICIENT_BUFFER;
  1737. }
  1738. else
  1739. {
  1740. HTTP_REQUEST_HANDLE_OBJECT *pRequest =
  1741. (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1742. CERT_CONTEXT_ARRAY* pArray = pRequest->GetCertContextArray();
  1743. if (!pArray)
  1744. {
  1745. pArray = new CERT_CONTEXT_ARRAY;
  1746. pRequest->SetCertContextArray(pArray);
  1747. }
  1748. if (!pArray)
  1749. error = ERROR_NOT_ENOUGH_MEMORY;
  1750. else
  1751. {
  1752. error = LoadSecurity();
  1753. if (ERROR_SUCCESS == error)
  1754. {
  1755. pArray->Reset();
  1756. pArray->AddCertContext((PCCERT_CONTEXT) lpBuffer);
  1757. pArray->SelectCertContext(0);
  1758. error = ERROR_SUCCESS;
  1759. }
  1760. else
  1761. {
  1762. pRequest->SetCertContextArray(NULL);
  1763. }
  1764. }
  1765. }
  1766. break;
  1767. case INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT:
  1768. // This option sets an index into an internal wininet structure.
  1769. // This is worthless to apps because there is no way to guarantee
  1770. // they enum the cert store the same as wininet, especially if the
  1771. // server returns a list of acceptable CA to filter by. This has
  1772. // been superseded by INTERNET_OPTION_CLIENT_CERT_CONTEXT above.
  1773. if (handleType != TypeHttpRequestHandle)
  1774. {
  1775. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1776. }
  1777. else if (dwBufferLength < sizeof(DWORD))
  1778. {
  1779. error = ERROR_INSUFFICIENT_BUFFER;
  1780. }
  1781. else
  1782. {
  1783. CERT_CONTEXT_ARRAY* pCertContextArray;
  1784. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  1785. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1786. pCertContextArray =
  1787. lphHttpRqst->GetCertContextArray();
  1788. if ( ! pCertContextArray )
  1789. {
  1790. error = ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP;
  1791. }
  1792. else
  1793. {
  1794. if ( (*((LPINT)lpBuffer) < (INT) pCertContextArray->GetArraySize() )
  1795. || *((LPINT)lpBuffer) == -1 )
  1796. {
  1797. pCertContextArray->SelectCertContext( *((LPDWORD)lpBuffer) );
  1798. error = ERROR_SUCCESS;
  1799. }
  1800. else
  1801. {
  1802. error = ERROR_INVALID_PARAMETER;
  1803. }
  1804. }
  1805. }
  1806. break;
  1807. case INTERNET_OPTION_SECURITY_FLAGS:
  1808. if (handleType != TypeHttpRequestHandle)
  1809. {
  1810. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1811. }
  1812. else if (dwBufferLength < sizeof(DWORD))
  1813. {
  1814. error = ERROR_INSUFFICIENT_BUFFER;
  1815. }
  1816. else
  1817. {
  1818. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  1819. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  1820. lphHttpRqst->SetSecureFlags(*(LPDWORD)lpBuffer);
  1821. error = ERROR_SUCCESS;
  1822. }
  1823. break;
  1824. case INTERNET_OPTION_REFRESH:
  1825. //
  1826. // BUGBUG - can only accept global or InternetOpen() handles currently
  1827. //
  1828. if (!ARGUMENT_PRESENT(hInternet)) {
  1829. if (!GlobalProxyInfo.IsModifiedInProcess()) {
  1830. FixProxySettingsForCurrentConnection(TRUE);
  1831. error = ERROR_SUCCESS;
  1832. } else {
  1833. INET_ASSERT(error == ERROR_SUCCESS);
  1834. }
  1835. } else if (handleType == TypeInternetHandle) {
  1836. error = ((INTERNET_HANDLE_OBJECT *)hInternet)->Refresh(0);
  1837. } else {
  1838. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1839. }
  1840. break;
  1841. case INTERNET_OPTION_PROXY:
  1842. if ((handleType == TypeInternetHandle) || !ARGUMENT_PRESENT(hInternet)) {
  1843. LPINTERNET_PROXY_INFO lpInfo = (LPINTERNET_PROXY_INFO)lpBuffer;
  1844. //
  1845. // validate parameters
  1846. //
  1847. if (dwBufferLength != sizeof(*lpInfo)) {
  1848. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1849. } else if (!((lpInfo->dwAccessType == INTERNET_OPEN_TYPE_DIRECT)
  1850. || (lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
  1851. || (lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG))
  1852. || ((lpInfo->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
  1853. && ((lpInfo->lpszProxy == NULL) || (*lpInfo->lpszProxy == '\0')))) {
  1854. error = ERROR_INVALID_PARAMETER;
  1855. } else {
  1856. if (!ARGUMENT_PRESENT(hInternet)) {
  1857. INTERNET_PROXY_INFO_EX info;
  1858. memset(&info, 0, sizeof(info));
  1859. info.dwFlags = PROXY_TYPE_DIRECT;
  1860. switch (lpInfo->dwAccessType) {
  1861. case INTERNET_OPEN_TYPE_PRECONFIG:
  1862. FixProxySettingsForCurrentConnection(TRUE);
  1863. error = ERROR_SUCCESS;
  1864. goto quit;
  1865. case INTERNET_OPEN_TYPE_DIRECT:
  1866. info.dwFlags |= PROXY_TYPE_DIRECT;
  1867. break;
  1868. case INTERNET_OPEN_TYPE_PROXY:
  1869. info.dwFlags |= PROXY_TYPE_PROXY;
  1870. info.lpszProxy = lpInfo->lpszProxy;
  1871. info.lpszProxyBypass = lpInfo->lpszProxyBypass;
  1872. break;
  1873. }
  1874. GlobalProxyInfo.SetProxySettings(&info, TRUE );
  1875. } else {
  1876. error = ((INTERNET_HANDLE_OBJECT *)hInternet)->SetProxyInfo(
  1877. lpInfo->dwAccessType,
  1878. lpInfo->lpszProxy,
  1879. lpInfo->lpszProxyBypass
  1880. );
  1881. }
  1882. }
  1883. } else {
  1884. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1885. }
  1886. break;
  1887. case INTERNET_OPTION_SETTINGS_CHANGED:
  1888. {
  1889. DWORD dwVer;
  1890. IncrementCurrentSettingsVersion(&dwVer);
  1891. // eat the update settings for this process,
  1892. // since calling ChangeGlobalSettings should suffice
  1893. InternetSettingsChanged();
  1894. ChangeGlobalSettings();
  1895. PurgeKeepAlives(PKA_NOW);
  1896. }
  1897. break;
  1898. case INTERNET_OPTION_PROXY_SETTINGS_CHANGED:
  1899. {
  1900. DWORD dwVer;
  1901. IncrementCurrentSettingsVersion(&dwVer);
  1902. // eat the update settings for this process,
  1903. // since calling ChangeGlobalSettings should suffice
  1904. InternetSettingsChanged();
  1905. ChangeGlobalSettings();
  1906. // PurgeKeepAlives(PKA_NOW);
  1907. }
  1908. break;
  1909. case INTERNET_OPTION_USER_AGENT:
  1910. if (*(LPSTR)lpBuffer == '\0') {
  1911. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  1912. } else {
  1913. if (handleType == TypeInternetHandle) {
  1914. ((INTERNET_HANDLE_OBJECT *)hInternet)->SetUserAgent((LPSTR)lpBuffer);
  1915. } else {
  1916. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  1917. }
  1918. }
  1919. break;
  1920. case INTERNET_OPTION_END_BROWSER_SESSION:
  1921. //
  1922. // Flush the in-memory password cache and drop any keep-alive
  1923. // sockets which had authorization (IIS retains the credentials.
  1924. //
  1925. AuthFlush();
  1926. PurgeKeepAlives (PKA_AUTH_FAILED);
  1927. if(g_hDialEvent)
  1928. {
  1929. WaitForSingleObject(g_hDialEvent, INFINITE);
  1930. CloseHandle(g_hDialEvent);
  1931. }
  1932. //
  1933. // Empty the content cache if registry key is set.
  1934. //
  1935. UrlCacheFlush();
  1936. //
  1937. // Flush session cookies.
  1938. //
  1939. PurgeCookieJarOfStaleCookies();
  1940. //
  1941. // Purge Proxy Script Cache
  1942. //
  1943. UPDATE_GLOBAL_PROXY_VERSION();
  1944. //
  1945. // Flush all cached SSL Certificates.
  1946. //
  1947. //GlobalCertCache.ClearList();
  1948. //
  1949. // Need to close global keys
  1950. //
  1951. ResetAutodialModule();
  1952. CloseInternetSettingsKey();
  1953. //
  1954. // Make sure cert key is reset, too
  1955. //
  1956. CloseMyCertStore();
  1957. // Look out: intentional fall through.
  1958. case INTERNET_OPTION_RESET_URLCACHE_SESSION:
  1959. // Look out: intentional fall through.
  1960. //
  1961. // Restart the session used for cache syncmode.
  1962. //
  1963. GetCurrentGmtTime ((LPFILETIME)&dwdwSessionStartTime);
  1964. dwdwSessionStartTime -= dwdwSessionStartTimeDefaultDelta;
  1965. error = ERROR_SUCCESS;
  1966. break;
  1967. case INTERNET_OPTION_DIGEST_AUTH_UNLOAD:
  1968. if (DIGEST_CTX::g_pFuncTbl)
  1969. {
  1970. DIGEST_CTX::Logoff();
  1971. DIGEST_CTX::g_pFuncTbl = NULL;
  1972. }
  1973. break;
  1974. case INTERNET_OPTION_LINE_STATE:
  1975. if (dwBufferLength == sizeof(INTERNET_ONLINE_OFFLINE_INFO)) {
  1976. LPINTERNET_ONLINE_OFFLINE_INFO lpInfo;
  1977. DWORD state;
  1978. lpInfo = (LPINTERNET_ONLINE_OFFLINE_INFO)lpBuffer;
  1979. state = lpInfo->dwOfflineState;
  1980. //
  1981. // we allow app to pass in INTERNET_STATE_OFFLINE_USER and interpret
  1982. // it as same as INTERNET_STATE_OFFLINE
  1983. //
  1984. if (state == INTERNET_STATE_OFFLINE_USER) {
  1985. state = INTERNET_STATE_OFFLINE;
  1986. }
  1987. if (((state == INTERNET_STATE_ONLINE)
  1988. || (state == INTERNET_STATE_OFFLINE))
  1989. && ((lpInfo->dwFlags & ~ISO_FORCE_OFFLINE) == 0)) {
  1990. error = SetOfflineUserState(state,
  1991. (lpInfo->dwFlags & ISO_FORCE_OFFLINE)
  1992. ? TRUE
  1993. : FALSE
  1994. );
  1995. // update registry value
  1996. InternetWriteRegistryDword("GlobalUserOffline",
  1997. ((state == INTERNET_STATE_ONLINE) ? 0 : 1));
  1998. // notification
  1999. DWORD dwOp = CACHE_NOTIFY_SET_OFFLINE;
  2000. if( state == INTERNET_STATE_ONLINE )
  2001. {
  2002. dwOp = CACHE_NOTIFY_SET_ONLINE;
  2003. }
  2004. UrlCacheSendNotification(dwOp);
  2005. // invalidate global info so other instances pick it up
  2006. DWORD dwVer;
  2007. IncrementCurrentSettingsVersion(&dwVer);
  2008. } else {
  2009. error = ERROR_INVALID_PARAMETER;
  2010. }
  2011. } else {
  2012. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2013. }
  2014. break;
  2015. case INTERNET_OPTION_OFFLINE_SEMANTICS:
  2016. break;
  2017. case INTERNET_OPTION_SECONDARY_CACHE_KEY:
  2018. if( handleType == TypeHttpRequestHandle ) {
  2019. lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
  2020. if (!lphRequest->SetSecondaryCacheKey((LPSTR) lpBuffer)) {
  2021. error = ERROR_NOT_ENOUGH_MEMORY;
  2022. } else {
  2023. INET_ASSERT (error == ERROR_SUCCESS);
  2024. }
  2025. } else {
  2026. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2027. }
  2028. break;
  2029. case INTERNET_OPTION_CALLBACK_FILTER:
  2030. error = ERROR_NOT_SUPPORTED;
  2031. break;
  2032. case INTERNET_OPTION_REQUEST_PRIORITY:
  2033. if (handleType == TypeHttpRequestHandle) {
  2034. if (dwBufferLength == sizeof(LONG)) {
  2035. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  2036. SetPriority(*(LPLONG)lpBuffer);
  2037. } else {
  2038. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2039. }
  2040. } else {
  2041. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2042. }
  2043. break;
  2044. case INTERNET_OPTION_HTTP_VERSION:
  2045. if (dwBufferLength == sizeof(HTTP_VERSION_INFO)) {
  2046. HttpVersionInfo = *(LPHTTP_VERSION_INFO)lpBuffer;
  2047. } else {
  2048. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2049. }
  2050. break;
  2051. case INTERNET_OPTION_ERROR_MASK:
  2052. lphRequest = (INTERNET_CONNECT_HANDLE_OBJECT *)hInternet;
  2053. if (dwBufferLength == sizeof(DWORD)) {
  2054. if ( *((LPDWORD) lpBuffer) & ~(INTERNET_ERROR_MASK_INSERT_CDROM |
  2055. INTERNET_ERROR_MASK_COMBINED_SEC_CERT |
  2056. INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY)) {
  2057. error = ERROR_INVALID_PARAMETER;
  2058. } else {
  2059. lphRequest->SetErrorMask(*(LPDWORD) lpBuffer);
  2060. }
  2061. } else {
  2062. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2063. }
  2064. break;
  2065. case INTERNET_OPTION_CODEPAGE:
  2066. if (handleType == TypeHttpRequestHandle) {
  2067. if (dwBufferLength == sizeof(DWORD)) {
  2068. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  2069. SetCodePage(*(LPDWORD)lpBuffer);
  2070. } else {
  2071. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2072. }
  2073. } else {
  2074. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2075. }
  2076. break;
  2077. case INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY:
  2078. if (!GlobalSendUTF8ServerToProxy)
  2079. {
  2080. error = ERROR_INTERNET_INVALID_OPTION;
  2081. }
  2082. else if (handleType != TypeHttpRequestHandle)
  2083. {
  2084. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2085. }
  2086. else if (dwBufferLength != sizeof(DWORD))
  2087. {
  2088. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2089. }
  2090. else
  2091. {
  2092. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  2093. SetSendUTF8ServerNameToProxy(*(LPDWORD)lpBuffer);
  2094. }
  2095. break;
  2096. case INTERNET_OPTION_DISABLE_AUTODIAL:
  2097. if (dwBufferLength == sizeof(DWORD)) {
  2098. DWORD dwValue = *(LPDWORD)lpBuffer;
  2099. SetAutodialEnable(dwValue == 0);
  2100. } else {
  2101. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2102. }
  2103. break;
  2104. case INTERNET_OPTION_AUTODIAL_MODE:
  2105. if(dwBufferLength == sizeof(DWORD))
  2106. {
  2107. SetAutodialMode(*(LPDWORD)lpBuffer);
  2108. }
  2109. else
  2110. {
  2111. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2112. }
  2113. break;
  2114. case INTERNET_OPTION_AUTODIAL_CONNECTION:
  2115. if(dwBufferLength > 0)
  2116. {
  2117. SetAutodialConnection((LPSTR)lpBuffer);
  2118. }
  2119. else
  2120. {
  2121. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2122. }
  2123. break;
  2124. // Override to disable NTLM preauth.
  2125. case INTERNET_OPTION_DISABLE_NTLM_PREAUTH:
  2126. if (handleType == TypeHttpRequestHandle) {
  2127. if (dwBufferLength == sizeof(DWORD)) {
  2128. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->
  2129. SetDisableNTLMPreauth(*(LPDWORD)lpBuffer);
  2130. } else {
  2131. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2132. }
  2133. } else {
  2134. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2135. }
  2136. break;
  2137. case INTERNET_OPTION_MAX_CONNS_PER_SERVER:
  2138. if (dwBufferLength == sizeof(DWORD)) {
  2139. DWORD dwValue = *(LPDWORD)lpBuffer;
  2140. if( !hInternet )
  2141. {
  2142. GlobalMaxConnectionsPerServer = dwValue;
  2143. // begin a-thkesa:
  2144. // Using NULL should affect the whole process.
  2145. // As per the bug, its not affecting the visited sites.
  2146. // so browse through the server info and set the new limits to all server.
  2147. // WindSE BUG: 243039 & Windows 612742
  2148. CServerInfo * lpServerInfo;
  2149. LockSerializedList(&GlobalServerInfoList);
  2150. for (lpServerInfo = (CServerInfo *)HeadOfSerializedList(&GlobalServerInfoList);
  2151. lpServerInfo != (CServerInfo *)SlSelf(&GlobalServerInfoList);
  2152. lpServerInfo = lpServerInfo->Next())
  2153. {
  2154. lpServerInfo->SetNewLimit(dwValue);
  2155. }
  2156. UnlockSerializedList(&GlobalServerInfoList);
  2157. //end: a-thkesa.
  2158. }
  2159. else
  2160. error = ERROR_INTERNET_INVALID_OPERATION;
  2161. } else {
  2162. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2163. }
  2164. break;
  2165. break;
  2166. case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER:
  2167. if (dwBufferLength == sizeof(DWORD)) {
  2168. DWORD dwValue = *(LPDWORD)lpBuffer;
  2169. if( !hInternet )
  2170. {
  2171. GlobalMaxConnectionsPer1_0Server = dwValue;
  2172. // begin a-thkesa:
  2173. // Using NULL should affect the whole process.
  2174. // As per the bug, its not affecting the visited sites.
  2175. // so browse through the server info and set the new limits to all server.
  2176. // WindSE BUG: 243039 & Windows 612742
  2177. CServerInfo * lpServerInfo;
  2178. LockSerializedList(&GlobalServerInfoList);
  2179. for (lpServerInfo = (CServerInfo *)HeadOfSerializedList(&GlobalServerInfoList);
  2180. lpServerInfo != (CServerInfo *)SlSelf(&GlobalServerInfoList);
  2181. lpServerInfo = lpServerInfo->Next())
  2182. {
  2183. lpServerInfo->SetNewLimit(dwValue);
  2184. }
  2185. UnlockSerializedList(&GlobalServerInfoList);
  2186. //end: a-thkesa.
  2187. }
  2188. else
  2189. error = ERROR_INTERNET_INVALID_OPERATION;
  2190. } else {
  2191. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2192. }
  2193. break;
  2194. case INTERNET_OPTION_PER_CONNECTION_OPTION:
  2195. {
  2196. if (handleType != TypeInternetHandle) {
  2197. hInternet = NULL;
  2198. }
  2199. error = SetPerConnOptions(hInternet,
  2200. lpThreadInfo? lpThreadInfo->IsAutoProxyProxyThread : FALSE,
  2201. (LPINTERNET_PER_CONN_OPTION_LIST)lpBuffer);
  2202. break;
  2203. }
  2204. case INTERNET_OPTION_IGNORE_OFFLINE:
  2205. if (handleType == TypeHttpRequestHandle) {
  2206. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->SetIgnoreOffline();
  2207. } else {
  2208. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2209. }
  2210. break;
  2211. case INTERNET_OPTION_IDENTITY:
  2212. if (dwBufferLength==sizeof(IUserIdentity2 *))
  2213. {
  2214. error = ERROR_INVALID_PARAMETER;
  2215. }
  2216. else if (dwBufferLength==sizeof(GUID))
  2217. {
  2218. error = SwitchIdentity((GUID*)lpBuffer);
  2219. }
  2220. else
  2221. {
  2222. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2223. }
  2224. break;
  2225. case INTERNET_OPTION_REMOVE_IDENTITY:
  2226. if (dwBufferLength==sizeof(GUID))
  2227. {
  2228. error = RemoveIdentity((GUID*)lpBuffer);
  2229. }
  2230. else
  2231. {
  2232. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2233. }
  2234. break;
  2235. case INTERNET_OPTION_ALTER_IDENTITY:
  2236. if (dwBufferLength==sizeof(DWORD))
  2237. {
  2238. error = AlterIdentity(*(LPDWORD)lpBuffer);
  2239. }
  2240. else
  2241. {
  2242. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2243. }
  2244. break;
  2245. case INTERNET_OPTION_SUPPRESS_BEHAVIOR:
  2246. if (dwBufferLength==sizeof(DWORD))
  2247. {
  2248. error = ERROR_SUCCESS;
  2249. switch (*(LPDWORD)lpBuffer)
  2250. {
  2251. case INTERNET_SUPPRESS_RESET_ALL:
  2252. GlobalSuppressCookiesPolicy = FALSE;
  2253. break;
  2254. case INTERNET_SUPPRESS_COOKIE_POLICY:
  2255. GlobalSuppressCookiesPolicy = TRUE;
  2256. break;
  2257. case INTERNET_SUPPRESS_COOKIE_POLICY_RESET:
  2258. GlobalSuppressCookiesPolicy = FALSE;
  2259. break;
  2260. default:
  2261. error = ERROR_INVALID_PARAMETER;
  2262. break;
  2263. }
  2264. }
  2265. else
  2266. {
  2267. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2268. }
  2269. break;
  2270. case INTERNET_OPTION_COOKIES_3RD_PARTY:
  2271. if(handleType == TypeHttpRequestHandle)
  2272. {
  2273. if(sizeof(DWORD) == dwBufferLength)
  2274. {
  2275. BOOL f3rdParty = *(BOOL *)lpBuffer;
  2276. ((HTTP_REQUEST_HANDLE_OBJECT *)hInternet)->Set3rdPartyCookies(f3rdParty);
  2277. }
  2278. else
  2279. {
  2280. error = ERROR_INTERNET_BAD_OPTION_LENGTH;
  2281. }
  2282. }
  2283. else
  2284. {
  2285. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2286. }
  2287. break;
  2288. case INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH:
  2289. if (handleType != TypeHttpRequestHandle)
  2290. {
  2291. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  2292. }
  2293. else if (dwBufferLength < sizeof(DWORD))
  2294. {
  2295. error = ERROR_INSUFFICIENT_BUFFER;
  2296. }
  2297. else
  2298. {
  2299. HTTP_REQUEST_HANDLE_OBJECT *lphHttpRqst;
  2300. lphHttpRqst = (HTTP_REQUEST_HANDLE_OBJECT *) hInternet;
  2301. lphHttpRqst->SetSocketSendBufferLength(*(LPDWORD)lpBuffer);
  2302. error = ERROR_SUCCESS;
  2303. }
  2304. break;
  2305. #if INET_DEBUG
  2306. case INTERNET_OPTION_SET_DEBUG_INFO:
  2307. error = InternetSetDebugInfo((LPINTERNET_DEBUG_INFO)lpBuffer,
  2308. dwBufferLength
  2309. );
  2310. break;
  2311. #endif // INET_DEBUG
  2312. default:
  2313. //
  2314. // this option is not recognized
  2315. //
  2316. error = ERROR_INTERNET_INVALID_OPTION;
  2317. }
  2318. quit:
  2319. //AuthUnlock();
  2320. if (hObjectMapped != NULL) {
  2321. DereferenceObject((LPVOID)hObjectMapped);
  2322. }
  2323. done:
  2324. if (error != ERROR_SUCCESS) {
  2325. DEBUG_ERROR(API, error);
  2326. SetLastError(error);
  2327. success = FALSE;
  2328. }
  2329. DEBUG_LEAVE_API(success);
  2330. return success;
  2331. }
  2332. INTERNETAPI_(BOOL) InternetSetOptionW(
  2333. IN HINTERNET hInternet OPTIONAL,
  2334. IN DWORD dwOption,
  2335. IN LPVOID lpBuffer,
  2336. IN DWORD dwBufferLength
  2337. )
  2338. /*++
  2339. Routine Description:
  2340. description-of-function.
  2341. Arguments:
  2342. hInternet -
  2343. dwOption -
  2344. lpBuffer -
  2345. dwBufferLength -
  2346. Return Value:
  2347. BOOL
  2348. --*/
  2349. {
  2350. DEBUG_ENTER_API((DBG_API,
  2351. Bool,
  2352. "InternetSetOptionW",
  2353. "%#x, %s (%d), %#x [%#x], %d",
  2354. hInternet,
  2355. InternetMapOption(dwOption),
  2356. dwOption,
  2357. lpBuffer,
  2358. lpBuffer
  2359. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  2360. ? *(LPDWORD)lpBuffer
  2361. : 0)
  2362. : 0,
  2363. dwBufferLength
  2364. ));
  2365. DWORD dwErr = ERROR_SUCCESS;
  2366. MEMORYPACKET mpBuffer;
  2367. BOOL fResult = FALSE;
  2368. switch (dwOption)
  2369. {
  2370. case INTERNET_OPTION_USERNAME:
  2371. case INTERNET_OPTION_PASSWORD:
  2372. case INTERNET_OPTION_DATAFILE_NAME:
  2373. case INTERNET_OPTION_URL:
  2374. case INTERNET_OPTION_USER_AGENT:
  2375. case INTERNET_OPTION_PROXY_USERNAME:
  2376. case INTERNET_OPTION_PROXY_PASSWORD:
  2377. case INTERNET_OPTION_SECONDARY_CACHE_KEY:
  2378. case INTERNET_OPTION_AUTODIAL_CONNECTION:
  2379. ALLOC_MB((LPWSTR)lpBuffer, dwBufferLength, mpBuffer);
  2380. if (!mpBuffer.psStr)
  2381. {
  2382. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2383. goto cleanup;
  2384. }
  2385. UNICODE_TO_ANSI((LPWSTR)lpBuffer, mpBuffer);
  2386. fResult = InternetSetOptionA(hInternet,
  2387. dwOption,
  2388. mpBuffer.psStr,
  2389. mpBuffer.dwSize
  2390. );
  2391. break;
  2392. case INTERNET_OPTION_PER_CONNECTION_OPTION:
  2393. {
  2394. if (!lpBuffer)
  2395. {
  2396. dwErr = ERROR_INVALID_PARAMETER;
  2397. goto cleanup;
  2398. }
  2399. INTERNET_PER_CONN_OPTION_LISTA listA;
  2400. LPINTERNET_PER_CONN_OPTION_LISTW plistW = (LPINTERNET_PER_CONN_OPTION_LISTW)lpBuffer;
  2401. CHAR szEntryA[RAS_MaxEntryName + 1];
  2402. listA.pszConnection = szEntryA;
  2403. InitIPCOList(plistW, &listA);
  2404. listA.pOptions = (LPINTERNET_PER_CONN_OPTIONA)_alloca(sizeof(INTERNET_PER_CONN_OPTIONA)*listA.dwOptionCount);
  2405. for (DWORD i=0; i<listA.dwOptionCount; i++)
  2406. {
  2407. listA.pOptions[i].dwOption = plistW->pOptions[i].dwOption;
  2408. switch (listA.pOptions[i].dwOption)
  2409. {
  2410. case INTERNET_PER_CONN_FLAGS:
  2411. case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
  2412. case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
  2413. listA.pOptions[i].Value.dwValue = plistW->pOptions[i].Value.dwValue;
  2414. break;
  2415. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
  2416. listA.pOptions[i].Value.ftValue = plistW->pOptions[i].Value.ftValue;
  2417. break;
  2418. case INTERNET_PER_CONN_PROXY_SERVER:
  2419. case INTERNET_PER_CONN_PROXY_BYPASS:
  2420. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  2421. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  2422. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  2423. if (plistW->pOptions[i].Value.pszValue && *plistW->pOptions[i].Value.pszValue)
  2424. {
  2425. // ** WARNING ** NO UTF8 ENCODING HERE
  2426. DWORD cb = WideCharToMultiByte(CP_ACP,
  2427. 0,
  2428. plistW->pOptions[i].Value.pszValue,
  2429. -1,
  2430. 0,
  2431. 0,
  2432. NULL,
  2433. NULL);
  2434. listA.pOptions[i].Value.pszValue = (PSTR)_alloca(cb);
  2435. WideCharToMultiByte(CP_ACP,
  2436. 0,
  2437. plistW->pOptions[i].Value.pszValue,
  2438. -1,
  2439. listA.pOptions[i].Value.pszValue,
  2440. cb,
  2441. NULL,
  2442. NULL);
  2443. }
  2444. else
  2445. {
  2446. listA.pOptions[i].Value.pszValue = NULL;
  2447. }
  2448. break;
  2449. default:
  2450. dwErr = ERROR_INVALID_PARAMETER;
  2451. goto cleanup;
  2452. break;
  2453. }
  2454. }
  2455. fResult = InternetSetOptionA(hInternet,
  2456. dwOption,
  2457. (PVOID)&listA,
  2458. dwBufferLength);
  2459. plistW->dwOptionError = listA.dwOptionError;
  2460. }
  2461. break;
  2462. default:
  2463. fResult = InternetSetOptionA(hInternet,
  2464. dwOption,
  2465. lpBuffer,
  2466. dwBufferLength
  2467. );
  2468. }
  2469. cleanup:
  2470. if (dwErr!=ERROR_SUCCESS)
  2471. {
  2472. SetLastError(dwErr);
  2473. DEBUG_ERROR(INET, dwErr);
  2474. }
  2475. DEBUG_LEAVE_API(fResult);
  2476. return fResult;
  2477. }
  2478. INTERNETAPI_(BOOL) InternetSetOptionExA(
  2479. IN HINTERNET hInternet OPTIONAL,
  2480. IN DWORD dwOption,
  2481. IN LPVOID lpBuffer,
  2482. IN DWORD dwBufferLength,
  2483. IN DWORD dwFlags
  2484. )
  2485. /*++
  2486. Routine Description:
  2487. Sets a handle-specific variable, or a per-thread variable
  2488. Arguments:
  2489. hInternet - handle of object for which information will be set,
  2490. or NULL if the option defines a per-thread variable
  2491. dwOption - the handle-specific INTERNET_OPTION to set
  2492. lpBuffer - pointer to a buffer containing value to set
  2493. dwBufferLength - size of lpBuffer
  2494. dwFlags - flags controlling operation. Possible values are:
  2495. ISO_GLOBAL - set this option globally. The
  2496. shared Wininet data segment will
  2497. be updated with this value
  2498. ISO_REGISTRY - this value will be written to the
  2499. registry for the corresponding
  2500. entry
  2501. Return Value:
  2502. BOOL
  2503. Success - TRUE
  2504. Failure - FALSE. Call GetLastError() for more info:
  2505. ERROR_INVALID_HANDLE
  2506. hInternet does not identify a valid Internet handle
  2507. object
  2508. ERROR_INTERNET_INTERNAL_ERROR
  2509. Shouldn't see this?
  2510. ERROR_INVALID_PARAMETER
  2511. One of the parameters was bad
  2512. ERROR_INTERNET_INVALID_OPTION
  2513. The requested option cannot be set
  2514. ERROR_INTERNET_OPTION_NOT_SETTABLE
  2515. Can't set this option, only query it
  2516. ERROR_INTERNET_BAD_OPTION_LENGTH
  2517. The dwBufferLength parameter is incorrect for the
  2518. expected type of the option
  2519. --*/
  2520. {
  2521. DEBUG_ENTER_API((DBG_API,
  2522. Bool,
  2523. "InternetSetOptionExA",
  2524. "%#x, %s (%d), %#x [%#x], %d, %#x",
  2525. hInternet,
  2526. InternetMapOption(dwOption),
  2527. dwOption,
  2528. lpBuffer,
  2529. lpBuffer
  2530. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  2531. ? *(LPDWORD)lpBuffer
  2532. : 0)
  2533. : 0,
  2534. dwBufferLength,
  2535. dwFlags
  2536. ));
  2537. BOOL success;
  2538. //
  2539. // validate parameters
  2540. //
  2541. //
  2542. // currently, dwFlags MBZ
  2543. //
  2544. if (dwFlags == 0) {
  2545. success = InternetSetOptionA(hInternet,
  2546. dwOption,
  2547. lpBuffer,
  2548. dwBufferLength
  2549. );
  2550. } else {
  2551. DEBUG_ERROR(INET, ERROR_INVALID_PARAMETER);
  2552. SetLastError(ERROR_INVALID_PARAMETER);
  2553. success = FALSE;
  2554. }
  2555. DEBUG_LEAVE_API(success);
  2556. return success;
  2557. }
  2558. INTERNETAPI_(BOOL) InternetSetOptionExW(
  2559. IN HINTERNET hInternet OPTIONAL,
  2560. IN DWORD dwOption,
  2561. IN LPVOID lpBuffer,
  2562. IN DWORD dwBufferLength,
  2563. IN DWORD dwFlags
  2564. )
  2565. /*++
  2566. Routine Description:
  2567. description-of-function.
  2568. Arguments:
  2569. hInternet -
  2570. dwOption -
  2571. lpBuffer -
  2572. dwBufferLength -
  2573. dwFlags -
  2574. Return Value:
  2575. BOOL
  2576. --*/
  2577. {
  2578. DEBUG_ENTER_API((DBG_API,
  2579. Bool,
  2580. "InternetSetOptionExW",
  2581. "%#x, %s (%d), %#x [%#x], %d, %#x",
  2582. hInternet,
  2583. InternetMapOption(dwOption),
  2584. dwOption,
  2585. lpBuffer,
  2586. lpBuffer
  2587. ? (!IsBadReadPtr(lpBuffer, sizeof(DWORD))
  2588. ? *(LPDWORD)lpBuffer
  2589. : 0)
  2590. : 0,
  2591. dwBufferLength,
  2592. dwFlags
  2593. ));
  2594. BOOL fResult = FALSE;
  2595. if (dwFlags)
  2596. {
  2597. DEBUG_ERROR(INET, ERROR_INVALID_PARAMETER);
  2598. SetLastError(ERROR_INVALID_PARAMETER);
  2599. }
  2600. else
  2601. {
  2602. fResult = InternetSetOptionW(hInternet,
  2603. dwOption,
  2604. lpBuffer,
  2605. dwBufferLength
  2606. );
  2607. }
  2608. DEBUG_LEAVE_API(fResult);
  2609. return fResult;
  2610. }
  2611. PRIVATE
  2612. BOOL
  2613. FValidCacheHandleType(
  2614. HINTERNET_HANDLE_TYPE hType
  2615. )
  2616. {
  2617. return ((hType != TypeInternetHandle) &&
  2618. (hType != TypeFtpConnectHandle) &&
  2619. (hType != TypeGopherConnectHandle) &&
  2620. (hType != TypeFileRequestHandle) &&
  2621. (hType != TypeHttpConnectHandle));
  2622. }