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.

1944 lines
58 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. InetSess.cpp
  5. Abstract:
  6. Implements the Passport Session that uses WinInet as the underlying transport.
  7. Author:
  8. Biao Wang (biaow) 01-Oct-2000
  9. --*/
  10. #include "PPdefs.h"
  11. #ifdef HINTERNET
  12. #undef HINTERNET
  13. #endif
  14. #ifdef INTERNET_PORT
  15. #undef INTERNET_PORT
  16. #endif
  17. #include <WinInet.h>
  18. #include "session.h"
  19. #include <wchar.h>
  20. #include "passport.h"
  21. #include <sensapi.h>
  22. // #include "inetsess.tmh"
  23. //
  24. // func pointer decl for WinInet
  25. //
  26. typedef HINTERNET
  27. (WINAPI * PFN_INTERNET_OPEN)(
  28. IN LPCWSTR lpwszAgent,
  29. IN DWORD dwAccessType,
  30. IN LPCWSTR lpwszProxy OPTIONAL,
  31. IN LPCWSTR lpwszProxyBypass OPTIONAL,
  32. IN DWORD dwFlags
  33. );
  34. typedef HINTERNET
  35. (WINAPI * PFN_INTERNET_CONNECT)(
  36. IN HINTERNET hInternet,
  37. IN LPCWSTR lpwszServerName,
  38. IN INTERNET_PORT nServerPort,
  39. IN LPCWSTR lpwszUserName OPTIONAL,
  40. IN LPCWSTR lpwszPassword OPTIONAL,
  41. IN DWORD dwService,
  42. IN DWORD dwFlags,
  43. IN DWORD_PTR dwContext
  44. );
  45. typedef HINTERNET
  46. (WINAPI * PFN_OPEN_REQUEST)(
  47. IN HINTERNET hConnect,
  48. IN LPCWSTR lpwszVerb,
  49. IN LPCWSTR lpwszObjectName,
  50. IN LPCWSTR lpwszVersion,
  51. IN LPCWSTR lpwszReferrer OPTIONAL,
  52. IN LPCWSTR FAR * lplpwszAcceptTypes OPTIONAL,
  53. IN DWORD dwFlags,
  54. IN DWORD_PTR dwContext
  55. );
  56. typedef BOOL
  57. (WINAPI * PFN_SEND_REQUEST)(
  58. IN HINTERNET hRequest,
  59. IN LPCWSTR lpwszHeaders OPTIONAL,
  60. IN DWORD dwHeadersLength,
  61. IN LPVOID lpOptional OPTIONAL,
  62. IN DWORD dwOptionalLength
  63. );
  64. typedef BOOL
  65. (WINAPI * PFN_QUERY_INFO)(
  66. IN HINTERNET hRequest,
  67. IN DWORD dwInfoLevel,
  68. IN LPVOID lpvBuffer,
  69. IN LPDWORD lpdwBufferLength,
  70. IN OUT LPDWORD lpdwIndex
  71. );
  72. typedef BOOL
  73. (WINAPI* PFN_CLOSE_HANDLE)(
  74. IN HINTERNET hInternet
  75. );
  76. typedef BOOL
  77. (WINAPI* PFN_SET_OPTION)(
  78. IN HINTERNET hInternet,
  79. IN DWORD dwOption,
  80. IN LPVOID lpBuffer,
  81. IN DWORD dwBufferLength
  82. );
  83. typedef BOOL
  84. (WINAPI* PFN_QUERY_OPTION)(
  85. IN HINTERNET hInternet,
  86. IN DWORD dwOption,
  87. OUT LPVOID lpBuffer,
  88. IN OUT LPDWORD lpdwBufferLength
  89. );
  90. typedef HINTERNET
  91. (WINAPI* PFN_OPEN_URL)(
  92. IN HINTERNET hInternet,
  93. IN LPCWSTR lpwszUrl,
  94. IN LPCWSTR lpwszHeaders,
  95. IN DWORD dwHeadersLength,
  96. IN DWORD dwFlags,
  97. IN DWORD_PTR dwContext
  98. );
  99. typedef BOOL
  100. (WINAPI* PFN_CRACK_URL)(
  101. IN LPCWSTR lpszUrl,
  102. IN DWORD dwUrlLength,
  103. IN DWORD dwFlags,
  104. IN OUT PVOID/*LPURL_COMPONENTSW*/ lpUrlComponents
  105. );
  106. typedef BOOL
  107. (WINAPI* PFN_READ_FILE)(
  108. IN HINTERNET hFile,
  109. IN LPVOID lpBuffer,
  110. IN DWORD dwNumberOfBytesToRead,
  111. OUT LPDWORD lpdwNumberOfBytesRead
  112. );
  113. typedef INTERNET_STATUS_CALLBACK
  114. (WINAPI* PFN_STATUS_CALLBACK)(
  115. IN HINTERNET hInternet,
  116. IN INTERNET_STATUS_CALLBACK lpfnInternetCallback
  117. );
  118. typedef BOOL
  119. (WINAPI* PFN_ADD_HEADERS)(
  120. IN HINTERNET hConnect,
  121. IN LPCWSTR lpszHeaders,
  122. IN DWORD dwHeadersLength,
  123. IN DWORD dwModifiers
  124. );
  125. typedef BOOL
  126. (WINAPI* PFN_IS_HOST_BYPASS_PROXY)(
  127. IN INTERNET_SCHEME tScheme,
  128. IN LPCSTR pszHost,
  129. IN DWORD cchHost);
  130. class WININET_SESSION : public SESSION
  131. {
  132. protected:
  133. WININET_SESSION(void);
  134. virtual ~WININET_SESSION(void);
  135. virtual BOOL Open(PCWSTR pwszHttpStack, HINTERNET);
  136. virtual void Close(void);
  137. protected:
  138. virtual HINTERNET Connect(
  139. LPCWSTR lpwszServerName,
  140. INTERNET_PORT
  141. );
  142. virtual HINTERNET OpenRequest(
  143. HINTERNET hConnect,
  144. LPCWSTR lpwszVerb,
  145. LPCWSTR lpwszObjectName,
  146. DWORD dwFlags,
  147. DWORD_PTR dwContext = 0);
  148. virtual BOOL SendRequest(
  149. HINTERNET hRequest,
  150. LPCWSTR lpwszHeaders,
  151. DWORD dwHeadersLength,
  152. DWORD_PTR dwContext = 0);
  153. virtual BOOL QueryHeaders(
  154. HINTERNET hRequest,
  155. DWORD dwInfoLevel,
  156. LPVOID lpvBuffer,
  157. LPDWORD lpdwBufferLength,
  158. LPDWORD lpdwIndex = NULL);
  159. virtual BOOL CloseHandle(
  160. IN HINTERNET hInternet);
  161. virtual BOOL QueryOption(
  162. HINTERNET hInternet,
  163. DWORD dwOption,
  164. LPVOID lpBuffer,
  165. LPDWORD lpdwBufferLength);
  166. virtual BOOL SetOption(
  167. HINTERNET hInternet,
  168. DWORD dwOption,
  169. LPVOID lpBuffer,
  170. DWORD dwBufferLength);
  171. virtual HINTERNET OpenUrl(
  172. LPCWSTR lpwszUrl,
  173. LPCWSTR lpwszHeaders,
  174. DWORD dwHeadersLength,
  175. DWORD dwFlags);
  176. virtual BOOL ReadFile(
  177. HINTERNET hFile,
  178. LPVOID lpBuffer,
  179. DWORD dwNumberOfBytesToRead,
  180. LPDWORD lpdwNumberOfBytesRead);
  181. virtual BOOL CrackUrl(
  182. LPCWSTR lpszUrl,
  183. DWORD dwUrlLength,
  184. DWORD dwFlags,
  185. PVOID/*LPURL_COMPONENTSW*/ lpUrlComponents);
  186. virtual PVOID SetStatusCallback(
  187. HINTERNET hInternet,
  188. PVOID lpfnCallback
  189. );
  190. virtual BOOL AddHeaders(
  191. HINTERNET hConnect,
  192. LPCWSTR lpszHeaders,
  193. DWORD dwHeadersLength,
  194. DWORD dwModifiers
  195. );
  196. virtual BOOL IsHostBypassProxy(
  197. INTERNET_SCHEME tScheme,
  198. LPCSTR pszHost,
  199. DWORD cchHost);
  200. #ifdef PP_DEMO
  201. virtual BOOL ContactPartner(PCWSTR pwszPartnerUrl,
  202. PCWSTR pwszVerb,
  203. PCWSTR pwszHeaders,
  204. PWSTR pwszData,
  205. PDWORD pdwDataLength
  206. );
  207. #endif // PP_DEMO
  208. BOOL InitHttpApi(PFN_INTERNET_OPEN*);
  209. protected:
  210. HINTERNET m_hInternet;
  211. PFN_INTERNET_CONNECT m_pfnConnect;
  212. PFN_OPEN_REQUEST m_pfnOpenRequest;
  213. PFN_SEND_REQUEST m_pfnSendRequest;
  214. PFN_QUERY_INFO m_pfnQueryInfo;
  215. PFN_CLOSE_HANDLE m_pfnCloseHandle;
  216. PFN_SET_OPTION m_pfnSetOption;
  217. PFN_OPEN_URL m_pfnOpenUrl;
  218. PFN_QUERY_OPTION m_pfnQueryOption;
  219. PFN_CRACK_URL m_pfnCrack;
  220. PFN_READ_FILE m_pfnReadFile;
  221. PFN_STATUS_CALLBACK m_pfnStatusCallback;
  222. PFN_ADD_HEADERS m_pfnAddHeaders;
  223. PFN_IS_HOST_BYPASS_PROXY m_pfnIsHostBypassProxy;
  224. friend class SESSION;
  225. };
  226. //
  227. // Implementation for SESSION
  228. //
  229. SESSION* CreateWinHttpSession(void);
  230. // -----------------------------------------------------------------------------
  231. BOOL SESSION::CreateObject(PCWSTR pwszHttpStack, HINTERNET hSession, SESSION*& pSess)
  232. {
  233. PP_ASSERT(pwszHttpStack != NULL);
  234. pSess = NULL;
  235. if (!::_wcsicmp(pwszHttpStack, L"WinInet.dll") ||
  236. !::_wcsicmp(pwszHttpStack, L"WinInet"))
  237. {
  238. pSess = new WININET_SESSION();
  239. }
  240. else
  241. {
  242. pSess = ::CreateWinHttpSession();
  243. }
  244. if (pSess)
  245. {
  246. return pSess->Open(pwszHttpStack, hSession);
  247. }
  248. else
  249. {
  250. DoTraceMessage(PP_LOG_ERROR, "CreateObject() failed; not enough memory");
  251. return FALSE;
  252. }
  253. }
  254. // -----------------------------------------------------------------------------
  255. SESSION::SESSION(void)
  256. {
  257. m_hHttpStack = 0;
  258. m_hCredUI = 0;
  259. m_RefCount = 0;
  260. m_pfnReadDomainCred = NULL;
  261. m_pfnCredFree = NULL;
  262. m_hKeyLM = NULL;
  263. m_hKeyCU = NULL;
  264. m_hKeyDAMap = NULL;
  265. m_wCurrentDAUrl[0] = 0;
  266. m_LastNexusDownloadTime = 0xFFFFFFFF;
  267. }
  268. // -----------------------------------------------------------------------------
  269. SESSION::~SESSION(void)
  270. {
  271. }
  272. BOOL SESSION::GetDAInfoFromPPNexus(
  273. IN BOOL fForce, // ignored for now, always assumes TRUE regardless of actual value
  274. IN PWSTR pwszRegUrl, // user supplied buffer ...
  275. IN OUT PDWORD pdwRegUrlLen, // ... and length (will be updated to actual length
  276. // on successful return)
  277. IN PWSTR pwszRealm, // user supplied buffer ...
  278. IN OUT PDWORD pdwRealmLen // ... and length (will be updated to actual length
  279. // on successful return)
  280. )
  281. {
  282. BOOL fRetVal = FALSE;
  283. HINTERNET hRequest = NULL;
  284. HINTERNET hConnect = NULL;
  285. DWORD dwError;
  286. WCHAR wNexusHost[128] = L"nexus.passport.com";
  287. DWORD dwHostLen = sizeof(wNexusHost); // note: size of the buffer, not # of UNICODE characters
  288. WCHAR wNexusObj[128] = L"rdr/pprdr.asp";
  289. DWORD dwObjLen = sizeof(wNexusObj);
  290. PWSTR pwszPassportUrls = NULL;
  291. DWORD dwUrlsLen = 0;
  292. DWORD dwValueType;
  293. WCHAR Delimiters[] = L",";
  294. PWSTR Token = NULL;
  295. // we allow only one Nexus contact per session to avoid infinite loop due to Nexus misconfiguration
  296. DWORD dwCurrentTime = ::GetTickCount();
  297. if ((dwCurrentTime >= m_LastNexusDownloadTime) &&
  298. (dwCurrentTime - m_LastNexusDownloadTime < 5*60*1000)) // 5 minutes
  299. {
  300. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() failed: Nexus info already downloaded");
  301. goto exit;
  302. }
  303. // biaow-todo: when the Passport Team gives us THE final Nexus name, we'll then hard-code it here. And
  304. // there will be no need to query registry here by then.
  305. if (m_hKeyLM)
  306. {
  307. dwError = ::RegQueryValueExW(m_hKeyLM,
  308. L"NexusHost",
  309. 0,
  310. &dwValueType,
  311. reinterpret_cast<LPBYTE>(wNexusHost),
  312. &dwHostLen);
  313. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  314. // PP_ASSERT(dwValueType == REG_SZ); BVT Break!!!
  315. dwError = ::RegQueryValueExW(m_hKeyLM,
  316. L"NexusObj",
  317. 0,
  318. &dwValueType,
  319. reinterpret_cast<LPBYTE>(wNexusObj),
  320. &dwObjLen);
  321. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  322. // PP_ASSERT(dwValueType == REG_SZ); BVT Break!!!
  323. }
  324. CHAR NexusHost[128];
  325. ::WideCharToMultiByte (CP_ACP, 0, wNexusHost, -1, NexusHost, 128, NULL, NULL);
  326. hConnect = Connect(wNexusHost,
  327. #ifdef DISABLE_SSL
  328. INTERNET_DEFAULT_HTTP_PORT
  329. #else
  330. INTERNET_DEFAULT_HTTPS_PORT
  331. #endif
  332. );
  333. if (hConnect == NULL)
  334. {
  335. DWORD dwErrorCode = ::GetLastError();
  336. DoTraceMessage(PP_LOG_ERROR,
  337. "SESSION::GetDAInfoFromPPNexus(): failed to connect to %ws; Error = %d",
  338. wNexusHost, dwErrorCode);
  339. goto exit;
  340. }
  341. hRequest = OpenRequest(hConnect,
  342. NULL,
  343. wNexusObj,
  344. #ifdef DISABLE_SSL
  345. 0
  346. #else
  347. INTERNET_FLAG_SECURE
  348. #endif
  349. );
  350. if (hRequest == NULL)
  351. {
  352. DWORD dwErrorCode = ::GetLastError();
  353. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; OpenRequest() to %ws failed, Error Code = %d",
  354. wNexusObj, dwErrorCode);
  355. goto exit;
  356. }
  357. if (!SendRequest(hRequest, NULL, 0))
  358. {
  359. DWORD dwErrorCode = ::GetLastError();
  360. #ifdef BAD_CERT_OK
  361. if (dwErrorCode == ERROR_INTERNET_INVALID_CA)
  362. {
  363. DWORD dwSecFlags;
  364. DWORD dwSecurityFlagsSize = sizeof(dwSecFlags);
  365. if (!QueryOption(hRequest,
  366. INTERNET_OPTION_SECURITY_FLAGS,
  367. &dwSecFlags,
  368. &dwSecurityFlagsSize))
  369. {
  370. dwSecFlags = 0;
  371. }
  372. else
  373. {
  374. dwSecFlags |= SECURITY_SET_MASK;
  375. }
  376. if (!SetOption(hRequest,
  377. INTERNET_OPTION_SECURITY_FLAGS,
  378. &dwSecFlags,
  379. dwSecurityFlagsSize))
  380. {
  381. PP_ASSERT(TRUE); // shouldn't reach here
  382. goto exit;
  383. }
  384. else
  385. {
  386. if (!SendRequest(hRequest, NULL, 0))
  387. {
  388. DWORD dwErrorCode = ::GetLastError();
  389. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus(): SendRequest() failed");
  390. goto exit;
  391. }
  392. }
  393. }
  394. #else
  395. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus(): failed");
  396. goto exit;
  397. #endif // BAD_CERT_OK
  398. }
  399. if (QueryHeaders(hRequest,
  400. HTTP_QUERY_PASSPORT_URLS,
  401. 0,
  402. &dwUrlsLen) == FALSE)
  403. {
  404. if ((::GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwUrlsLen == 0))
  405. {
  406. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
  407. goto exit;
  408. }
  409. }
  410. else
  411. {
  412. PP_ASSERT(TRUE); // should not reach here
  413. }
  414. pwszPassportUrls = new WCHAR[dwUrlsLen];
  415. if (pwszPassportUrls == NULL)
  416. {
  417. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; insufficient memory");
  418. goto exit;
  419. }
  420. if (QueryHeaders(hRequest,
  421. HTTP_QUERY_PASSPORT_URLS,
  422. pwszPassportUrls,
  423. &dwUrlsLen) == FALSE)
  424. {
  425. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
  426. goto exit;
  427. }
  428. Token = ::wcstok(pwszPassportUrls, Delimiters);
  429. while (Token != NULL)
  430. {
  431. // skip leading white spaces
  432. while (*Token == (L" ")[0]) { ++Token; }
  433. if (Token == NULL)
  434. {
  435. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no text in between commas");
  436. goto next_token;
  437. }
  438. // find DALocation
  439. if (!::_wcsnicmp(Token, L"DALogin", ::wcslen(L"DALogin")))
  440. {
  441. PWSTR pwszDAUrl = ::wcsstr(Token, L"=");
  442. if (pwszDAUrl == NULL)
  443. {
  444. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DALocation");
  445. goto exit;
  446. }
  447. pwszDAUrl++; // skip "="
  448. while (*pwszDAUrl == (L" ")[0]) { ++pwszDAUrl; } // skip leading white spaces
  449. ::wcscpy(m_wDefaultDAUrl, L"https://");
  450. ::wcscat(m_wDefaultDAUrl, pwszDAUrl);
  451. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  452. L"LoginServerUrl",
  453. 0,
  454. REG_SZ,
  455. reinterpret_cast<const LPBYTE>(m_wDefaultDAUrl),
  456. ::wcslen(m_wDefaultDAUrl) * sizeof(WCHAR)) != ERROR_SUCCESS)
  457. {
  458. if (m_hKeyCU)
  459. {
  460. ::RegSetValueExW(m_hKeyCU,
  461. L"LoginServerUrl",
  462. 0,
  463. REG_SZ,
  464. reinterpret_cast<const LPBYTE>(m_wDefaultDAUrl),
  465. ::wcslen(m_wDefaultDAUrl) * sizeof(WCHAR));
  466. }
  467. }
  468. m_LastNexusDownloadTime = ::GetTickCount();
  469. fRetVal = TRUE;
  470. DoTraceMessage(PP_LOG_INFO, "DALocation URL %ws found", m_wDefaultDAUrl);
  471. }
  472. else if (!::_wcsnicmp(Token, L"DARealm", ::wcslen(L"DARealm")))
  473. {
  474. PWSTR pwszDARealm = ::wcsstr(Token, L"=");
  475. if (pwszDARealm == NULL)
  476. {
  477. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DARealm");
  478. goto exit;
  479. }
  480. pwszDARealm++; // skip "="
  481. while (*pwszDARealm == (L" ")[0]) { ++pwszDARealm; } // skip leading white spaces
  482. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  483. L"LoginServerRealm",
  484. 0,
  485. REG_SZ,
  486. reinterpret_cast<const LPBYTE>(pwszDARealm),
  487. ::wcslen(pwszDARealm) * sizeof(WCHAR)) != ERROR_SUCCESS)
  488. {
  489. if (m_hKeyCU)
  490. {
  491. ::RegSetValueExW(m_hKeyCU,
  492. L"LoginServerRealm",
  493. 0,
  494. REG_SZ,
  495. reinterpret_cast<const LPBYTE>(pwszDARealm),
  496. ::wcslen(pwszDARealm) * sizeof(WCHAR));
  497. }
  498. }
  499. if (pwszRealm)
  500. {
  501. if (*pdwRealmLen < ::wcslen(pwszDARealm) + 1)
  502. {
  503. *pdwRealmLen = ::wcslen(pwszDARealm) + 1;
  504. fRetVal = FALSE;
  505. goto exit;
  506. }
  507. else
  508. {
  509. ::wcscpy(pwszRealm, pwszDARealm);
  510. *pdwRealmLen = ::wcslen(pwszDARealm) + 1;
  511. }
  512. }
  513. DoTraceMessage(PP_LOG_INFO, "DARealm URL %ws found", m_wDefaultDAUrl);
  514. }
  515. else if (!::_wcsnicmp(Token, L"DAReg", ::wcslen(L"DAReg")))
  516. {
  517. PWSTR pwszDAReg = ::wcsstr(Token, L"=");
  518. if (pwszDAReg == NULL)
  519. {
  520. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DAReg");
  521. goto exit;
  522. }
  523. pwszDAReg++; // skip "="
  524. while (*pwszDAReg == (L" ")[0]) { ++pwszDAReg; } // skip leading white spaces
  525. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  526. L"RegistrationUrl",
  527. 0,
  528. REG_SZ,
  529. reinterpret_cast<const LPBYTE>(pwszDAReg),
  530. ::wcslen(pwszDAReg) * sizeof(WCHAR)) != ERROR_SUCCESS)
  531. {
  532. if (m_hKeyCU)
  533. {
  534. ::RegSetValueExW(m_hKeyCU,
  535. L"RegistrationUrl",
  536. 0,
  537. REG_SZ,
  538. reinterpret_cast<const LPBYTE>(pwszDAReg),
  539. ::wcslen(pwszDAReg) * sizeof(WCHAR));
  540. }
  541. }
  542. if (pwszRegUrl)
  543. {
  544. if (*pdwRegUrlLen < ::wcslen(pwszDAReg) + 1)
  545. {
  546. *pdwRegUrlLen = ::wcslen(pwszDAReg) + 1;
  547. fRetVal = FALSE;
  548. goto exit;
  549. }
  550. else
  551. {
  552. ::wcscpy(pwszRegUrl, pwszDAReg);
  553. *pdwRegUrlLen = ::wcslen(pwszDAReg) + 1;
  554. }
  555. }
  556. DoTraceMessage(PP_LOG_INFO, "DAReg URL %ws found", m_wDefaultDAUrl);
  557. }
  558. else if (!::_wcsnicmp(Token, L"ConfigVersion", ::wcslen(L"ConfigVersion")))
  559. {
  560. PWSTR pwszConfigVersion = ::wcsstr(Token, L"=");
  561. if (pwszConfigVersion == NULL)
  562. {
  563. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after ConfigVersion");
  564. goto exit;
  565. }
  566. pwszConfigVersion++; // skip "="
  567. while (*pwszConfigVersion == (L" ")[0]) { ++pwszConfigVersion; } // skip leading white spaces
  568. DWORD dwVersion = _wtoi(pwszConfigVersion);
  569. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  570. L"ConfigVersion",
  571. 0,
  572. REG_DWORD,
  573. reinterpret_cast<const LPBYTE>(&dwVersion),
  574. sizeof(DWORD)) != ERROR_SUCCESS)
  575. {
  576. if (m_hKeyCU)
  577. {
  578. ::RegSetValueExW(m_hKeyCU,
  579. L"ConfigVersion",
  580. 0,
  581. REG_DWORD,
  582. reinterpret_cast<const LPBYTE>(&dwVersion),
  583. sizeof(DWORD));
  584. }
  585. }
  586. DoTraceMessage(PP_LOG_INFO, "ConfigVersion URL %ws found", m_wDefaultDAUrl);
  587. }
  588. else if (!::_wcsnicmp(Token, L"Help", ::wcslen(L"Help")))
  589. {
  590. PWSTR pwszHelp = ::wcsstr(Token, L"=");
  591. if (pwszHelp == NULL)
  592. {
  593. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after Help");
  594. goto exit;
  595. }
  596. pwszHelp++; // skip "="
  597. while (*pwszHelp == (L" ")[0]) { ++pwszHelp; } // skip leading white spaces
  598. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  599. L"Help",
  600. 0,
  601. REG_SZ,
  602. reinterpret_cast<const LPBYTE>(pwszHelp),
  603. ::wcslen(pwszHelp) * sizeof(WCHAR)) != ERROR_SUCCESS)
  604. {
  605. if (m_hKeyCU)
  606. {
  607. ::RegSetValueExW(m_hKeyCU,
  608. L"Help",
  609. 0,
  610. REG_SZ,
  611. reinterpret_cast<const LPBYTE>(pwszHelp),
  612. ::wcslen(pwszHelp) * sizeof(WCHAR));
  613. }
  614. }
  615. DoTraceMessage(PP_LOG_INFO, "Help URL %ws found", m_wDefaultDAUrl);
  616. }
  617. else if (!::_wcsnicmp(Token, L"Privacy", ::wcslen(L"Privacy")))
  618. {
  619. PWSTR pwszPrivacy = ::wcsstr(Token, L"=");
  620. if (pwszPrivacy == NULL)
  621. {
  622. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after Privacy");
  623. goto exit;
  624. }
  625. pwszPrivacy++; // skip "="
  626. while (*pwszPrivacy == (L" ")[0]) { ++pwszPrivacy; } // skip leading white spaces
  627. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  628. L"Privacy",
  629. 0,
  630. REG_SZ,
  631. reinterpret_cast<const LPBYTE>(pwszPrivacy),
  632. ::wcslen(pwszPrivacy) * sizeof(WCHAR)) != ERROR_SUCCESS)
  633. {
  634. if (m_hKeyCU)
  635. {
  636. ::RegSetValueExW(m_hKeyCU,
  637. L"Privacy",
  638. 0,
  639. REG_SZ,
  640. reinterpret_cast<const LPBYTE>(pwszPrivacy),
  641. ::wcslen(pwszPrivacy) * sizeof(WCHAR));
  642. }
  643. }
  644. DoTraceMessage(PP_LOG_INFO, "Privacy URL %ws found", m_wDefaultDAUrl);
  645. }
  646. else if (!::_wcsnicmp(Token, L"Properties", ::wcslen(L"Properties")))
  647. {
  648. PWSTR pwszProperties = ::wcsstr(Token, L"=");
  649. if (pwszProperties == NULL)
  650. {
  651. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after Properties");
  652. goto exit;
  653. }
  654. pwszProperties++; // skip "="
  655. while (*pwszProperties == (L" ")[0]) { ++pwszProperties; } // skip leading white spaces
  656. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  657. L"Properties",
  658. 0,
  659. REG_SZ,
  660. reinterpret_cast<const LPBYTE>(pwszProperties),
  661. ::wcslen(pwszProperties) * sizeof(WCHAR)) != ERROR_SUCCESS)
  662. {
  663. if (m_hKeyCU)
  664. {
  665. ::RegSetValueExW(m_hKeyCU,
  666. L"Properties",
  667. 0,
  668. REG_SZ,
  669. reinterpret_cast<const LPBYTE>(pwszProperties),
  670. ::wcslen(pwszProperties) * sizeof(WCHAR));
  671. }
  672. }
  673. DoTraceMessage(PP_LOG_INFO, "Properties URL %ws found", m_wDefaultDAUrl);
  674. }
  675. else if (!::_wcsnicmp(Token, L"GeneralRedir", ::wcslen(L"GeneralRedir")))
  676. {
  677. PWSTR pwszGeneralRedir = ::wcsstr(Token, L"=");
  678. if (pwszGeneralRedir == NULL)
  679. {
  680. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after GeneralRedir");
  681. goto exit;
  682. }
  683. pwszGeneralRedir++; // skip "="
  684. while (*pwszGeneralRedir == (L" ")[0]) { ++pwszGeneralRedir; } // skip leading white spaces
  685. if (m_hKeyLM == NULL || ::RegSetValueExW(m_hKeyLM,
  686. L"GeneralRedir",
  687. 0,
  688. REG_SZ,
  689. reinterpret_cast<const LPBYTE>(pwszGeneralRedir),
  690. ::wcslen(pwszGeneralRedir) * sizeof(WCHAR)) != ERROR_SUCCESS)
  691. {
  692. if (m_hKeyCU)
  693. {
  694. ::RegSetValueExW(m_hKeyCU,
  695. L"GeneralRedir",
  696. 0,
  697. REG_SZ,
  698. reinterpret_cast<const LPBYTE>(pwszGeneralRedir),
  699. ::wcslen(pwszGeneralRedir) * sizeof(WCHAR));
  700. }
  701. }
  702. DoTraceMessage(PP_LOG_INFO, "GeneralRedir URL %ws found", m_wDefaultDAUrl);
  703. }
  704. next_token:
  705. Token = ::wcstok(NULL, Delimiters);
  706. }
  707. exit:
  708. if (pwszPassportUrls)
  709. {
  710. delete [] pwszPassportUrls;
  711. }
  712. if (hRequest)
  713. {
  714. CloseHandle(hRequest);
  715. }
  716. if (hConnect)
  717. {
  718. CloseHandle(hConnect);
  719. }
  720. return fRetVal;
  721. }
  722. BOOL SESSION::GetRealm(
  723. PWSTR pwszRealm, // user supplied buffer ...
  724. PDWORD pdwRealmLen // ... and length (will be updated to actual length
  725. // on successful return)
  726. ) const
  727. {
  728. WCHAR wRealm[64];
  729. DWORD RealmLen = sizeof(wRealm);
  730. DWORD dwValueType;
  731. BOOL fRealmFound = FALSE;
  732. if (m_hKeyCU == NULL || ::RegQueryValueExW(m_hKeyCU,
  733. L"LoginServerRealm",
  734. 0,
  735. &dwValueType,
  736. reinterpret_cast<LPBYTE>(&wRealm),
  737. &RealmLen) != ERROR_SUCCESS)
  738. {
  739. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  740. L"LoginServerRealm",
  741. 0,
  742. &dwValueType,
  743. reinterpret_cast<LPBYTE>(&wRealm),
  744. &RealmLen) == ERROR_SUCCESS)
  745. {
  746. fRealmFound = TRUE;
  747. }
  748. }
  749. else
  750. {
  751. fRealmFound = TRUE;
  752. }
  753. if (!fRealmFound)
  754. {
  755. *pdwRealmLen = 0;
  756. return FALSE;
  757. }
  758. if (!pwszRealm)
  759. {
  760. *pdwRealmLen = ::wcslen(wRealm) + 1;
  761. return FALSE;
  762. }
  763. if (*pdwRealmLen < ::wcslen(wRealm) + 1)
  764. {
  765. *pdwRealmLen = ::wcslen(wRealm) + 1;
  766. return FALSE;
  767. }
  768. ::wcscpy(pwszRealm, wRealm);
  769. *pdwRealmLen = ::wcslen(wRealm) + 1;
  770. return TRUE;
  771. }
  772. DWORD SESSION::GetNexusVersion(void)
  773. {
  774. DWORD dwVersion = 0;
  775. DWORD dwValueType;
  776. DWORD dwVerLen = sizeof(dwVersion);
  777. BOOL fVersionFound = FALSE;
  778. if (m_hKeyCU == NULL || ::RegQueryValueExW(m_hKeyCU,
  779. L"ConfigVersion",
  780. 0,
  781. &dwValueType,
  782. reinterpret_cast<LPBYTE>(&dwVersion),
  783. &dwVerLen) != ERROR_SUCCESS)
  784. {
  785. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  786. L"ConfigVersion",
  787. 0,
  788. &dwValueType,
  789. reinterpret_cast<LPBYTE>(&dwVersion),
  790. &dwVerLen) == ERROR_SUCCESS)
  791. {
  792. fVersionFound = TRUE;
  793. }
  794. }
  795. else
  796. {
  797. fVersionFound = TRUE;
  798. }
  799. if (fVersionFound)
  800. {
  801. return dwVersion;
  802. }
  803. else
  804. {
  805. return 0;
  806. }
  807. }
  808. BOOL SESSION::UpdateDAInfo(
  809. PCWSTR pwszSignIn,
  810. PCWSTR pwszDAUrl
  811. )
  812. {
  813. if (pwszSignIn)
  814. {
  815. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  816. if (pwszDomain && m_hKeyDAMap)
  817. {
  818. DWORD dwError = ::RegSetValueExW(m_hKeyDAMap,
  819. pwszDomain,
  820. 0,
  821. REG_SZ,
  822. reinterpret_cast<const LPBYTE>(const_cast<PWSTR>(pwszDAUrl)),
  823. ::wcslen(pwszDAUrl) * sizeof(WCHAR));
  824. if (dwError == ERROR_SUCCESS)
  825. {
  826. return TRUE;
  827. }
  828. }
  829. }
  830. return FALSE;
  831. }
  832. BOOL SESSION::PurgeDAInfo(PCWSTR pwszSignIn)
  833. {
  834. if (pwszSignIn == NULL)
  835. {
  836. return TRUE;
  837. }
  838. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  839. if (pwszDomain && m_hKeyDAMap)
  840. {
  841. ::RegDeleteValueW(m_hKeyDAMap, pwszDomain);
  842. return TRUE;
  843. }
  844. return FALSE;
  845. }
  846. BOOL SESSION::GetDAInfo(PCWSTR pwszSignIn,
  847. LPWSTR pwszDAHostName,
  848. DWORD HostNameLen,
  849. LPWSTR pwszDAHostObj,
  850. DWORD HostObjLen)
  851. {
  852. LPCWSTR pwszDAUrl = m_wDefaultDAUrl;
  853. PWSTR pwszDomainDAUrl = NULL;
  854. if (pwszSignIn)
  855. {
  856. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  857. if (pwszDomain && m_hKeyDAMap)
  858. {
  859. pwszDomainDAUrl = new WCHAR[512];
  860. if (pwszDomainDAUrl == NULL)
  861. {
  862. return FALSE;
  863. }
  864. DWORD dwDomainUrlLen = 512 * sizeof(sizeof(WCHAR));
  865. DWORD dwValueType;
  866. DWORD dwError = ::RegQueryValueExW(m_hKeyDAMap,
  867. pwszDomain,
  868. 0,
  869. &dwValueType,
  870. reinterpret_cast<LPBYTE>(pwszDomainDAUrl),
  871. &dwDomainUrlLen);
  872. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  873. // PP_ASSERT(dwValueType == REG_SZ);
  874. if (dwError == ERROR_SUCCESS)
  875. {
  876. pwszDAUrl = pwszDomainDAUrl;
  877. }
  878. }
  879. }
  880. ::wcscpy(m_wCurrentDAUrl, pwszDAUrl);
  881. URL_COMPONENTSW UrlComps;
  882. ::memset(&UrlComps, 0, sizeof(UrlComps));
  883. UrlComps.dwStructSize = sizeof(UrlComps) / sizeof(WCHAR);
  884. UrlComps.lpszHostName = pwszDAHostName;
  885. UrlComps.dwHostNameLength = HostNameLen;
  886. UrlComps.lpszUrlPath = pwszDAHostObj;
  887. UrlComps.dwUrlPathLength = HostObjLen;
  888. if (CrackUrl(pwszDAUrl,
  889. 0,
  890. 0,
  891. &UrlComps) == FALSE)
  892. {
  893. DoTraceMessage(PP_LOG_ERROR,
  894. "WININET_SESSION::GetDAInfo() failed; can not crack the URL %ws",
  895. pwszDAUrl);
  896. delete [] pwszDomainDAUrl;
  897. return FALSE;
  898. }
  899. delete [] pwszDomainDAUrl;
  900. return TRUE;
  901. }
  902. BOOL SESSION::GetCachedCreds(
  903. PCWSTR pwszRealm,
  904. PCWSTR pwszTarget,
  905. PCREDENTIALW** pppCreds,
  906. DWORD* pdwCreds
  907. )
  908. {
  909. *pppCreds = NULL;
  910. *pdwCreds = 0;
  911. if (m_pfnReadDomainCred == NULL)
  912. {
  913. return FALSE;
  914. }
  915. ULONG CredTypes = CRED_TYPE_DOMAIN_VISIBLE_PASSWORD;
  916. DWORD dwFlags = CRED_CACHE_TARGET_INFORMATION;
  917. CREDENTIAL_TARGET_INFORMATIONW TargetInfo;
  918. memset ( (void*)&TargetInfo, 0, sizeof(CREDENTIAL_TARGET_INFORMATIONW));
  919. TargetInfo.TargetName = const_cast<PWSTR>(pwszTarget);
  920. TargetInfo.DnsDomainName = const_cast<PWSTR>(pwszRealm);
  921. TargetInfo.PackageName = L"Passport1.4";
  922. TargetInfo.Flags = 0;
  923. TargetInfo.CredTypeCount = 1;
  924. TargetInfo.CredTypes = &CredTypes;
  925. if ((*m_pfnReadDomainCred)(&TargetInfo,
  926. dwFlags,
  927. pdwCreds,
  928. pppCreds ) != TRUE)
  929. {
  930. *pppCreds = NULL;
  931. *pdwCreds = 0;
  932. }
  933. // check to see if we've been told to ignore cached creds
  934. if ( g_fIgnoreCachedCredsForPassport )
  935. {
  936. if ( *pppCreds != NULL )
  937. {
  938. if (m_pfnCredFree)
  939. {
  940. m_pfnCredFree(*pppCreds);
  941. }
  942. }
  943. *pppCreds = NULL;
  944. *pdwCreds = 0;
  945. }
  946. return (*pppCreds != NULL );
  947. }
  948. BOOL SESSION::Open(PCWSTR /*pwszHttpStack*/, HINTERNET)
  949. {
  950. BOOL fRetVal = FALSE;
  951. DWORD dwError;
  952. DWORD dwValueType;
  953. DWORD dwUrlLen = sizeof(m_wDefaultDAUrl); // note: size of the buffer, not # of UNICODE characters
  954. BOOL fDAInfoCached = FALSE; // assume NO DA info's cached locally
  955. dwError = ::RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  956. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  957. 0,
  958. NULL,
  959. REG_OPTION_NON_VOLATILE,
  960. KEY_READ | KEY_WRITE,
  961. NULL,
  962. &m_hKeyLM,
  963. NULL);
  964. if (dwError != ERROR_SUCCESS)
  965. {
  966. DoTraceMessage(PP_LOG_ERROR,
  967. "SESSION::Open() failed; can not create/open the Passport key; Error = %d", dwError);
  968. // we can't open the Passport key for read & write, let's try open it for read only
  969. ::RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  970. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  971. 0,
  972. NULL,
  973. REG_OPTION_NON_VOLATILE,
  974. KEY_READ,
  975. NULL,
  976. &m_hKeyLM,
  977. NULL);
  978. // if we still can't open it for read, we are still fine since we can download the info from the
  979. // Nexus server. *NOTE* m_hKeyLM could be NULL from this point on.
  980. }
  981. dwError = ::RegCreateKeyExW(HKEY_CURRENT_USER,
  982. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  983. 0,
  984. NULL,
  985. REG_OPTION_NON_VOLATILE,
  986. KEY_READ | KEY_WRITE,
  987. NULL,
  988. &m_hKeyCU,
  989. NULL);
  990. if (dwError != ERROR_SUCCESS)
  991. {
  992. DoTraceMessage(PP_LOG_ERROR,
  993. "SESSION::Open() failed; can not create/open the Passport key; Error = %d", dwError);
  994. ::RegCreateKeyExW(HKEY_CURRENT_USER,
  995. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Passport",
  996. 0,
  997. NULL,
  998. REG_OPTION_NON_VOLATILE,
  999. KEY_READ,
  1000. NULL,
  1001. &m_hKeyCU,
  1002. NULL);
  1003. }
  1004. if (m_hKeyCU)
  1005. {
  1006. dwError = ::RegCreateKeyExW(m_hKeyCU,
  1007. L"DAMap",
  1008. 0,
  1009. NULL,
  1010. REG_OPTION_NON_VOLATILE,
  1011. KEY_READ | KEY_WRITE,
  1012. NULL,
  1013. &m_hKeyDAMap,
  1014. NULL);
  1015. if (dwError != ERROR_SUCCESS)
  1016. {
  1017. DoTraceMessage(PP_LOG_ERROR,
  1018. "SESSION::Open() failed; can not create/open the Passport key; Error = %d", dwError);
  1019. ::RegCreateKeyExW(m_hKeyCU,
  1020. L"DAMap",
  1021. 0,
  1022. NULL,
  1023. REG_OPTION_NON_VOLATILE,
  1024. KEY_READ,
  1025. NULL,
  1026. &m_hKeyDAMap,
  1027. NULL);
  1028. }
  1029. }
  1030. if (m_hKeyCU == NULL || ::RegQueryValueExW(m_hKeyCU,
  1031. L"LoginServerUrl",
  1032. 0,
  1033. &dwValueType,
  1034. reinterpret_cast<LPBYTE>(m_wDefaultDAUrl),
  1035. &dwUrlLen) != ERROR_SUCCESS)
  1036. {
  1037. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  1038. L"LoginServerUrl",
  1039. 0,
  1040. &dwValueType,
  1041. reinterpret_cast<LPBYTE>(m_wDefaultDAUrl),
  1042. &dwUrlLen) == ERROR_SUCCESS)
  1043. {
  1044. fDAInfoCached = TRUE;
  1045. }
  1046. }
  1047. else
  1048. {
  1049. fDAInfoCached = TRUE;
  1050. }
  1051. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  1052. // PP_ASSERT(dwValueType == REG_SZ); BVT break!!!
  1053. if (!fDAInfoCached || (::wcslen(m_wDefaultDAUrl) == ::wcslen(L"")))
  1054. {
  1055. if (GetDAInfoFromPPNexus(FALSE, // don't force connection establishment if nexus not reachable
  1056. NULL,
  1057. 0,
  1058. NULL,
  1059. 0) == FALSE)
  1060. {
  1061. goto exit;
  1062. }
  1063. }
  1064. else
  1065. {
  1066. /*
  1067. URL_COMPONENTSW UrlComps;
  1068. ::memset(&UrlComps, 0, sizeof(UrlComps));
  1069. UrlComps.dwStructSize = sizeof(UrlComps) / sizeof(WCHAR);
  1070. UrlComps.lpszHostName = m_wDAHostName;
  1071. UrlComps.dwHostNameLength = ARRAYSIZE(m_wDAHostName);
  1072. UrlComps.lpszUrlPath = m_wDATargetObj;
  1073. UrlComps.dwUrlPathLength = ARRAYSIZE(m_wDATargetObj);
  1074. if (CrackUrl(m_wDefaultDAUrl,
  1075. 0,
  1076. 0,
  1077. &UrlComps) == FALSE)
  1078. {
  1079. DoTraceMessage(PP_LOG_ERROR,
  1080. "WININET_SESSION::Open() failed; can not crack the URL %ws",
  1081. m_wDefaultDAUrl);
  1082. goto exit;
  1083. }
  1084. */
  1085. }
  1086. /*
  1087. DWORD dwRegUrlLen = sizeof(m_wRegistrationUrl);
  1088. dwError = ::RegQueryValueExW(m_hKeyLM,
  1089. L"RegistrationUrl",
  1090. 0,
  1091. &dwValueType,
  1092. reinterpret_cast<LPBYTE>(m_wRegistrationUrl),
  1093. &dwRegUrlLen);
  1094. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  1095. */
  1096. m_hCredUI = ::LoadLibraryW(L"advapi32.dll");
  1097. if (m_hCredUI)
  1098. {
  1099. m_pfnReadDomainCred =
  1100. reinterpret_cast<PFN_READ_DOMAIN_CRED_W>(::GetProcAddress(m_hCredUI, "CredReadDomainCredentialsW"));
  1101. if (m_pfnReadDomainCred == NULL)
  1102. {
  1103. DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredReadDomainCredentialsW()");
  1104. }
  1105. m_pfnCredFree =
  1106. reinterpret_cast<PFN_CRED_FREE>(::GetProcAddress(m_hCredUI, "CredFree"));
  1107. if (m_pfnCredFree == NULL)
  1108. {
  1109. DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredFree()");
  1110. }
  1111. }
  1112. fRetVal = TRUE;
  1113. exit:
  1114. return fRetVal;
  1115. }
  1116. void SESSION::Close(void)
  1117. {
  1118. if (m_hCredUI)
  1119. {
  1120. ::FreeLibrary(m_hCredUI);
  1121. m_hCredUI = NULL;
  1122. }
  1123. if (m_hKeyDAMap)
  1124. {
  1125. ::RegCloseKey(m_hKeyDAMap);
  1126. }
  1127. if (m_hKeyCU)
  1128. {
  1129. ::RegCloseKey(m_hKeyCU);
  1130. }
  1131. if (m_hKeyLM)
  1132. {
  1133. ::RegCloseKey(m_hKeyLM);
  1134. }
  1135. }
  1136. //
  1137. // Implementation for WININET_SESSION
  1138. //
  1139. // -----------------------------------------------------------------------------
  1140. WININET_SESSION::WININET_SESSION(void)
  1141. {
  1142. m_hInternet = NULL;
  1143. m_pfnConnect = NULL;
  1144. m_pfnOpenRequest = NULL;
  1145. m_pfnSendRequest = NULL;
  1146. m_pfnQueryInfo = NULL;
  1147. m_pfnCloseHandle = NULL;
  1148. m_pfnSetOption = NULL;
  1149. m_pfnOpenUrl = NULL;
  1150. m_pfnQueryOption = NULL;
  1151. m_pfnCrack = NULL;
  1152. m_pfnReadFile = NULL;
  1153. m_pfnStatusCallback = NULL;
  1154. m_pfnAddHeaders = NULL;
  1155. m_pfnIsHostBypassProxy = NULL;
  1156. }
  1157. // -----------------------------------------------------------------------------
  1158. WININET_SESSION::~WININET_SESSION(void)
  1159. {
  1160. }
  1161. // -----------------------------------------------------------------------------
  1162. HINTERNET WININET_SESSION::Connect(
  1163. LPCWSTR lpwszServerName,
  1164. INTERNET_PORT nPort)
  1165. {
  1166. PP_ASSERT(m_pfnConnect != NULL);
  1167. return (*m_pfnConnect)(m_hInternet,
  1168. lpwszServerName,
  1169. nPort,
  1170. NULL,
  1171. NULL,
  1172. INTERNET_SERVICE_HTTP,
  1173. 0,
  1174. 0);
  1175. }
  1176. // -----------------------------------------------------------------------------
  1177. HINTERNET WININET_SESSION::OpenRequest(
  1178. HINTERNET hConnect,
  1179. LPCWSTR lpwszVerb,
  1180. LPCWSTR lpwszObjectName,
  1181. DWORD dwFlags,
  1182. DWORD_PTR dwContext)
  1183. {
  1184. PP_ASSERT(m_pfnOpenRequest != NULL);
  1185. return (*m_pfnOpenRequest)(hConnect,
  1186. lpwszVerb,
  1187. lpwszObjectName,
  1188. L"HTTP/1.1",
  1189. NULL,
  1190. NULL,
  1191. dwFlags,
  1192. dwContext);
  1193. }
  1194. // -----------------------------------------------------------------------------
  1195. BOOL WININET_SESSION::SendRequest(
  1196. HINTERNET hRequest,
  1197. LPCWSTR lpwszHeaders,
  1198. DWORD dwHeadersLength,
  1199. DWORD_PTR dwContext)
  1200. {
  1201. PP_ASSERT(m_pfnSendRequest != NULL);
  1202. return (*m_pfnSendRequest)(hRequest,
  1203. lpwszHeaders,
  1204. dwHeadersLength,
  1205. NULL,
  1206. 0);
  1207. }
  1208. // -----------------------------------------------------------------------------
  1209. BOOL WININET_SESSION::QueryHeaders(
  1210. HINTERNET hRequest,
  1211. DWORD dwInfoLevel,
  1212. LPVOID lpvBuffer,
  1213. LPDWORD lpdwBufferLength,
  1214. LPDWORD lpdwIndex)
  1215. {
  1216. PP_ASSERT(m_pfnQueryInfo != NULL);
  1217. return (*m_pfnQueryInfo)(hRequest,
  1218. dwInfoLevel,
  1219. lpvBuffer,
  1220. lpdwBufferLength,
  1221. lpdwIndex);
  1222. }
  1223. // -----------------------------------------------------------------------------
  1224. BOOL WININET_SESSION::CloseHandle(
  1225. IN HINTERNET hInternet)
  1226. {
  1227. PP_ASSERT(m_pfnCloseHandle != NULL);
  1228. return (*m_pfnCloseHandle)(hInternet);
  1229. }
  1230. // -----------------------------------------------------------------------------
  1231. BOOL WININET_SESSION::QueryOption(
  1232. HINTERNET hInternet,
  1233. DWORD dwOption,
  1234. LPVOID lpBuffer,
  1235. LPDWORD lpdwBufferLength)
  1236. {
  1237. PP_ASSERT(m_pfnQueryOption != NULL);
  1238. return (*m_pfnQueryOption)(hInternet,
  1239. dwOption,
  1240. lpBuffer,
  1241. lpdwBufferLength
  1242. );
  1243. }
  1244. // -----------------------------------------------------------------------------
  1245. BOOL WININET_SESSION::SetOption(
  1246. HINTERNET hInternet,
  1247. DWORD dwOption,
  1248. LPVOID lpBuffer,
  1249. DWORD dwBufferLength)
  1250. {
  1251. PP_ASSERT(m_pfnSetOption != NULL);
  1252. return (*m_pfnSetOption)(hInternet,
  1253. dwOption,
  1254. lpBuffer,
  1255. dwBufferLength);
  1256. }
  1257. // -----------------------------------------------------------------------------
  1258. HINTERNET WININET_SESSION::OpenUrl(
  1259. LPCWSTR lpwszUrl,
  1260. LPCWSTR lpwszHeaders,
  1261. DWORD dwHeadersLength,
  1262. DWORD dwFlags)
  1263. {
  1264. PP_ASSERT(m_pfnOpenUrl != NULL);
  1265. return (*m_pfnOpenUrl)(m_hInternet,
  1266. lpwszUrl,
  1267. lpwszHeaders,
  1268. dwHeadersLength,
  1269. dwFlags,
  1270. 0);
  1271. }
  1272. // -----------------------------------------------------------------------------
  1273. BOOL WININET_SESSION::ReadFile(
  1274. HINTERNET hFile,
  1275. LPVOID lpBuffer,
  1276. DWORD dwNumberOfBytesToRead,
  1277. LPDWORD lpdwNumberOfBytesRead)
  1278. {
  1279. PP_ASSERT(m_pfnReadFile != NULL);
  1280. return (*m_pfnReadFile)(
  1281. hFile,
  1282. lpBuffer,
  1283. dwNumberOfBytesToRead,
  1284. lpdwNumberOfBytesRead);
  1285. }
  1286. BOOL WININET_SESSION::CrackUrl(
  1287. LPCWSTR lpszUrl,
  1288. DWORD dwUrlLength,
  1289. DWORD dwFlags,
  1290. PVOID/*LPURL_COMPONENTSW*/ lpUrlComponents)
  1291. {
  1292. PP_ASSERT (m_pfnCrack != NULL);
  1293. return (*m_pfnCrack)(lpszUrl,
  1294. dwUrlLength,
  1295. dwFlags,
  1296. lpUrlComponents);
  1297. }
  1298. PVOID WININET_SESSION::SetStatusCallback(
  1299. HINTERNET hInternet,
  1300. PVOID lpfnCallback
  1301. )
  1302. {
  1303. PP_ASSERT (m_pfnStatusCallback != NULL);
  1304. return (*m_pfnStatusCallback)(hInternet,
  1305. (INTERNET_STATUS_CALLBACK)lpfnCallback);
  1306. }
  1307. BOOL WININET_SESSION::AddHeaders(
  1308. HINTERNET hConnect,
  1309. LPCWSTR lpszHeaders,
  1310. DWORD dwHeadersLength,
  1311. DWORD dwModifiers
  1312. )
  1313. {
  1314. PP_ASSERT(m_pfnAddHeaders != NULL);
  1315. return (*m_pfnAddHeaders)(hConnect,
  1316. lpszHeaders,
  1317. dwHeadersLength,
  1318. dwModifiers
  1319. );
  1320. }
  1321. BOOL WININET_SESSION::IsHostBypassProxy(
  1322. INTERNET_SCHEME tScheme,
  1323. LPCSTR pszHost,
  1324. DWORD cchHost)
  1325. {
  1326. PP_ASSERT(m_pfnIsHostBypassProxy != NULL);
  1327. return (*m_pfnIsHostBypassProxy)(tScheme,
  1328. pszHost,
  1329. cchHost);
  1330. }
  1331. BOOL WININET_SESSION::InitHttpApi(PFN_INTERNET_OPEN* ppfnInternetOpen)
  1332. {
  1333. BOOL fRet = FALSE;
  1334. m_pfnCloseHandle =
  1335. reinterpret_cast<PFN_CLOSE_HANDLE>(::GetProcAddress(m_hHttpStack, "InternetCloseHandle"));
  1336. if (m_pfnCloseHandle == NULL)
  1337. {
  1338. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetCloseHandle not found");
  1339. goto exit;
  1340. }
  1341. *ppfnInternetOpen =
  1342. reinterpret_cast<PFN_INTERNET_OPEN>(::GetProcAddress(m_hHttpStack, "InternetOpenW"));
  1343. if (*ppfnInternetOpen == NULL)
  1344. {
  1345. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetOpenW not found");
  1346. goto exit;
  1347. }
  1348. m_pfnConnect =
  1349. reinterpret_cast<PFN_INTERNET_CONNECT>(::GetProcAddress(m_hHttpStack, "InternetConnectW"));
  1350. if (m_pfnConnect == NULL)
  1351. {
  1352. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetConnectW not found");
  1353. goto exit;
  1354. }
  1355. m_pfnOpenRequest =
  1356. reinterpret_cast<PFN_OPEN_REQUEST>(::GetProcAddress(m_hHttpStack, "HttpOpenRequestW"));
  1357. if (m_pfnOpenRequest == NULL)
  1358. {
  1359. DoTraceMessage(PP_LOG_ERROR, "function entry point HttpOpenRequestW not found");
  1360. goto exit;
  1361. }
  1362. m_pfnSendRequest =
  1363. reinterpret_cast<PFN_SEND_REQUEST>(::GetProcAddress(m_hHttpStack, "HttpSendRequestW"));
  1364. if (m_pfnSendRequest == NULL)
  1365. {
  1366. DoTraceMessage(PP_LOG_ERROR, "function entry point HttpSendRequestW not found");
  1367. goto exit;
  1368. }
  1369. m_pfnQueryInfo =
  1370. reinterpret_cast<PFN_QUERY_INFO>(::GetProcAddress(m_hHttpStack, "HttpQueryInfoW"));
  1371. if (m_pfnQueryInfo == NULL)
  1372. {
  1373. DoTraceMessage(PP_LOG_ERROR, "function entry point HttpQueryInfoW not found");
  1374. goto exit;
  1375. }
  1376. m_pfnSetOption =
  1377. reinterpret_cast<PFN_SET_OPTION>(::GetProcAddress(m_hHttpStack, "InternetSetOptionW"));
  1378. if (m_pfnSetOption == NULL)
  1379. {
  1380. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetSetOptionW not found");
  1381. goto exit;
  1382. }
  1383. m_pfnOpenUrl =
  1384. reinterpret_cast<PFN_OPEN_URL>(::GetProcAddress(m_hHttpStack, "InternetOpenUrlW"));
  1385. if (m_pfnOpenUrl == NULL)
  1386. {
  1387. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetOpenUrlW not found");
  1388. goto exit;
  1389. }
  1390. m_pfnQueryOption =
  1391. reinterpret_cast<PFN_QUERY_OPTION>(::GetProcAddress(m_hHttpStack, "InternetQueryOptionW"));
  1392. if (m_pfnQueryOption == NULL)
  1393. {
  1394. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetQueryOptionW not found");
  1395. goto exit;
  1396. }
  1397. m_pfnCrack =
  1398. reinterpret_cast<PFN_CRACK_URL>(::GetProcAddress(m_hHttpStack, "InternetCrackUrlW"));
  1399. if (m_pfnCrack == NULL)
  1400. {
  1401. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetCrackUrlW not found");
  1402. goto exit;
  1403. }
  1404. m_pfnReadFile =
  1405. reinterpret_cast<PFN_READ_FILE>(::GetProcAddress(m_hHttpStack, "InternetReadFile"));
  1406. if (m_pfnReadFile == NULL)
  1407. {
  1408. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetReadFile not found");
  1409. goto exit;
  1410. }
  1411. m_pfnStatusCallback =
  1412. reinterpret_cast<PFN_STATUS_CALLBACK>(::GetProcAddress(m_hHttpStack, "InternetSetStatusCallbackW"));
  1413. if (m_pfnStatusCallback == NULL)
  1414. {
  1415. DoTraceMessage(PP_LOG_ERROR, "function entry point InternetSetStatusCallback not found");
  1416. goto exit;
  1417. }
  1418. m_pfnAddHeaders =
  1419. reinterpret_cast<PFN_ADD_HEADERS>(::GetProcAddress(m_hHttpStack, "HttpAddRequestHeadersW"));
  1420. if (m_pfnAddHeaders == NULL)
  1421. {
  1422. DoTraceMessage(PP_LOG_ERROR, "function entry point HttpAddRequestHeaders not found");
  1423. goto exit;
  1424. }
  1425. m_pfnIsHostBypassProxy =
  1426. reinterpret_cast<PFN_IS_HOST_BYPASS_PROXY>(::GetProcAddress(m_hHttpStack, "IsHostInProxyBypassList"));
  1427. if (m_pfnIsHostBypassProxy == NULL)
  1428. {
  1429. DoTraceMessage(PP_LOG_ERROR, "function entry point IsHostInProxyBypassList not found");
  1430. goto exit;
  1431. }
  1432. fRet = TRUE;
  1433. exit:
  1434. return fRet;
  1435. }
  1436. BOOL WININET_SESSION::Open(
  1437. PCWSTR pwszHttpStack,
  1438. HINTERNET hInternet
  1439. )
  1440. {
  1441. PP_ASSERT(pwszHttpStack != NULL);
  1442. DWORD dwErrorCode;
  1443. BOOL fRet = FALSE;
  1444. PFN_INTERNET_OPEN pfnInternetOpen = NULL;
  1445. PP_ASSERT(m_hHttpStack == 0);
  1446. m_hHttpStack = ::LoadLibraryW(pwszHttpStack);
  1447. if (m_hHttpStack == NULL)
  1448. {
  1449. dwErrorCode = ::GetLastError();
  1450. DoTraceMessage(PP_LOG_ERROR, "failed to load library %ws; error = %d", pwszHttpStack, dwErrorCode);
  1451. goto exit;
  1452. }
  1453. if (InitHttpApi(&pfnInternetOpen) == FALSE)
  1454. {
  1455. goto exit;
  1456. }
  1457. if (hInternet)
  1458. {
  1459. m_hInternet = hInternet;
  1460. m_fOwnedSession = FALSE;
  1461. }
  1462. else
  1463. {
  1464. m_hInternet = (*pfnInternetOpen)(
  1465. L"Microsoft.NET-Passport-Authentication-Service/1.4; Q312461",
  1466. INTERNET_OPEN_TYPE_PRECONFIG,
  1467. NULL,
  1468. NULL,
  1469. 0 /*INTERNET_FLAG_ASYNC*/ // biaow-todo: use async
  1470. );
  1471. (*m_pfnSetOption)(m_hInternet, INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT, NULL, 0);
  1472. m_fOwnedSession = TRUE;
  1473. }
  1474. if (m_hInternet == NULL)
  1475. {
  1476. dwErrorCode = ::GetLastError();
  1477. DoTraceMessage(PP_LOG_ERROR, "failed to open an HTTP session through %ws; error = %d",
  1478. pwszHttpStack, dwErrorCode);
  1479. goto exit;
  1480. }
  1481. if (SESSION::Open(pwszHttpStack, hInternet) == FALSE)
  1482. {
  1483. goto exit;
  1484. }
  1485. fRet = TRUE;
  1486. DoTraceMessage(PP_LOG_INFO, "WinInet Http Session opened");
  1487. exit:
  1488. if (!fRet)
  1489. {
  1490. if (m_hInternet && m_fOwnedSession)
  1491. {
  1492. (*m_pfnCloseHandle)(m_hInternet);
  1493. m_hInternet = NULL;
  1494. }
  1495. if (m_hHttpStack)
  1496. {
  1497. ::FreeLibrary(m_hHttpStack);
  1498. m_hHttpStack = NULL;
  1499. }
  1500. DoTraceMessage(PP_LOG_ERROR, "WinInet Http Session failed");
  1501. }
  1502. return fRet;
  1503. }
  1504. void WININET_SESSION::Close(void)
  1505. {
  1506. PP_ASSERT(m_pfnCloseHandle);
  1507. if (m_hInternet && m_fOwnedSession)
  1508. {
  1509. (*m_pfnCloseHandle)(m_hInternet);
  1510. m_pfnCloseHandle = NULL;
  1511. }
  1512. if (m_hHttpStack)
  1513. {
  1514. ::FreeLibrary(m_hHttpStack);
  1515. m_hHttpStack = NULL;
  1516. }
  1517. SESSION::Close();
  1518. DoTraceMessage(PP_LOG_INFO, "WinInet Http Session closed");
  1519. }
  1520. #ifdef PP_DEMO
  1521. BOOL WININET_SESSION::ContactPartner(PCWSTR pwszPartnerUrl,
  1522. PCWSTR pwszVerb,
  1523. PCWSTR pwszHeaders,
  1524. PWSTR pwszData,
  1525. PDWORD pdwDataLength
  1526. )
  1527. {
  1528. BOOL fRet = FALSE;
  1529. HINTERNET hConnect = NULL;
  1530. HINTERNET hRequest = NULL;
  1531. WCHAR ServerName[128];
  1532. WCHAR ObjectPath[1024];
  1533. URL_COMPONENTSW UrlComps;
  1534. ::memset(&UrlComps, 0, sizeof(UrlComps));
  1535. UrlComps.dwStructSize = sizeof(UrlComps) / sizeof(WCHAR);
  1536. UrlComps.lpszHostName = ServerName;
  1537. UrlComps.dwHostNameLength = ARRAYSIZE(ServerName);
  1538. UrlComps.lpszUrlPath = ObjectPath;
  1539. UrlComps.dwUrlPathLength = ARRAYSIZE(ObjectPath);
  1540. PP_ASSERT(m_pfnCrack != NULL);
  1541. if ((*m_pfnCrack)(pwszPartnerUrl,
  1542. 0,
  1543. 0,
  1544. &UrlComps) == FALSE)
  1545. {
  1546. DoTraceMessage(PP_LOG_ERROR,
  1547. "WININET_SESSION::ContactPartner() failed; can not crack the URL %ws",
  1548. pwszPartnerUrl);
  1549. goto exit;
  1550. }
  1551. PP_ASSERT(m_pfnConnect != NULL);
  1552. hConnect = (*m_pfnConnect)(m_hInternet,
  1553. UrlComps.lpszHostName,
  1554. UrlComps.nPort,
  1555. NULL,
  1556. NULL,
  1557. INTERNET_SERVICE_HTTP,
  1558. 0,
  1559. 0);
  1560. if (hConnect == NULL)
  1561. {
  1562. DoTraceMessage(PP_LOG_ERROR,
  1563. "WININET_SESSION::ContactPartner() failed; can not open an HTTP sesstion to %ws:%d",
  1564. UrlComps.lpszHostName, UrlComps.nPort);
  1565. goto exit;
  1566. }
  1567. PP_ASSERT(m_pfnOpenRequest != NULL);
  1568. hRequest = (*m_pfnOpenRequest)(hConnect,
  1569. pwszVerb,
  1570. UrlComps.lpszUrlPath,
  1571. L"HTTP/1.1",
  1572. NULL,
  1573. NULL,
  1574. INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_NO_AUTH,
  1575. 0);
  1576. if (hRequest == NULL)
  1577. {
  1578. DoTraceMessage(PP_LOG_ERROR,
  1579. "WININET_SESSION::ContactPartner() failed; can not open an HTTP request to %ws:(%ws)",
  1580. UrlComps.lpszUrlPath, pwszVerb);
  1581. goto exit;
  1582. }
  1583. PP_ASSERT(m_pfnSendRequest != NULL);
  1584. if ((*m_pfnSendRequest)(hRequest,
  1585. pwszHeaders,
  1586. 0,
  1587. NULL,
  1588. 0) == FALSE)
  1589. {
  1590. DoTraceMessage(PP_LOG_ERROR,
  1591. "WININET_SESSION::ContactPartner() failed; can not send an HTTP request");
  1592. goto exit;
  1593. }
  1594. if (pwszData == NULL)
  1595. {
  1596. fRet = TRUE;
  1597. goto exit;
  1598. }
  1599. DWORD dwStatus, dwStatusLen;
  1600. dwStatusLen = sizeof(dwStatus);
  1601. if (!QueryHeaders(hRequest,
  1602. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  1603. &dwStatus,
  1604. &dwStatusLen))
  1605. {
  1606. DoTraceMessage(PP_LOG_ERROR,
  1607. "WININET_SESSION::ContactPartner() failed; can not query status code");
  1608. goto exit;
  1609. }
  1610. if (dwStatus != HTTP_STATUS_REDIRECT)
  1611. {
  1612. DoTraceMessage(PP_LOG_ERROR,
  1613. "WININET_SESSION::ContactPartner() failed; expecting %d but get %d",
  1614. HTTP_STATUS_REDIRECT, dwStatus);
  1615. goto exit;
  1616. }
  1617. ::wcscpy(pwszData, L"WWW-Authenticate: ");
  1618. if(!QueryHeaders(hRequest,
  1619. HTTP_QUERY_WWW_AUTHENTICATE,
  1620. (LPVOID)(pwszData + ::wcslen(L"WWW-Authenticate: ")),
  1621. pdwDataLength))
  1622. {
  1623. DoTraceMessage(PP_LOG_ERROR,
  1624. "WININET_SESSION::ContactPartner() failed; no auth headers found");
  1625. goto exit;
  1626. }
  1627. (*m_pfnCloseHandle)(hRequest);
  1628. hRequest = NULL;
  1629. (*m_pfnCloseHandle)(hConnect);
  1630. hConnect = NULL;
  1631. fRet = TRUE;
  1632. exit:
  1633. if (hRequest)
  1634. {
  1635. (*m_pfnCloseHandle)(hRequest);
  1636. hRequest = NULL;
  1637. }
  1638. if (hConnect)
  1639. {
  1640. (*m_pfnCloseHandle)(hConnect);
  1641. hConnect = NULL;
  1642. }
  1643. return fRet;
  1644. }
  1645. #endif // PP_DEMO