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.

978 lines
26 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. inetapiw.cxx
  5. Abstract:
  6. Contains the wide-character Internet APIs
  7. Contents:
  8. WinHttpCrackUrl
  9. WinHttpCreateUrl
  10. WinHttpOpen
  11. WinHttpConnect
  12. WinHttpSetStatusCallback
  13. Author:
  14. Richard L Firth (rfirth) 02-Mar-1995
  15. Environment:
  16. Win32(s) user-mode DLL
  17. Revision History:
  18. 02-Mar-1995 rfirth
  19. Created
  20. --*/
  21. #include <wininetp.h>
  22. // because wininet doesnt know about IStream
  23. #define NO_SHLWAPI_STREAM
  24. #include <shlwapi.h>
  25. #include <shlwapip.h>
  26. // -- FixStrings ------
  27. // Used in WinHttpCrackUrlW only.
  28. // Either
  29. // (a) If we have an ansi string, AND a unicode buffer, convert from ansi to unicode
  30. // (b) If we have an ansi string, but NO unicode buffer, determine where the ansi string
  31. // occurs in the unicode URL, and point the component there.
  32. VOID
  33. FixStrings(
  34. LPSTR& pszA,
  35. DWORD cbA,
  36. LPWSTR& pszW,
  37. DWORD& ccW,
  38. LPSTR pszUrlA,
  39. LPCWSTR pszUrlW)
  40. {
  41. if (!pszA)
  42. return;
  43. if (pszW)
  44. {
  45. ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA+1, pszW, ccW) - 1;
  46. }
  47. else
  48. {
  49. pszW = (LPWSTR)(pszUrlW + MultiByteToWideChar(CP_ACP, 0,
  50. pszUrlA, (int) (pszA-pszUrlA), NULL, 0));
  51. ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA, NULL, 0);
  52. }
  53. }
  54. //
  55. // functions
  56. //
  57. INTERNETAPI
  58. BOOL
  59. WINAPI
  60. WinHttpCrackUrl(
  61. IN LPCWSTR pszUrlW,
  62. IN DWORD dwUrlLengthW,
  63. IN DWORD dwFlags,
  64. IN OUT LPURL_COMPONENTSW pUCW
  65. )
  66. /*++
  67. Routine Description:
  68. Cracks an URL into its constituent parts. Optionally escapes the url-path.
  69. We assume that the user has supplied large enough buffers for the various
  70. URL parts
  71. Arguments:
  72. pszUrl - pointer to URL to crack
  73. dwUrlLength - 0 if pszUrl is ASCIIZ string, else length of pszUrl
  74. dwFlags - flags controlling operation
  75. lpUrlComponents - pointer to URL_COMPONENTS
  76. Return Value:
  77. BOOL
  78. Success - TRUE
  79. Failure - FALSE. Call GetLastError() for more info
  80. --*/
  81. {
  82. DEBUG_ENTER_API((DBG_API,
  83. Bool,
  84. "WinHttpCrackUrl",
  85. "%wq, %#x, %#x, %#x",
  86. pszUrlW,
  87. dwUrlLengthW,
  88. dwFlags,
  89. pUCW
  90. ));
  91. INET_ASSERT(pszUrlW);
  92. INET_ASSERT(pUCW);
  93. DWORD dwErr = ERROR_SUCCESS;
  94. BOOL fResult = FALSE;
  95. BOOL fContinue;
  96. DWORD c;
  97. MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
  98. URL_COMPONENTSA UCA;
  99. if (!pszUrlW
  100. || (dwUrlLengthW
  101. ? IsBadStringPtrW(pszUrlW,-1)
  102. : IsBadReadPtr(pszUrlW,dwUrlLengthW))
  103. || !pUCW
  104. || IsBadWritePtr(pUCW, sizeof(*pUCW))
  105. || (pUCW->dwStructSize != sizeof(*pUCW))
  106. || (dwFlags & ~(ICU_ESCAPE | ICU_DECODE)))
  107. {
  108. dwErr = ERROR_INVALID_PARAMETER;
  109. goto cleanup;
  110. }
  111. UCA.dwStructSize = sizeof(URL_COMPONENTSA);
  112. ALLOC_MB(pszUrlW, dwUrlLengthW, mpUrlA);
  113. if (!mpUrlA.psStr) {
  114. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  115. goto cleanup;
  116. }
  117. UNICODE_TO_ANSI(pszUrlW, mpUrlA);
  118. for (c=0; c<=5; c++) {
  119. LPWSTR pszWorker;
  120. DWORD ccLen;
  121. MEMORYPACKET* pmpWorker;
  122. switch(c)
  123. {
  124. case 0:
  125. pszWorker = pUCW->lpszScheme;
  126. ccLen = pUCW->dwSchemeLength;
  127. pmpWorker = &mpScheme;
  128. break;
  129. case 1:
  130. pszWorker = pUCW->lpszHostName;
  131. ccLen = pUCW->dwHostNameLength;
  132. pmpWorker = &mpHostName;
  133. break;
  134. case 2:
  135. pszWorker = pUCW->lpszUserName;
  136. ccLen = pUCW->dwUserNameLength;
  137. pmpWorker = &mpUserName;
  138. break;
  139. case 3:
  140. pszWorker = pUCW->lpszPassword;
  141. ccLen = pUCW->dwPasswordLength;
  142. pmpWorker = &mpPassword;
  143. break;
  144. case 4:
  145. pszWorker = pUCW->lpszUrlPath;
  146. ccLen = pUCW->dwUrlPathLength;
  147. pmpWorker = &mpUrlPath;
  148. break;
  149. case 5:
  150. pszWorker = pUCW->lpszExtraInfo;
  151. ccLen = pUCW->dwExtraInfoLength;
  152. pmpWorker = &mpExtraInfo;
  153. break;
  154. }
  155. if (pszWorker)
  156. {
  157. if (pszWorker
  158. && ccLen
  159. && (ProbeWriteBuffer(pszWorker,ccLen) != ERROR_SUCCESS) )
  160. {
  161. dwErr = ERROR_INVALID_PARAMETER;
  162. goto cleanup;
  163. }
  164. ALLOC_MB(pszWorker,ccLen,(*pmpWorker));
  165. if (!pmpWorker->psStr)
  166. {
  167. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  168. goto cleanup;
  169. }
  170. }
  171. else
  172. {
  173. pmpWorker->dwAlloc = ccLen;
  174. }
  175. };
  176. REASSIGN_ALLOC(mpScheme,UCA.lpszScheme,UCA.dwSchemeLength);
  177. REASSIGN_ALLOC(mpHostName, UCA.lpszHostName,UCA.dwHostNameLength);
  178. REASSIGN_ALLOC(mpUserName, UCA.lpszUserName,UCA.dwUserNameLength);
  179. REASSIGN_ALLOC(mpPassword,UCA.lpszPassword,UCA.dwPasswordLength);
  180. REASSIGN_ALLOC(mpUrlPath,UCA.lpszUrlPath,UCA.dwUrlPathLength);
  181. REASSIGN_ALLOC(mpExtraInfo,UCA.lpszExtraInfo,UCA.dwExtraInfoLength);
  182. fResult = WinHttpCrackUrlA(mpUrlA.psStr, mpUrlA.dwSize, dwFlags, &UCA);
  183. if (fResult) {
  184. FixStrings(UCA.lpszScheme, UCA.dwSchemeLength, pUCW->lpszScheme,
  185. pUCW->dwSchemeLength, mpUrlA.psStr, pszUrlW);
  186. FixStrings(UCA.lpszHostName, UCA.dwHostNameLength, pUCW->lpszHostName,
  187. pUCW->dwHostNameLength, mpUrlA.psStr, pszUrlW);
  188. FixStrings(UCA.lpszUserName, UCA.dwUserNameLength, pUCW->lpszUserName,
  189. pUCW->dwUserNameLength, mpUrlA.psStr, pszUrlW);
  190. FixStrings(UCA.lpszPassword, UCA.dwPasswordLength, pUCW->lpszPassword,
  191. pUCW->dwPasswordLength, mpUrlA.psStr, pszUrlW);
  192. FixStrings(UCA.lpszUrlPath, UCA.dwUrlPathLength, pUCW->lpszUrlPath,
  193. pUCW->dwUrlPathLength, mpUrlA.psStr, pszUrlW);
  194. FixStrings(UCA.lpszExtraInfo, UCA.dwExtraInfoLength, pUCW->lpszExtraInfo,
  195. pUCW->dwExtraInfoLength, mpUrlA.psStr, pszUrlW);
  196. pUCW->nScheme = UCA.nScheme;
  197. pUCW->nPort = UCA.nPort;
  198. pUCW->dwStructSize = sizeof(URL_COMPONENTSW);
  199. }
  200. cleanup:
  201. if (dwErr!=ERROR_SUCCESS) {
  202. SetLastError(dwErr);
  203. DEBUG_ERROR(API, dwErr);
  204. }
  205. DEBUG_LEAVE_API(fResult);
  206. return fResult;
  207. }
  208. INTERNETAPI
  209. BOOL
  210. WINAPI
  211. WinHttpCreateUrl(
  212. IN LPURL_COMPONENTSW pUCW,
  213. IN DWORD dwFlags,
  214. OUT LPWSTR pszUrlW,
  215. IN OUT LPDWORD pdwUrlLengthW
  216. )
  217. /*++
  218. Routine Description:
  219. Creates an URL from its constituent parts
  220. Arguments:
  221. Return Value:
  222. BOOL
  223. Success - URL written to pszUrl
  224. Failure - call GetLastError() for more info
  225. --*/
  226. {
  227. DEBUG_ENTER_API((DBG_API,
  228. Bool,
  229. "WinHttpCreateUrl",
  230. "%#x, %#x, %#x, %#x",
  231. pUCW,
  232. dwFlags,
  233. pszUrlW,
  234. pdwUrlLengthW
  235. ));
  236. INET_ASSERT(pszUrlW);
  237. INET_ASSERT(pUCW);
  238. DWORD dwErr = ERROR_SUCCESS;
  239. BOOL fResult = FALSE;
  240. MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
  241. URL_COMPONENTSA UCA;
  242. if (!pdwUrlLengthW
  243. || (pUCW==NULL)
  244. || IsBadWritePtr(pUCW, sizeof(*pUCW))
  245. || (pUCW->dwStructSize != sizeof(*pUCW))
  246. || (pszUrlW && IsBadWritePtr(pszUrlW, *pdwUrlLengthW*sizeof(WCHAR)))
  247. || (dwFlags & ~(ICU_ESCAPE)))
  248. {
  249. dwErr = ERROR_INVALID_PARAMETER;
  250. goto cleanup;
  251. }
  252. if (pszUrlW)
  253. {
  254. ALLOC_MB(pszUrlW, *pdwUrlLengthW, mpUrlA);
  255. if (!mpUrlA.psStr)
  256. {
  257. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  258. goto cleanup;
  259. }
  260. }
  261. mpUrlA.dwSize = mpUrlA.dwAlloc;
  262. UCA.dwStructSize = sizeof(URL_COMPONENTSA);
  263. UCA.nScheme = pUCW->nScheme;
  264. UCA.nPort = pUCW->nPort;
  265. if (pUCW->lpszScheme)
  266. {
  267. if (pUCW->dwSchemeLength
  268. ? IsBadReadPtr(pUCW->lpszScheme, pUCW->dwSchemeLength)
  269. : IsBadStringPtrW(pUCW->lpszScheme, -1))
  270. {
  271. dwErr = ERROR_INVALID_PARAMETER;
  272. goto cleanup;
  273. }
  274. ALLOC_MB(pUCW->lpszScheme, pUCW->dwSchemeLength, mpScheme);
  275. if (!mpScheme.psStr)
  276. {
  277. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  278. goto cleanup;
  279. }
  280. UNICODE_TO_ANSI(pUCW->lpszScheme, mpScheme);
  281. }
  282. REASSIGN_SIZE(mpScheme, UCA.lpszScheme, UCA.dwSchemeLength);
  283. if (pUCW->lpszHostName)
  284. {
  285. if (pUCW->dwHostNameLength
  286. ? IsBadReadPtr(pUCW->lpszHostName, pUCW->dwHostNameLength)
  287. : IsBadStringPtrW(pUCW->lpszHostName, -1))
  288. {
  289. dwErr = ERROR_INVALID_PARAMETER;
  290. goto cleanup;
  291. }
  292. ALLOC_MB(pUCW->lpszHostName, pUCW->dwHostNameLength, mpHostName);
  293. if (!mpHostName.psStr)
  294. {
  295. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  296. goto cleanup;
  297. }
  298. UNICODE_TO_ANSI(pUCW->lpszHostName, mpHostName);
  299. }
  300. REASSIGN_SIZE(mpHostName, UCA.lpszHostName, UCA.dwHostNameLength);
  301. if (pUCW->lpszUserName)
  302. {
  303. if (pUCW->dwUserNameLength
  304. ? IsBadReadPtr(pUCW->lpszUserName, pUCW->dwUserNameLength)
  305. : IsBadStringPtrW(pUCW->lpszUserName, -1))
  306. {
  307. dwErr = ERROR_INVALID_PARAMETER;
  308. goto cleanup;
  309. }
  310. ALLOC_MB(pUCW->lpszUserName, pUCW->dwUserNameLength, mpUserName);
  311. if (!mpUserName.psStr)
  312. {
  313. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  314. goto cleanup;
  315. }
  316. UNICODE_TO_ANSI(pUCW->lpszUserName, mpUserName);
  317. }
  318. REASSIGN_SIZE(mpUserName, UCA.lpszUserName, UCA.dwUserNameLength);
  319. if (pUCW->lpszPassword)
  320. {
  321. if (pUCW->dwPasswordLength
  322. ? IsBadReadPtr(pUCW->lpszPassword, pUCW->dwPasswordLength)
  323. : IsBadStringPtrW(pUCW->lpszPassword, -1))
  324. {
  325. dwErr = ERROR_INVALID_PARAMETER;
  326. goto cleanup;
  327. }
  328. ALLOC_MB(pUCW->lpszPassword, pUCW->dwPasswordLength, mpPassword);
  329. if (!mpPassword.psStr)
  330. {
  331. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  332. goto cleanup;
  333. }
  334. UNICODE_TO_ANSI(pUCW->lpszPassword, mpPassword);
  335. }
  336. REASSIGN_SIZE(mpPassword, UCA.lpszPassword, UCA.dwPasswordLength);
  337. if (pUCW->lpszUrlPath)
  338. {
  339. if (pUCW->dwUrlPathLength
  340. ? IsBadReadPtr(pUCW->lpszUrlPath, pUCW->dwUrlPathLength)
  341. : IsBadStringPtrW(pUCW->lpszUrlPath, -1))
  342. {
  343. dwErr = ERROR_INVALID_PARAMETER;
  344. goto cleanup;
  345. }
  346. ALLOC_MB(pUCW->lpszUrlPath, pUCW->dwUrlPathLength, mpUrlPath);
  347. if (!mpUrlPath.psStr)
  348. {
  349. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  350. goto cleanup;
  351. }
  352. UNICODE_TO_ANSI(pUCW->lpszUrlPath, mpUrlPath);
  353. }
  354. REASSIGN_SIZE(mpUrlPath, UCA.lpszUrlPath, UCA.dwUrlPathLength);
  355. if (pUCW->lpszExtraInfo)
  356. {
  357. if (pUCW->dwExtraInfoLength
  358. ? IsBadReadPtr(pUCW->lpszExtraInfo, pUCW->dwExtraInfoLength)
  359. : IsBadStringPtrW(pUCW->lpszExtraInfo, -1))
  360. {
  361. dwErr = ERROR_INVALID_PARAMETER;
  362. goto cleanup;
  363. }
  364. ALLOC_MB(pUCW->lpszExtraInfo, pUCW->dwExtraInfoLength, mpExtraInfo);
  365. if (!mpExtraInfo.psStr)
  366. {
  367. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  368. goto cleanup;
  369. }
  370. UNICODE_TO_ANSI(pUCW->lpszExtraInfo, mpExtraInfo);
  371. }
  372. REASSIGN_SIZE(mpExtraInfo, UCA.lpszExtraInfo, UCA.dwExtraInfoLength);
  373. fResult = WinHttpCreateUrlA(&UCA, dwFlags, mpUrlA.psStr, &mpUrlA.dwSize);
  374. if (fResult)
  375. {
  376. DWORD dwRet;
  377. fResult = FALSE;
  378. if (pszUrlW && *pdwUrlLengthW)
  379. {
  380. //On success, reduce length of terminating NULL widechar.
  381. dwRet = MultiByteToWideChar(CP_ACP, 0, mpUrlA.psStr, mpUrlA.dwSize+1, pszUrlW, *pdwUrlLengthW);
  382. if (dwRet)
  383. {
  384. *pdwUrlLengthW = dwRet-1;
  385. fResult = TRUE;
  386. }
  387. }
  388. //If no url or no length or failure in prev. call, use MBtoWC to calculate required length of buffer.
  389. //If a value is returned, then set ERROR_INSUFFICIENT_BUFFER as last error
  390. if (!fResult)
  391. {
  392. dwRet = MultiByteToWideChar(CP_ACP, 0, mpUrlA.psStr, mpUrlA.dwSize+1, pszUrlW, 0);
  393. if (dwRet)
  394. {
  395. dwErr = ERROR_INSUFFICIENT_BUFFER;
  396. *pdwUrlLengthW = dwRet;
  397. }
  398. else
  399. {
  400. dwErr = GetLastError();
  401. //Morph the error since we don't know what to initialize pdwUrlLengthW to
  402. if (dwErr == ERROR_INSUFFICIENT_BUFFER)
  403. {
  404. dwErr = ERROR_INVALID_PARAMETER;
  405. }
  406. }
  407. }
  408. }
  409. else
  410. {
  411. *pdwUrlLengthW = mpUrlA.dwSize;
  412. }
  413. cleanup:
  414. if (dwErr!=ERROR_SUCCESS)
  415. {
  416. SetLastError(dwErr);
  417. DEBUG_ERROR(API, dwErr);
  418. }
  419. DEBUG_LEAVE_API(fResult);
  420. return fResult;
  421. }
  422. // implemented in inetapia.cxx
  423. DWORD ICUHrToWin32Error(HRESULT);
  424. INTERNETAPI
  425. HINTERNET
  426. WINAPI
  427. WinHttpOpen(
  428. IN LPCWSTR pszAgentW,
  429. IN DWORD dwAccessType,
  430. IN LPCWSTR pszProxyW OPTIONAL,
  431. IN LPCWSTR pszProxyBypassW OPTIONAL,
  432. IN DWORD dwFlags
  433. )
  434. /*++
  435. Routine Description:
  436. description-of-function.
  437. Arguments:
  438. pszAgent -
  439. dwAccessType -
  440. pszProxy -
  441. pszProxyBypass -
  442. dwFlags -
  443. Return Value:
  444. HINTERNET
  445. --*/
  446. {
  447. DEBUG_ENTER_API((DBG_API,
  448. Handle,
  449. "WinHttpOpen",
  450. "%wq, %s (%d), %wq, %wq, %#x",
  451. pszAgentW,
  452. InternetMapOpenType(dwAccessType),
  453. dwAccessType,
  454. pszProxyW,
  455. pszProxyBypassW,
  456. dwFlags
  457. ));
  458. DWORD dwErr = ERROR_SUCCESS;
  459. HINTERNET hInternet = NULL;
  460. MEMORYPACKET mpAgentA, mpProxyA, mpProxyBypassA;
  461. if (dwFlags &~ (WINHTTP_OPEN_FLAGS_MASK))
  462. {
  463. dwErr = ERROR_INVALID_PARAMETER;
  464. goto cleanup;
  465. }
  466. if (pszAgentW)
  467. {
  468. if (IsBadStringPtrW(pszAgentW, -1))
  469. {
  470. dwErr = ERROR_INVALID_PARAMETER;
  471. goto cleanup;
  472. }
  473. ALLOC_MB(pszAgentW,0,mpAgentA);
  474. if (!mpAgentA.psStr)
  475. {
  476. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  477. goto cleanup;
  478. }
  479. UNICODE_TO_ANSI(pszAgentW,mpAgentA);
  480. }
  481. if (dwAccessType & WINHTTP_ACCESS_TYPE_NAMED_PROXY)
  482. {
  483. if (pszProxyW)
  484. {
  485. if (IsBadStringPtrW(pszProxyW, -1)
  486. || (*pszProxyW == L'\0'))
  487. {
  488. dwErr = ERROR_INVALID_PARAMETER;
  489. goto cleanup;
  490. }
  491. ALLOC_MB(pszProxyW,0,mpProxyA);
  492. if (!mpProxyA.psStr)
  493. {
  494. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  495. goto cleanup;
  496. }
  497. UNICODE_TO_ANSI(pszProxyW,mpProxyA);
  498. }
  499. if (pszProxyBypassW)
  500. {
  501. if (IsBadStringPtrW(pszProxyBypassW, -1))
  502. {
  503. dwErr = ERROR_INVALID_PARAMETER;
  504. goto cleanup;
  505. }
  506. ALLOC_MB(pszProxyBypassW,0,mpProxyBypassA);
  507. if (!mpProxyBypassA.psStr)
  508. {
  509. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  510. goto cleanup;
  511. }
  512. UNICODE_TO_ANSI(pszProxyBypassW,mpProxyBypassA);
  513. }
  514. }
  515. hInternet = InternetOpenA(mpAgentA.psStr, dwAccessType, mpProxyA.psStr,
  516. mpProxyBypassA.psStr, dwFlags);
  517. cleanup:
  518. if (dwErr!=ERROR_SUCCESS) {
  519. SetLastError(dwErr);
  520. DEBUG_ERROR(API, dwErr);
  521. }
  522. DEBUG_LEAVE_API(hInternet);
  523. return hInternet;
  524. }
  525. INTERNETAPI
  526. HINTERNET
  527. WINAPI
  528. WinHttpConnect(
  529. IN HINTERNET hInternetSession,
  530. IN LPCWSTR pszServerNameW,
  531. IN INTERNET_PORT nServerPort,
  532. IN DWORD dwReserved
  533. )
  534. /*++
  535. Routine Description:
  536. description-of-function.
  537. Arguments:
  538. hInternetSession -
  539. pszServerName -
  540. nServerPort -
  541. pszUserName -
  542. pszPassword -
  543. dwService -
  544. dwReserved -
  545. Return Value:
  546. HINTERNET
  547. --*/
  548. {
  549. DEBUG_ENTER_API((DBG_API,
  550. Handle,
  551. "WinHttpConnect",
  552. "%#x, %wq, %d, %#x",
  553. hInternetSession,
  554. pszServerNameW,
  555. nServerPort,
  556. dwReserved
  557. ));
  558. DWORD dwErr = ERROR_SUCCESS;
  559. MEMORYPACKET mpServerNameA;
  560. HINTERNET hInternet = NULL;
  561. if (dwReserved)
  562. {
  563. dwErr = ERROR_INVALID_PARAMETER;
  564. goto cleanup;
  565. }
  566. if (pszServerNameW)
  567. {
  568. if (IsBadStringPtrW(pszServerNameW,-1))
  569. {
  570. dwErr = ERROR_INVALID_PARAMETER;
  571. goto cleanup;
  572. }
  573. dwErr = ConvertUnicodeToMultiByte(pszServerNameW, 0/*CODEPAGE not used here*/, &mpServerNameA,
  574. WINHTTP_FLAG_VALID_HOSTNAME);
  575. if (dwErr != ERROR_SUCCESS)
  576. {
  577. goto cleanup;
  578. }
  579. }
  580. else
  581. {
  582. dwErr = ERROR_INVALID_PARAMETER;
  583. goto cleanup;
  584. }
  585. hInternet = InternetConnectA
  586. (hInternetSession, mpServerNameA.psStr, nServerPort, dwReserved, NULL);
  587. cleanup:
  588. if (dwErr!=ERROR_SUCCESS) {
  589. SetLastError(dwErr);
  590. DEBUG_ERROR(API, dwErr);
  591. }
  592. DEBUG_LEAVE_API(hInternet);
  593. return hInternet;
  594. }
  595. INTERNETAPI
  596. WINHTTP_STATUS_CALLBACK
  597. WINAPI
  598. WinHttpSetStatusCallback(
  599. IN HINTERNET hInternet,
  600. IN WINHTTP_STATUS_CALLBACK lpfnInternetCallback,
  601. IN DWORD dwNotificationFlags,
  602. IN DWORD_PTR dwReserved
  603. )
  604. /*++
  605. Routine Description:
  606. Sets the status callback function for the DLL or the handle object
  607. Arguments:
  608. hInternet - handle of the object for which we wish to set the
  609. status callback
  610. lpfnInternetCallback - pointer to caller-supplied status function
  611. Return Value:
  612. FARPROC
  613. Success - previous status callback function address
  614. Failure - INTERNET_INVALID_STATUS_CALLBACK. Call GetLastErrorInfo() for
  615. more information:
  616. ERROR_INVALID_PARAMETER
  617. The callback function is invalid
  618. ERROR_WINHTTP_INCORRECT_HANDLE_TYPE
  619. Cannot set the callback on the supplied handle (probably
  620. a NULL handle - per-process callbacks no longer
  621. supported)
  622. --*/
  623. {
  624. DEBUG_ENTER_API((DBG_API,
  625. Pointer,
  626. "WinHttpSetStatusCallback",
  627. "%#x, %#x, %#x",
  628. hInternet,
  629. lpfnInternetCallback,
  630. dwNotificationFlags
  631. ));
  632. DWORD dwErr = ERROR_SUCCESS;
  633. BOOL fIsUnicode = TRUE; //vestigial UNICODE indicator
  634. WINHTTP_STATUS_CALLBACK previousCallback = WINHTTP_INVALID_STATUS_CALLBACK;
  635. HINTERNET hObjectMapped = NULL;
  636. if (!GlobalDataInitialized)
  637. {
  638. dwErr = GlobalDataInitialize();
  639. if (dwErr != ERROR_SUCCESS)
  640. {
  641. goto cleanup;
  642. }
  643. }
  644. if (((lpfnInternetCallback != NULL) && IsBadCodePtr((FARPROC)lpfnInternetCallback))
  645. || (dwNotificationFlags == 0) || (dwReserved != 0))
  646. {
  647. dwErr = ERROR_INVALID_PARAMETER;
  648. goto cleanup;
  649. }
  650. if (!hInternet)
  651. {
  652. dwErr = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  653. goto cleanup;
  654. }
  655. // map the handle
  656. dwErr = MapHandleToAddress(hInternet, (LPVOID *)&hObjectMapped, FALSE);
  657. if (dwErr != ERROR_SUCCESS)
  658. {
  659. goto cleanup;
  660. }
  661. // swap the new and previous handle object status callbacks, ONLY
  662. // if there are no pending requests on this handle
  663. previousCallback = lpfnInternetCallback;
  664. dwErr = RExchangeStatusCallback(hObjectMapped, &previousCallback, fIsUnicode, dwNotificationFlags);
  665. cleanup:
  666. if (hObjectMapped != NULL)
  667. {
  668. DereferenceObject((LPVOID)hObjectMapped);
  669. }
  670. if (dwErr!=ERROR_SUCCESS)
  671. {
  672. SetLastError(dwErr);
  673. DEBUG_ERROR(API, dwErr);
  674. }
  675. DEBUG_LEAVE_API(previousCallback);
  676. return previousCallback;
  677. }
  678. // WinHttpPlatformCheck() API routines //////////////////////////////////////
  679. static void ConvertVersionString(LPCSTR pszVersion, WORD rwVer[], CHAR ch)
  680. {
  681. LPCSTR pszEnd;
  682. LPCSTR pszTemp;
  683. int i;
  684. for (i = 0; i < 4; i++)
  685. rwVer[i] = 0;
  686. pszEnd = pszVersion + lstrlen(pszVersion);
  687. pszTemp = pszVersion;
  688. for (i = 0; i < 4 && pszTemp < pszEnd; i++)
  689. {
  690. while (pszTemp < pszEnd && *pszTemp != ch)
  691. {
  692. rwVer[i] = rwVer[i] * 10 + (*pszTemp - '0');
  693. pszTemp++;
  694. }
  695. pszTemp++;
  696. }
  697. }
  698. const char c_gszRegActiveSetup[] = "Software\\Microsoft\\Active Setup\\Installed Components\\";
  699. const char c_gszInternetExplorerCLSID[] = "{89820200-ECBD-11cf-8B85-00AA005B4383}";
  700. static void GetInstalledComponentVersion(LPCSTR szCLSID, DWORD *pdwMSVer, DWORD *pdwLSVer)
  701. {
  702. HKEY hKey;
  703. char szKey[MAX_PATH];
  704. WORD rgwVersion[4];
  705. DWORD dwSize;
  706. *pdwMSVer = 0;
  707. *pdwLSVer = 0;
  708. // Build the registry path.
  709. lstrcpy(szKey, c_gszRegActiveSetup);
  710. lstrcat(szKey, szCLSID);
  711. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
  712. {
  713. dwSize = sizeof(szKey);
  714. if ((RegQueryValueEx(hKey, "Version", NULL, NULL, (BYTE *)szKey, &dwSize) == ERROR_SUCCESS) &&
  715. (dwSize > 0))
  716. {
  717. ConvertVersionString(szKey, rgwVersion, ',');
  718. *pdwMSVer = (DWORD)rgwVersion[0] << 16; // Make hi word of MS version
  719. *pdwMSVer += (DWORD)rgwVersion[1]; // Make lo word of MS version
  720. *pdwLSVer = (DWORD)rgwVersion[2] << 16; // Make hi word of LS version
  721. *pdwLSVer += (DWORD)rgwVersion[3]; // Make lo word of LS version
  722. }
  723. RegCloseKey(hKey);
  724. }
  725. }
  726. static BOOL Is_IE_501_OrLaterInstalled()
  727. {
  728. DWORD dwMSVer;
  729. DWORD dwLSVer;
  730. //
  731. // Find the IE version number. IE 5.01 has version number 5.00.2919.6300.
  732. // This will be returned from GetInstalledComponentVersion as two DWORDs,
  733. // like so:
  734. // 5.00 -> 0x00050000
  735. // 2919.6300 -> 0x0B67189C
  736. //
  737. GetInstalledComponentVersion(c_gszInternetExplorerCLSID, &dwMSVer, &dwLSVer);
  738. if (dwMSVer > 0x00050000)
  739. return TRUE;
  740. else if ((dwMSVer == 0x00050000) && (dwLSVer >= 0x0B67189C))
  741. return TRUE;
  742. return FALSE;
  743. }
  744. #if 0
  745. #define REGSTR_CCS_CONTROL_WINDOWS TEXT("SYSTEM\\CurrentControlSet\\Control\\WINDOWS")
  746. #define CSDVERSION TEXT("CSDVersion")
  747. #define SP6_VERSION 0x0600
  748. static BOOL Is_SP6_OrLater()
  749. {
  750. BOOL fSP6OrLater = FALSE;
  751. HKEY hKey;
  752. DWORD dwCSDVersion;
  753. DWORD dwSize;
  754. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_CCS_CONTROL_WINDOWS, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
  755. {
  756. dwSize = sizeof(dwCSDVersion);
  757. if (RegQueryValueEx(hKey, CSDVERSION, NULL, NULL, (BYTE *)&dwCSDVersion, &dwSize) == ERROR_SUCCESS)
  758. {
  759. fSP6OrLater = (LOWORD(dwCSDVersion) >= SP6_VERSION);
  760. }
  761. RegCloseKey(hKey);
  762. }
  763. return fSP6OrLater;
  764. }
  765. #endif
  766. INTERNETAPI
  767. BOOL
  768. WINAPI
  769. WinHttpCheckPlatform(void)
  770. {
  771. static BOOL _fCheckedPlatform = FALSE;
  772. static BOOL _fPlatformOk;
  773. if (!_fCheckedPlatform)
  774. {
  775. OSVERSIONINFO osvi;
  776. BOOL fPlatformOk = FALSE;
  777. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  778. if (GetVersionEx(&osvi))
  779. {
  780. // Allow only Win2K or NT-based platforms.
  781. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  782. {
  783. if (osvi.dwMajorVersion >= 5)
  784. {
  785. // Ok on Win2K or later.
  786. fPlatformOk = TRUE;
  787. }
  788. else if (osvi.dwMajorVersion == 4)
  789. {
  790. // On NT4, we require IE 5.01 (or later).
  791. fPlatformOk = Is_IE_501_OrLaterInstalled();
  792. }
  793. }
  794. }
  795. _fPlatformOk = fPlatformOk;
  796. InterlockedExchange((long *)&_fCheckedPlatform, TRUE);
  797. }
  798. return _fPlatformOk;
  799. }