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.

721 lines
20 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. #include "session.h"
  12. // #include "inetsess.tmh"
  13. SESSION* CreateWinHttpSession(void);
  14. // -----------------------------------------------------------------------------
  15. BOOL SESSION::CreateObject(PCWSTR pwszHttpStack, HINTERNET hSession,
  16. PCWSTR pwszProxyUser,
  17. PCWSTR pwszProxyPass,
  18. SESSION*& pSess)
  19. {
  20. PP_ASSERT(pwszHttpStack != NULL);
  21. pSess = NULL;
  22. if (!::_wcsicmp(pwszHttpStack, L"WinInet.dll") ||
  23. !::_wcsicmp(pwszHttpStack, L"WinInet"))
  24. {
  25. PP_ASSERT(FALSE);
  26. pSess = NULL; // new WININET_SESSION();
  27. }
  28. else
  29. {
  30. pSess = ::CreateWinHttpSession();
  31. }
  32. if (pSess)
  33. {
  34. pSess->SetProxyCreds(pwszProxyUser, pwszProxyPass);
  35. return pSess->Open(pwszHttpStack, hSession);
  36. }
  37. else
  38. {
  39. DoTraceMessage(PP_LOG_ERROR, "CreateObject() failed; not enough memory");
  40. return FALSE;
  41. }
  42. }
  43. // -----------------------------------------------------------------------------
  44. SESSION::SESSION(void)
  45. {
  46. m_hHttpStack = 0;
  47. m_hCredUI = 0;
  48. m_RefCount = 0;
  49. m_pfnReadDomainCred = NULL;
  50. m_pfnCredFree = NULL;
  51. m_hKeyLM = NULL;
  52. m_fLogout = FALSE;
  53. m_wDefaultDAUrl[0] = 0;
  54. m_wCurrentDAUrl[0] = 0;
  55. m_wCurrentDAHost[0] = 0;
  56. m_wDARealm[0] = 0;
  57. m_LastNexusDownloadTime = 0xFFFFFFFF;
  58. m_pwszProxyUser = NULL;
  59. m_pwszProxyPass = NULL;
  60. m_dwVersion = 0;
  61. InitializeListHead(&m_DAMap);
  62. }
  63. // -----------------------------------------------------------------------------
  64. SESSION::~SESSION(void)
  65. {
  66. if (m_pwszProxyUser)
  67. {
  68. SecureZeroMemory((void*)m_pwszProxyUser,sizeof(m_pwszProxyUser[0])*wcslen(m_pwszProxyUser));
  69. delete [] m_pwszProxyUser;
  70. }
  71. if (m_pwszProxyPass)
  72. {
  73. SecureZeroMemory((void*)m_pwszProxyPass,sizeof(m_pwszProxyPass[0])*wcslen(m_pwszProxyPass));
  74. delete [] m_pwszProxyPass;
  75. }
  76. }
  77. BOOL SESSION::GetDAInfoFromPPNexus(
  78. )
  79. {
  80. BOOL fRetVal = FALSE;
  81. HINTERNET hRequest = NULL;
  82. HINTERNET hConnect = NULL;
  83. DWORD dwError;
  84. WCHAR wNexusHost[128] = L"nexus.passport.com";
  85. DWORD dwHostLen = sizeof(wNexusHost); // note: size of the buffer, not # of UNICODE characters
  86. WCHAR wNexusObj[128] = L"rdr/pprdr.asp";
  87. DWORD dwObjLen = sizeof(wNexusObj);
  88. PWSTR pwszPassportUrls = NULL;
  89. DWORD dwUrlsLen = 0;
  90. DWORD dwValueType;
  91. WCHAR Delimiters[] = L",";
  92. PWSTR Token = NULL;
  93. // we allow only one Nexus contact per session to avoid infinite loop due to Nexus misconfiguration
  94. DWORD dwCurrentTime = ::GetTickCount();
  95. if ((dwCurrentTime >= m_LastNexusDownloadTime) &&
  96. (dwCurrentTime - m_LastNexusDownloadTime < 5*60*1000)) // 5 minutes
  97. {
  98. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() failed: Nexus info already downloaded");
  99. goto exit;
  100. }
  101. if (m_hKeyLM)
  102. {
  103. dwError = ::RegQueryValueExW(m_hKeyLM,
  104. L"NexusHost",
  105. 0,
  106. &dwValueType,
  107. reinterpret_cast<LPBYTE>(wNexusHost),
  108. &dwHostLen);
  109. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  110. dwError = ::RegQueryValueExW(m_hKeyLM,
  111. L"NexusObj",
  112. 0,
  113. &dwValueType,
  114. reinterpret_cast<LPBYTE>(wNexusObj),
  115. &dwObjLen);
  116. PP_ASSERT(!(dwError == ERROR_MORE_DATA));
  117. }
  118. hConnect = Connect(wNexusHost,
  119. INTERNET_DEFAULT_HTTPS_PORT
  120. );
  121. if (hConnect == NULL)
  122. {
  123. DWORD dwErrorCode = ::GetLastError();
  124. DoTraceMessage(PP_LOG_ERROR,
  125. "SESSION::GetDAInfoFromPPNexus(): failed to connect to %ws; Error = %d",
  126. wNexusHost, dwErrorCode);
  127. goto exit;
  128. }
  129. hRequest = OpenRequest(hConnect,
  130. NULL,
  131. wNexusObj,
  132. WINHTTP_FLAG_SECURE
  133. );
  134. if (hRequest == NULL)
  135. {
  136. DWORD dwErrorCode = ::GetLastError();
  137. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; OpenRequest() to %ws failed, Error Code = %d",
  138. wNexusObj, dwErrorCode);
  139. goto exit;
  140. }
  141. if (m_pwszProxyUser && m_pwszProxyPass)
  142. {
  143. SetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, (void*)m_pwszProxyUser, wcslen(m_pwszProxyUser) + 1);
  144. SetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (void*)m_pwszProxyPass, wcslen(m_pwszProxyPass) + 1);
  145. }
  146. if (!SendRequest(hRequest, NULL, 0))
  147. {
  148. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus(): failed");
  149. goto exit;
  150. }
  151. if (ReceiveResponse(hRequest) == FALSE)
  152. {
  153. DWORD dwErrorCode = ::GetLastError();
  154. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; ReceiveResponse() failed, Error Code = %d",
  155. dwErrorCode);
  156. goto exit;
  157. }
  158. if (QueryHeaders(hRequest,
  159. WINHTTP_QUERY_PASSPORT_URLS,
  160. 0,
  161. &dwUrlsLen) == FALSE)
  162. {
  163. if ((::GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwUrlsLen == 0))
  164. {
  165. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
  166. goto exit;
  167. }
  168. }
  169. else
  170. {
  171. PP_ASSERT(FALSE); // should not reach here
  172. }
  173. pwszPassportUrls = new WCHAR[dwUrlsLen];
  174. if (pwszPassportUrls == NULL)
  175. {
  176. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; insufficient memory");
  177. goto exit;
  178. }
  179. if (QueryHeaders(hRequest,
  180. WINHTTP_QUERY_PASSPORT_URLS,
  181. pwszPassportUrls,
  182. &dwUrlsLen) == FALSE)
  183. {
  184. DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
  185. goto exit;
  186. }
  187. Token = ::wcstok(pwszPassportUrls, Delimiters);
  188. while (Token != NULL)
  189. {
  190. // skip leading white spaces
  191. while (*Token == (L" ")[0]) { ++Token; }
  192. if (*Token == L'\0')
  193. {
  194. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no text in between commas");
  195. goto next_token;
  196. }
  197. // find DALocation
  198. if (!::_wcsnicmp(Token, L"DALogin", ::wcslen(L"DALogin")))
  199. {
  200. PWSTR pwszDAUrl = ::wcsstr(Token, L"=");
  201. if (pwszDAUrl == NULL)
  202. {
  203. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DALocation");
  204. goto exit;
  205. }
  206. pwszDAUrl++; // skip "="
  207. while (*pwszDAUrl == (L" ")[0]) { ++pwszDAUrl; } // skip leading white spaces
  208. if (*pwszDAUrl == L'\0')
  209. {
  210. goto exit;
  211. }
  212. ::wcscpy(m_wDefaultDAUrl, L"https://");
  213. ::wcsncat(m_wDefaultDAUrl, pwszDAUrl, MAX_PASSPORT_URL_LENGTH - 8);
  214. m_LastNexusDownloadTime = ::GetTickCount();
  215. fRetVal = TRUE;
  216. DoTraceMessage(PP_LOG_INFO, "DALocation URL %ws found", m_wDefaultDAUrl);
  217. }
  218. else if (!::_wcsnicmp(Token, L"DARealm", ::wcslen(L"DARealm")))
  219. {
  220. PWSTR pwszDARealm = ::wcsstr(Token, L"=");
  221. if (pwszDARealm == NULL)
  222. {
  223. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DARealm");
  224. goto exit;
  225. }
  226. pwszDARealm++; // skip "="
  227. while (*pwszDARealm == (L" ")[0]) { ++pwszDARealm; } // skip leading white spaces
  228. if (*pwszDARealm == L'\0')
  229. {
  230. goto exit;
  231. }
  232. ::wcsncpy(m_wDARealm, pwszDARealm, MAX_PASSPORT_REALM_LENGTH);
  233. m_wDARealm[MAX_PASSPORT_REALM_LENGTH] = 0;
  234. DoTraceMessage(PP_LOG_INFO, "DARealm URL %ws found", m_wDefaultDAUrl);
  235. }
  236. else if (!::_wcsnicmp(Token, L"ConfigVersion", ::wcslen(L"ConfigVersion")))
  237. {
  238. PWSTR pwszConfigVersion = ::wcsstr(Token, L"=");
  239. if (pwszConfigVersion == NULL)
  240. {
  241. DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after ConfigVersion");
  242. goto exit;
  243. }
  244. pwszConfigVersion++; // skip "="
  245. while (*pwszConfigVersion == (L" ")[0]) { ++pwszConfigVersion; } // skip leading white spaces
  246. if (*pwszConfigVersion == L'\0')
  247. {
  248. goto exit;
  249. }
  250. m_dwVersion = _wtoi(pwszConfigVersion);
  251. DoTraceMessage(PP_LOG_INFO, "ConfigVersion URL %ws found", m_wDefaultDAUrl);
  252. }
  253. next_token:
  254. Token = ::wcstok(NULL, Delimiters);
  255. }
  256. exit:
  257. if (pwszPassportUrls)
  258. {
  259. delete [] pwszPassportUrls;
  260. }
  261. if (hRequest)
  262. {
  263. CloseHandle(hRequest);
  264. }
  265. if (hConnect)
  266. {
  267. CloseHandle(hConnect);
  268. }
  269. return fRetVal;
  270. }
  271. BOOL SESSION::GetRealm(
  272. PWSTR pwszRealm, // user supplied buffer ...
  273. PDWORD pdwRealmLen // ... and length (will be updated to actual length
  274. // on successful return)
  275. ) const
  276. {
  277. DWORD RealmLen = sizeof(m_wDARealm);
  278. DWORD dwValueType;
  279. PWSTR pwszDARealm = const_cast<PWSTR>(&m_wDARealm[0]);
  280. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  281. L"LoginServerRealm",
  282. 0,
  283. &dwValueType,
  284. reinterpret_cast<LPBYTE>(pwszDARealm),
  285. &RealmLen) == ERROR_SUCCESS)
  286. {
  287. ;
  288. }
  289. if (!m_wDARealm[0])
  290. {
  291. *pdwRealmLen = 0;
  292. return FALSE;
  293. }
  294. if (!pwszRealm)
  295. {
  296. *pdwRealmLen = ::wcslen(m_wDARealm) + 1;
  297. return FALSE;
  298. }
  299. if (*pdwRealmLen < (DWORD)::wcslen(m_wDARealm) + 1)
  300. {
  301. *pdwRealmLen = ::wcslen(m_wDARealm) + 1;
  302. return FALSE;
  303. }
  304. ::wcscpy(pwszRealm, m_wDARealm);
  305. *pdwRealmLen = ::wcslen(m_wDARealm) + 1;
  306. return TRUE;
  307. }
  308. DWORD SESSION::GetNexusVersion(void)
  309. {
  310. DWORD dwValueType;
  311. DWORD dwVerLen = sizeof(m_dwVersion);
  312. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  313. L"ConfigVersion",
  314. 0,
  315. &dwValueType,
  316. reinterpret_cast<LPBYTE>(&m_dwVersion),
  317. &dwVerLen) == ERROR_SUCCESS)
  318. {
  319. ;
  320. }
  321. return m_dwVersion;
  322. }
  323. BOOL SESSION::UpdateDAInfo(
  324. PCWSTR pwszSignIn,
  325. PCWSTR pwszDAUrl
  326. )
  327. {
  328. BOOL fRet = FALSE;
  329. if (pwszSignIn)
  330. {
  331. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  332. if (pwszDomain)
  333. {
  334. BOOL fFound = FALSE;
  335. for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
  336. entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
  337. entry = entry->Flink)
  338. {
  339. P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
  340. if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
  341. {
  342. fFound = TRUE;
  343. ::wcsncpy(pDAEntry->wDA, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
  344. pDAEntry->wDA[MAX_PASSPORT_URL_LENGTH] = 0;
  345. fRet = TRUE;
  346. break;
  347. }
  348. }
  349. if (!fFound)
  350. {
  351. P_DA_ENTRY pDAEntry = new DA_ENTRY;
  352. if (pDAEntry)
  353. {
  354. ::wcsncpy(pDAEntry->wDomain, pwszDomain, MAX_PASSPORT_DOMAIN_LENGTH);
  355. pDAEntry->wDomain[MAX_PASSPORT_DOMAIN_LENGTH] = 0;
  356. ::wcsncpy(pDAEntry->wDA, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
  357. pDAEntry->wDA[MAX_PASSPORT_URL_LENGTH] = 0;
  358. InsertHeadList(&m_DAMap, (PLIST_ENTRY)pDAEntry);
  359. fRet = TRUE;
  360. }
  361. }
  362. }
  363. }
  364. return fRet;
  365. }
  366. BOOL SESSION::PurgeDAInfo(PCWSTR pwszSignIn)
  367. {
  368. if (pwszSignIn == NULL)
  369. {
  370. return TRUE;
  371. }
  372. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  373. if (pwszDomain)
  374. {
  375. for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
  376. entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
  377. entry = entry->Flink)
  378. {
  379. P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
  380. if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
  381. {
  382. RemoveEntryList(entry);
  383. delete pDAEntry;
  384. break;
  385. }
  386. }
  387. }
  388. return TRUE;
  389. }
  390. BOOL SESSION::GetDAInfo(PCWSTR pwszSignIn,
  391. LPWSTR pwszDAHostName,
  392. DWORD HostNameLen,
  393. LPWSTR pwszDAHostObj,
  394. DWORD HostObjLen)
  395. {
  396. LPCWSTR pwszDAUrl = m_wDefaultDAUrl;
  397. if (pwszSignIn)
  398. {
  399. LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
  400. if (pwszDomain)
  401. {
  402. for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
  403. entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
  404. entry = entry->Flink)
  405. {
  406. P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
  407. if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
  408. {
  409. pwszDAUrl = pDAEntry->wDA;
  410. break;
  411. }
  412. }
  413. }
  414. }
  415. ::wcsncpy(m_wCurrentDAUrl, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
  416. m_wCurrentDAUrl[MAX_PASSPORT_URL_LENGTH] = 0;
  417. URL_COMPONENTSW UrlComps;
  418. ::memset(&UrlComps, 0, sizeof(UrlComps));
  419. UrlComps.dwStructSize = sizeof(UrlComps);
  420. UrlComps.lpszHostName = pwszDAHostName;
  421. UrlComps.dwHostNameLength = HostNameLen;
  422. UrlComps.lpszUrlPath = pwszDAHostObj;
  423. UrlComps.dwUrlPathLength = HostObjLen;
  424. if (CrackUrl(pwszDAUrl,
  425. 0,
  426. 0,
  427. &UrlComps) == FALSE)
  428. {
  429. DoTraceMessage(PP_LOG_ERROR,
  430. "WININET_SESSION::GetDAInfo() failed; can not crack the URL %ws",
  431. pwszDAUrl);
  432. return FALSE;
  433. }
  434. ::wcsncpy(m_wCurrentDAHost, UrlComps.lpszHostName, MAX_PASSPORT_HOST_LENGTH);
  435. m_wCurrentDAHost[MAX_PASSPORT_HOST_LENGTH] = 0;
  436. return TRUE;
  437. }
  438. BOOL SESSION::GetCachedCreds(
  439. PCWSTR pwszRealm,
  440. PCWSTR pwszTarget,
  441. PCREDENTIALW** pppCreds,
  442. DWORD* pdwCreds
  443. )
  444. {
  445. *pppCreds = NULL;
  446. *pdwCreds = 0;
  447. if (m_pfnReadDomainCred == NULL)
  448. {
  449. return FALSE;
  450. }
  451. ULONG CredTypes = CRED_TYPE_DOMAIN_VISIBLE_PASSWORD;
  452. DWORD dwFlags = CRED_CACHE_TARGET_INFORMATION;
  453. CREDENTIAL_TARGET_INFORMATIONW TargetInfo;
  454. memset ( (void*)&TargetInfo, 0, sizeof(CREDENTIAL_TARGET_INFORMATIONW));
  455. TargetInfo.TargetName = const_cast<PWSTR>(pwszTarget);
  456. TargetInfo.DnsDomainName = const_cast<PWSTR>(pwszRealm);
  457. TargetInfo.PackageName = L"Passport1.4";
  458. TargetInfo.Flags = 0;
  459. TargetInfo.CredTypeCount = 1;
  460. TargetInfo.CredTypes = &CredTypes;
  461. if ((*m_pfnReadDomainCred)(&TargetInfo,
  462. dwFlags,
  463. pdwCreds,
  464. pppCreds ) != TRUE)
  465. {
  466. *pppCreds = NULL;
  467. *pdwCreds = 0;
  468. }
  469. else
  470. {
  471. if (IsLoggedOut())
  472. {
  473. FILETIME LogoutTimestamp;
  474. ::SystemTimeToFileTime(GetLogoutTimeStamp(), &LogoutTimestamp);
  475. if (::CompareFileTime(&((**pppCreds)->LastWritten), &LogoutTimestamp) == -1)
  476. {
  477. // the cred is entered/created earlier (less) than the Logout request. It is no good.
  478. m_pfnCredFree(*pppCreds);
  479. *pppCreds = NULL;
  480. *pdwCreds = 0;
  481. }
  482. else
  483. {
  484. ResetLogoutFlag();
  485. }
  486. }
  487. }
  488. return (*pppCreds != NULL );
  489. }
  490. BOOL SESSION::Open(PCWSTR /*pwszHttpStack*/, HINTERNET)
  491. {
  492. BOOL fRetVal = FALSE;
  493. DWORD dwValueType;
  494. DWORD dwUrlLen = sizeof(m_wDefaultDAUrl); // note: size of the buffer, not # of UNICODE characters
  495. BOOL fDAInfoCached = FALSE; // assume NO DA info's cached locally
  496. ::RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  497. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\WinHttp\\Passport Test",
  498. 0,
  499. NULL,
  500. REG_OPTION_NON_VOLATILE,
  501. KEY_READ,
  502. NULL,
  503. &m_hKeyLM,
  504. NULL);
  505. if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
  506. L"LoginServerUrl",
  507. 0,
  508. &dwValueType,
  509. reinterpret_cast<LPBYTE>(m_wDefaultDAUrl),
  510. &dwUrlLen) == ERROR_SUCCESS)
  511. {
  512. fDAInfoCached = TRUE;
  513. }
  514. if (!fDAInfoCached || (::wcslen(m_wDefaultDAUrl) == ::wcslen(L"")))
  515. {
  516. if (GetDAInfoFromPPNexus() == FALSE)
  517. {
  518. goto exit;
  519. }
  520. }
  521. m_hCredUI = ::LoadLibraryW(L"advapi32.dll");
  522. if (m_hCredUI)
  523. {
  524. m_pfnReadDomainCred =
  525. reinterpret_cast<PFN_READ_DOMAIN_CRED_W>(::GetProcAddress(m_hCredUI, "CredReadDomainCredentialsW"));
  526. if (m_pfnReadDomainCred == NULL)
  527. {
  528. DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredReadDomainCredentialsW()");
  529. }
  530. m_pfnCredFree =
  531. reinterpret_cast<PFN_CRED_FREE>(::GetProcAddress(m_hCredUI, "CredFree"));
  532. if (m_pfnCredFree == NULL)
  533. {
  534. DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredFree()");
  535. }
  536. }
  537. fRetVal = TRUE;
  538. exit:
  539. return fRetVal;
  540. }
  541. void SESSION::Logout(void)
  542. {
  543. if (!m_fLogout)
  544. {
  545. m_fLogout = TRUE;
  546. ::GetSystemTime(&m_LogoutTimeStamp);
  547. SetOption(m_hInternet,
  548. WINHTTP_OPTION_PASSPORT_SIGN_OUT,
  549. m_wCurrentDAUrl,
  550. ::wcslen(m_wCurrentDAUrl) + 1);
  551. }
  552. }
  553. BOOL SESSION::IsLoggedOut(void) const
  554. {
  555. return m_fLogout;
  556. }
  557. void SESSION::ResetLogoutFlag(void)
  558. {
  559. m_fLogout = FALSE;
  560. }
  561. const SYSTEMTIME* SESSION::GetLogoutTimeStamp(void) const
  562. {
  563. return &m_LogoutTimeStamp;
  564. }
  565. void SESSION::Close(void)
  566. {
  567. if (m_hCredUI)
  568. {
  569. ::FreeLibrary(m_hCredUI);
  570. m_hCredUI = NULL;
  571. }
  572. if (m_hKeyLM)
  573. {
  574. ::RegCloseKey(m_hKeyLM);
  575. }
  576. PurgeAllDAInfo();
  577. }
  578. BOOL SESSION::PurgeAllDAInfo(void)
  579. {
  580. while (!IsListEmpty(&m_DAMap))
  581. {
  582. PLIST_ENTRY pEntry = RemoveHeadList(&m_DAMap);
  583. P_DA_ENTRY pDAEntry = (P_DA_ENTRY)pEntry;
  584. delete pDAEntry;
  585. }
  586. return TRUE;
  587. }