Source code of Windows XP (NT5)
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.

956 lines
20 KiB

  1. /*++
  2. Copyright (C) 1992-98 Microsft Corporation. All rights reserved.
  3. Module Name:
  4. dlparams.c
  5. Abstract:
  6. Routines for storing and retrieving user Lsa secret
  7. dial parameters.
  8. Author:
  9. Gurdeep Singh Pall (gurdeep) 06-Jun-1997
  10. Revision History:
  11. Miscellaneous Modifications - raos 31-Dec-1997
  12. --*/
  13. #define RASMXS_DYNAMIC_LINK
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <ntlsa.h>
  18. #include <ntmsv1_0.h>
  19. #include <llinfo.h>
  20. #include <rasman.h>
  21. #include <lm.h>
  22. #include <lmwksta.h>
  23. #include <wanpub.h>
  24. #include <raserror.h>
  25. // #include <rasarp.h>
  26. #include <media.h>
  27. #include <device.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <ntlsa.h>
  31. #define MAX_REGISTRY_VALUE_LENGTH ((64*1024) - 1)
  32. #define cszEapKeyRas TEXT("Software\\Microsoft\\RAS EAP\\UserEapInfo")
  33. #define cszEapKeyRouter TEXT("Software\\Microsoft\\Router EAP\\IfEapInfo")
  34. #define cszEapValue TEXT("EapInfo")
  35. #define EAP_SIG 0x31504145
  36. #define EAP_SIG_2 0x32504145
  37. typedef struct _EAP_USER_INFO
  38. {
  39. DWORD dwSignature;
  40. DWORD dwEapTypeId;
  41. GUID Guid;
  42. DWORD dwSize;
  43. BYTE abdata[1];
  44. } EAP_USER_INFO, *PEAP_USER_INFO;
  45. typedef struct _EAP_USER_INFO_0
  46. {
  47. DWORD dwUID;
  48. DWORD dwSize;
  49. BYTE abdata[1];
  50. } EAP_USER_INFO_0, *PEAP_USER_INFO_0;
  51. DWORD
  52. DwGetSidFromHtoken(
  53. HANDLE hToken,
  54. PWCHAR pszSid,
  55. USHORT cbSid
  56. )
  57. {
  58. DWORD cbNeeded, dwErr;
  59. BOOL fThreadTokenOpened = FALSE;
  60. UNICODE_STRING unicodeString;
  61. TOKEN_USER *pUserToken = NULL;
  62. if( (NULL == hToken)
  63. || (INVALID_HANDLE_VALUE == hToken))
  64. {
  65. fThreadTokenOpened = TRUE;
  66. if (!OpenThreadToken(
  67. GetCurrentThread(),
  68. TOKEN_QUERY,
  69. TRUE,
  70. &hToken))
  71. {
  72. dwErr = GetLastError();
  73. if (dwErr == ERROR_NO_TOKEN)
  74. {
  75. //
  76. // This means we are not impersonating
  77. // anyone. Instead, get the token out
  78. // of the process.
  79. //
  80. if (!OpenProcessToken(
  81. GetCurrentProcess(),
  82. TOKEN_QUERY,
  83. &hToken))
  84. {
  85. return GetLastError();
  86. }
  87. }
  88. else
  89. {
  90. return dwErr;
  91. }
  92. }
  93. }
  94. //
  95. // Call GetTokenInformation once to determine
  96. // the number of bytes needed.
  97. //
  98. cbNeeded = 0;
  99. GetTokenInformation(hToken,
  100. TokenUser,
  101. NULL, 0,
  102. &cbNeeded);
  103. if (!cbNeeded)
  104. {
  105. dwErr = GetLastError();
  106. goto done;
  107. }
  108. //
  109. // Allocate the memory and call it again.
  110. //
  111. pUserToken = LocalAlloc(LPTR, cbNeeded);
  112. if (pUserToken == NULL)
  113. {
  114. return GetLastError();
  115. }
  116. if (!GetTokenInformation(
  117. hToken,
  118. TokenUser,
  119. pUserToken,
  120. cbNeeded,
  121. &cbNeeded))
  122. {
  123. dwErr = GetLastError();
  124. goto done;
  125. }
  126. //
  127. // Format the SID as a Unicode string.
  128. //
  129. unicodeString.Length = 0;
  130. unicodeString.MaximumLength = cbSid;
  131. unicodeString.Buffer = pszSid;
  132. dwErr = RtlConvertSidToUnicodeString(
  133. &unicodeString,
  134. pUserToken->User.Sid,
  135. FALSE);
  136. done:
  137. if (pUserToken != NULL)
  138. {
  139. LocalFree(pUserToken);
  140. }
  141. if ( (NULL != hToken)
  142. && (INVALID_HANDLE_VALUE != hToken)
  143. && fThreadTokenOpened)
  144. {
  145. CloseHandle(hToken);
  146. }
  147. return dwErr;
  148. }
  149. DWORD
  150. GetUserSid(
  151. IN PWCHAR pszSid,
  152. IN USHORT cbSid
  153. )
  154. {
  155. return DwGetSidFromHtoken(NULL,
  156. pszSid,
  157. cbSid);
  158. }
  159. LONG
  160. lrGetEapKeyFromToken(HANDLE hToken,
  161. HKEY *phkey)
  162. {
  163. LONG lr = ERROR_SUCCESS;
  164. WCHAR szSid[260];
  165. HKEY hkeyUser = NULL;
  166. HKEY hkeyEap = NULL;
  167. DWORD dwDisposition;
  168. ASSERT(NULL != phkey);
  169. //
  170. // Get sid of the user from the htoken
  171. //
  172. lr = (LONG) DwGetSidFromHtoken(hToken,
  173. szSid,
  174. sizeof(szSid));
  175. if(ERROR_SUCCESS != lr)
  176. {
  177. goto done;
  178. }
  179. //
  180. // Open the users registry key
  181. //
  182. lr = RegOpenKeyExW(HKEY_USERS,
  183. szSid,
  184. 0,
  185. KEY_ALL_ACCESS,
  186. &hkeyUser);
  187. if(ERROR_SUCCESS != lr)
  188. {
  189. goto done;
  190. }
  191. //
  192. // Create the eap key if required.
  193. //
  194. lr = RegCreateKeyEx(hkeyUser,
  195. cszEapKeyRas,
  196. 0,
  197. NULL,
  198. REG_OPTION_NON_VOLATILE,
  199. KEY_ALL_ACCESS,
  200. NULL,
  201. &hkeyEap,
  202. &dwDisposition);
  203. if(ERROR_SUCCESS != lr)
  204. {
  205. goto done;
  206. }
  207. done:
  208. if(NULL != hkeyUser)
  209. {
  210. RegCloseKey(hkeyUser);
  211. }
  212. *phkey = hkeyEap;
  213. return lr;
  214. }
  215. DWORD
  216. DwUpgradeEapInfo(PBYTE *ppbInfo,
  217. DWORD *pdwSize)
  218. {
  219. BYTE *pbInfo;
  220. DWORD dwErr = ERROR_SUCCESS;
  221. EAP_USER_INFO UNALIGNED *pEapInfo;
  222. DWORD dwSize;
  223. DWORD dwRequiredSize = 0;
  224. BYTE *pbNewInfo = NULL;
  225. EAP_USER_INFO *pNewEapInfo;
  226. if( (NULL == ppbInfo)
  227. || (NULL == pdwSize))
  228. {
  229. dwErr = E_INVALIDARG;
  230. goto done;
  231. }
  232. dwSize = *pdwSize;
  233. pbInfo = *ppbInfo;
  234. pEapInfo = (EAP_USER_INFO *) pbInfo;
  235. while((BYTE *) pEapInfo < pbInfo + dwSize)
  236. {
  237. dwRequiredSize += RASMAN_ALIGN8(
  238. sizeof(EAP_USER_INFO)
  239. + pEapInfo->dwSize);
  240. ((PBYTE) pEapInfo) += (sizeof(EAP_USER_INFO)
  241. + pEapInfo->dwSize);
  242. }
  243. pbNewInfo = LocalAlloc(LPTR, dwRequiredSize);
  244. if(NULL == pbNewInfo)
  245. {
  246. dwErr = GetLastError();
  247. goto done;
  248. }
  249. pEapInfo = (EAP_USER_INFO *) pbInfo;
  250. pNewEapInfo = (EAP_USER_INFO *) pbNewInfo;
  251. while((BYTE *) pEapInfo < pbInfo + dwSize)
  252. {
  253. CopyMemory(
  254. (BYTE *) pNewEapInfo,
  255. (BYTE *) pEapInfo,
  256. sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
  257. pNewEapInfo->dwSignature = EAP_SIG_2;
  258. (BYTE *) pNewEapInfo += RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  259. + pEapInfo->dwSize);
  260. (BYTE *) pEapInfo += (sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
  261. }
  262. *ppbInfo = pbNewInfo;
  263. *pdwSize = dwRequiredSize;
  264. if(NULL != pbInfo)
  265. {
  266. LocalFree(pbInfo);
  267. }
  268. done:
  269. return dwErr;
  270. }
  271. DWORD
  272. DwGetEapInfo(HANDLE hToken,
  273. BOOL fRouter,
  274. PBYTE *ppbInfo,
  275. DWORD *pdwSize,
  276. HKEY *phkey
  277. )
  278. {
  279. LONG lr = ERROR_SUCCESS;
  280. HKEY hkey = NULL;
  281. DWORD dwDisposition;
  282. DWORD dwInfoSize = 0;
  283. DWORD dwType;
  284. PBYTE pbInfo = NULL;
  285. if( (NULL == ppbInfo)
  286. || (NULL == pdwSize))
  287. {
  288. lr = (LONG) E_INVALIDARG;
  289. goto done;
  290. }
  291. if( (NULL != hToken)
  292. && (INVALID_HANDLE_VALUE != hToken)
  293. && !fRouter)
  294. {
  295. //
  296. // If a valid token is passed then its most likely
  297. // a service trying to open users registry. Get the
  298. // sid of the user and open HKU in this case.
  299. //
  300. if(ERROR_SUCCESS != (lr = lrGetEapKeyFromToken(hToken,
  301. &hkey)))
  302. {
  303. goto done;
  304. }
  305. }
  306. else
  307. {
  308. //
  309. // Open the key. Create the key if its not present
  310. //
  311. if(ERROR_SUCCESS != (lr = RegCreateKeyEx(
  312. (fRouter)
  313. ? HKEY_LOCAL_MACHINE
  314. : HKEY_CURRENT_USER,
  315. (fRouter)
  316. ? cszEapKeyRouter
  317. : cszEapKeyRas,
  318. 0,
  319. NULL,
  320. REG_OPTION_NON_VOLATILE,
  321. KEY_ALL_ACCESS,
  322. NULL,
  323. &hkey,
  324. &dwDisposition)))
  325. {
  326. goto done;
  327. }
  328. }
  329. //
  330. // Get size of the binary value. If the value is not
  331. // found, return no information. This value will be
  332. // set the first time we store any eap information.
  333. //
  334. if( (ERROR_SUCCESS != (lr = RegQueryValueEx(
  335. hkey,
  336. cszEapValue,
  337. NULL,
  338. &dwType,
  339. NULL,
  340. &dwInfoSize)))
  341. && (ERROR_SUCCESS != lr))
  342. {
  343. goto done;
  344. }
  345. #if DBG
  346. ASSERT(REG_BINARY == dwType);
  347. #endif
  348. //
  349. // Allocate a buffer to hold the binary value
  350. //
  351. pbInfo = LocalAlloc(LPTR, dwInfoSize);
  352. if(NULL == pbInfo)
  353. {
  354. lr = (LONG) GetLastError();
  355. goto done;
  356. }
  357. //
  358. // Get the binary value
  359. //
  360. if(ERROR_SUCCESS != (lr = RegQueryValueEx(
  361. hkey,
  362. cszEapValue,
  363. NULL,
  364. &dwType,
  365. pbInfo,
  366. &dwInfoSize)))
  367. {
  368. goto done;
  369. }
  370. done:
  371. if(NULL != phkey)
  372. {
  373. *phkey = hkey;
  374. }
  375. else if (NULL != hkey)
  376. {
  377. RegCloseKey(hkey);
  378. }
  379. if(NULL != ppbInfo)
  380. {
  381. *ppbInfo = pbInfo;
  382. }
  383. else if(NULL != pbInfo)
  384. {
  385. LocalFree(pbInfo);
  386. }
  387. if(NULL != pdwSize)
  388. {
  389. *pdwSize = dwInfoSize;
  390. }
  391. if(ERROR_FILE_NOT_FOUND == lr)
  392. {
  393. lr = ERROR_SUCCESS;
  394. }
  395. return (DWORD) lr;
  396. }
  397. DWORD
  398. DwSetEapInfo(HKEY hkey,
  399. PBYTE pbInfo,
  400. DWORD dwSize)
  401. {
  402. LONG lr = ERROR_SUCCESS;
  403. if(ERROR_SUCCESS != (lr = RegSetValueEx(
  404. hkey,
  405. cszEapValue,
  406. 0,
  407. REG_BINARY,
  408. pbInfo,
  409. dwSize)))
  410. {
  411. goto done;
  412. }
  413. done:
  414. return (DWORD) lr;
  415. }
  416. DWORD
  417. DwRemoveEapUserInfo(GUID *pGuid,
  418. PBYTE pbInfo,
  419. PDWORD pdwSize,
  420. HKEY hkey,
  421. BOOL fWrite,
  422. DWORD dwEapTypeId)
  423. {
  424. DWORD dwErr = ERROR_SUCCESS;
  425. DWORD dwcb = 0;
  426. EAP_USER_INFO *pEapInfo = (EAP_USER_INFO *) pbInfo;
  427. DWORD dwNewSize;
  428. DWORD dwSize = *pdwSize;
  429. //
  430. // Find the binary blob with the
  431. // UID
  432. //
  433. while(dwcb < dwSize)
  434. {
  435. if( (0 == memcmp(
  436. (PBYTE) pGuid,
  437. (PBYTE) &pEapInfo->Guid,
  438. sizeof(GUID)))
  439. && (dwEapTypeId == pEapInfo->dwEapTypeId))
  440. {
  441. break;
  442. }
  443. dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
  444. pEapInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
  445. }
  446. if(dwcb >= dwSize)
  447. {
  448. goto done;
  449. }
  450. #if DBG
  451. ASSERT(dwSize >= dwcb
  452. + RASMAN_ALIGN8(pEapInfo->dwSize
  453. + sizeof(EAP_USER_INFO)));
  454. #endif
  455. dwNewSize = dwSize -
  456. RASMAN_ALIGN8(pEapInfo->dwSize + sizeof(EAP_USER_INFO));
  457. //
  458. // Remove the info
  459. //
  460. MoveMemory(
  461. pbInfo + dwcb,
  462. pbInfo + dwcb
  463. + RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize),
  464. dwSize - dwcb
  465. - RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
  466. if(fWrite)
  467. {
  468. dwErr = DwSetEapInfo(
  469. hkey,
  470. pbInfo,
  471. dwNewSize);
  472. }
  473. else
  474. {
  475. *pdwSize = dwNewSize;
  476. }
  477. done:
  478. return dwErr;
  479. }
  480. DWORD
  481. DwReplaceEapUserInfo(GUID *pGuid,
  482. PBYTE pbUserInfo,
  483. DWORD dwUserInfo,
  484. PBYTE pbInfo,
  485. DWORD dwSize,
  486. HKEY hkey,
  487. DWORD dwEapTypeId)
  488. {
  489. DWORD dwErr = ERROR_SUCCESS;
  490. DWORD dwNewSize = dwSize;
  491. PBYTE pbNewInfo = NULL;
  492. EAP_USER_INFO UNALIGNED *pEapInfo;
  493. if(NULL == pGuid)
  494. {
  495. ASSERT(FALSE);
  496. goto done;
  497. }
  498. //
  499. // Remove the existing eap information corresponding
  500. // to dwUID if any.
  501. //
  502. if(ERROR_SUCCESS != (dwErr = DwRemoveEapUserInfo(
  503. pGuid,
  504. pbInfo,
  505. &dwNewSize,
  506. hkey,
  507. FALSE,
  508. dwEapTypeId)))
  509. {
  510. goto done;
  511. }
  512. //
  513. // Local Alloc a new blob with enough space for the
  514. // eap information of the new entry
  515. //
  516. pbNewInfo = LocalAlloc(LPTR,
  517. dwNewSize
  518. + RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  519. + dwUserInfo));
  520. if(NULL == pbNewInfo)
  521. {
  522. dwErr = GetLastError();
  523. goto done;
  524. }
  525. RtlCopyMemory(
  526. pbNewInfo,
  527. pbInfo,
  528. dwNewSize);
  529. pEapInfo = (EAP_USER_INFO *) (pbNewInfo + dwNewSize);
  530. pEapInfo->Guid = *pGuid;
  531. pEapInfo->dwEapTypeId = dwEapTypeId;
  532. pEapInfo->dwSize = dwUserInfo;
  533. pEapInfo->dwSignature = EAP_SIG_2;
  534. dwNewSize += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + dwUserInfo));
  535. RtlCopyMemory(
  536. pEapInfo->abdata,
  537. pbUserInfo,
  538. dwUserInfo);
  539. dwErr = DwSetEapInfo(
  540. hkey,
  541. pbNewInfo,
  542. dwNewSize);
  543. done:
  544. if(NULL != pbNewInfo)
  545. {
  546. LocalFree(pbNewInfo);
  547. }
  548. return dwErr;
  549. }
  550. DWORD
  551. DwSetEapUserInfo(HANDLE hToken,
  552. GUID *pGuid,
  553. PBYTE pbUserInfo,
  554. DWORD dwInfoSize,
  555. BOOL fClear,
  556. BOOL fRouter,
  557. DWORD dwEapTypeId)
  558. {
  559. DWORD dwErr = ERROR_SUCCESS;
  560. PBYTE pbInfo = NULL;
  561. DWORD dwSize = 0;
  562. HKEY hkey = NULL;
  563. if(NULL == pGuid)
  564. {
  565. ASSERT(FALSE);
  566. goto done;
  567. }
  568. if(ERROR_SUCCESS != (dwErr = DwGetEapInfo(
  569. hToken,
  570. fRouter,
  571. &pbInfo,
  572. &dwSize,
  573. &hkey)))
  574. {
  575. goto done;
  576. }
  577. #if DBG
  578. ASSERT(NULL != hkey);
  579. #endif
  580. //
  581. // Check to see if the blob is one we recognize
  582. //
  583. if( !fClear
  584. && ( (sizeof(DWORD) > dwSize)
  585. || (((*((DWORD *) pbInfo)) != EAP_SIG))
  586. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  587. {
  588. EAP_USER_INFO *pEapInfo;
  589. //
  590. // Upgrade?? How? We will just blow away all the old data.
  591. //
  592. pEapInfo = (EAP_USER_INFO *) LocalAlloc(LPTR,
  593. RASMAN_ALIGN8(
  594. sizeof(EAP_USER_INFO)
  595. + dwInfoSize));
  596. if(NULL == pEapInfo)
  597. {
  598. dwErr = GetLastError();
  599. goto done;
  600. }
  601. pEapInfo->Guid = *pGuid;
  602. pEapInfo->dwEapTypeId = dwEapTypeId;
  603. pEapInfo->dwSize = dwInfoSize;
  604. pEapInfo->dwSignature = EAP_SIG_2;
  605. RtlCopyMemory(
  606. pEapInfo->abdata,
  607. pbUserInfo,
  608. dwInfoSize);
  609. dwErr = DwSetEapInfo(hkey,
  610. (PBYTE) pEapInfo,
  611. RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  612. + dwInfoSize));
  613. goto done;
  614. }
  615. else if ( (fClear)
  616. && ( (sizeof(DWORD) > dwSize)
  617. || (((*((DWORD *) pbInfo)) != EAP_SIG))
  618. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  619. {
  620. //
  621. // Blow away the old information
  622. //
  623. dwErr = RegDeleteValue(
  624. hkey,
  625. cszEapValue);
  626. goto done;
  627. }
  628. if(*((DWORD *) pbInfo) == EAP_SIG)
  629. {
  630. //
  631. // upgrade the blob so that its aligned
  632. // at 8-byte boundaries
  633. //
  634. dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
  635. if(ERROR_SUCCESS != dwErr)
  636. {
  637. goto done;
  638. }
  639. }
  640. if(fClear)
  641. {
  642. dwErr = DwRemoveEapUserInfo(pGuid,
  643. pbInfo,
  644. &dwSize,
  645. hkey,
  646. TRUE,
  647. dwEapTypeId);
  648. }
  649. else
  650. {
  651. dwErr = DwReplaceEapUserInfo(
  652. pGuid,
  653. pbUserInfo,
  654. dwInfoSize,
  655. pbInfo,
  656. dwSize,
  657. hkey,
  658. dwEapTypeId);
  659. }
  660. done:
  661. if(NULL != hkey)
  662. {
  663. RegCloseKey(hkey);
  664. }
  665. if(NULL != pbInfo)
  666. {
  667. LocalFree(pbInfo);
  668. }
  669. return dwErr;
  670. }
  671. DWORD
  672. DwGetEapUserInfo(HANDLE hToken,
  673. PBYTE pbEapInfo,
  674. DWORD *pdwInfoSize,
  675. GUID *pGuid,
  676. BOOL fRouter,
  677. DWORD dwEapTypeId)
  678. {
  679. DWORD dwErr = ERROR_SUCCESS;
  680. PBYTE pbInfo = NULL;
  681. DWORD dwSize;
  682. DWORD dwcb = 0;
  683. EAP_USER_INFO UNALIGNED *pEapUserInfo = NULL;
  684. HKEY hkey = NULL;
  685. if(NULL == pdwInfoSize)
  686. {
  687. dwErr = E_INVALIDARG;
  688. goto done;
  689. }
  690. // *pdwInfoSize = 0;
  691. if(NULL == pGuid)
  692. {
  693. ASSERT(FALSE);
  694. *pdwInfoSize = 0;
  695. goto done;
  696. }
  697. //
  698. // Get the binary blob from the registry
  699. //
  700. dwErr = DwGetEapInfo(hToken,
  701. fRouter,
  702. &pbInfo,
  703. &dwSize,
  704. &hkey);
  705. if( (ERROR_SUCCESS != dwErr)
  706. || (0 == dwSize))
  707. {
  708. goto done;
  709. }
  710. //
  711. // Check to see if the blob is one we recognize
  712. //
  713. if( (sizeof(DWORD) > dwSize)
  714. || (((*((DWORD *) pbInfo)) != EAP_SIG)
  715. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  716. {
  717. //
  718. // Upgrade?? How? We will just blow away all the old data.
  719. //
  720. RegDeleteValue(hkey, cszEapValue);
  721. *pdwInfoSize = 0;
  722. goto done;
  723. }
  724. if(*((DWORD *) pbInfo) == EAP_SIG)
  725. {
  726. //
  727. // Upgrade the blob so that its
  728. // aligned correctly.
  729. //
  730. dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
  731. if(ERROR_SUCCESS != dwErr)
  732. {
  733. goto done;
  734. }
  735. }
  736. //
  737. // Loop through the binary blob and look for the
  738. // eap info corresponding to the UID passed in.
  739. //
  740. pEapUserInfo = (EAP_USER_INFO *) pbInfo;
  741. while(dwcb < dwSize)
  742. {
  743. if( (0 == memcmp(
  744. (PBYTE) pGuid,
  745. (PBYTE) &pEapUserInfo->Guid,
  746. sizeof(GUID)))
  747. && (dwEapTypeId == pEapUserInfo->dwEapTypeId))
  748. {
  749. break;
  750. }
  751. dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO)
  752. + pEapUserInfo->dwSize));
  753. pEapUserInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
  754. }
  755. if(dwcb >= dwSize)
  756. {
  757. *pdwInfoSize = 0;
  758. goto done;
  759. }
  760. if( (NULL != pbEapInfo)
  761. && (*pdwInfoSize >= pEapUserInfo->dwSize))
  762. {
  763. RtlCopyMemory(pbEapInfo,
  764. pEapUserInfo->abdata,
  765. pEapUserInfo->dwSize);
  766. }
  767. else
  768. {
  769. dwErr = ERROR_BUFFER_TOO_SMALL;
  770. }
  771. *pdwInfoSize = pEapUserInfo->dwSize;
  772. done:
  773. if(NULL != pbInfo)
  774. {
  775. LocalFree(pbInfo);
  776. }
  777. if(NULL != hkey)
  778. {
  779. RegCloseKey(hkey);
  780. }
  781. return dwErr;
  782. }