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.

958 lines
21 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. USHORT usSidSize;
  169. ASSERT(NULL != phkey);
  170. //
  171. // Get sid of the user from the htoken
  172. //
  173. usSidSize= sizeof(szSid); // Size in bytes
  174. lr = (LONG) DwGetSidFromHtoken(hToken,
  175. szSid,
  176. usSidSize);
  177. if(ERROR_SUCCESS != lr)
  178. {
  179. goto done;
  180. }
  181. //
  182. // Open the users registry key
  183. //
  184. lr = RegOpenKeyExW(HKEY_USERS,
  185. szSid,
  186. 0,
  187. KEY_ALL_ACCESS,
  188. &hkeyUser);
  189. if(ERROR_SUCCESS != lr)
  190. {
  191. goto done;
  192. }
  193. //
  194. // Create the eap key if required.
  195. //
  196. lr = RegCreateKeyEx(hkeyUser,
  197. cszEapKeyRas,
  198. 0,
  199. NULL,
  200. REG_OPTION_NON_VOLATILE,
  201. KEY_ALL_ACCESS,
  202. NULL,
  203. &hkeyEap,
  204. &dwDisposition);
  205. if(ERROR_SUCCESS != lr)
  206. {
  207. goto done;
  208. }
  209. done:
  210. if(NULL != hkeyUser)
  211. {
  212. RegCloseKey(hkeyUser);
  213. }
  214. *phkey = hkeyEap;
  215. return lr;
  216. }
  217. DWORD
  218. DwUpgradeEapInfo(PBYTE *ppbInfo,
  219. DWORD *pdwSize)
  220. {
  221. BYTE *pbInfo;
  222. DWORD dwErr = ERROR_SUCCESS;
  223. EAP_USER_INFO UNALIGNED *pEapInfo;
  224. DWORD dwSize;
  225. DWORD dwRequiredSize = 0;
  226. BYTE *pbNewInfo = NULL;
  227. EAP_USER_INFO *pNewEapInfo;
  228. if( (NULL == ppbInfo)
  229. || (NULL == pdwSize))
  230. {
  231. dwErr = E_INVALIDARG;
  232. goto done;
  233. }
  234. dwSize = *pdwSize;
  235. pbInfo = *ppbInfo;
  236. pEapInfo = (EAP_USER_INFO *) pbInfo;
  237. while((BYTE *) pEapInfo < pbInfo + dwSize)
  238. {
  239. dwRequiredSize += RASMAN_ALIGN8(
  240. sizeof(EAP_USER_INFO)
  241. + pEapInfo->dwSize);
  242. ((PBYTE) pEapInfo) += (sizeof(EAP_USER_INFO)
  243. + pEapInfo->dwSize);
  244. }
  245. pbNewInfo = LocalAlloc(LPTR, dwRequiredSize);
  246. if(NULL == pbNewInfo)
  247. {
  248. dwErr = GetLastError();
  249. goto done;
  250. }
  251. pEapInfo = (EAP_USER_INFO *) pbInfo;
  252. pNewEapInfo = (EAP_USER_INFO *) pbNewInfo;
  253. while((BYTE *) pEapInfo < pbInfo + dwSize)
  254. {
  255. CopyMemory(
  256. (BYTE *) pNewEapInfo,
  257. (BYTE *) pEapInfo,
  258. sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
  259. pNewEapInfo->dwSignature = EAP_SIG_2;
  260. (BYTE *) pNewEapInfo += RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  261. + pEapInfo->dwSize);
  262. (BYTE *) pEapInfo += (sizeof(EAP_USER_INFO) + pEapInfo->dwSize);
  263. }
  264. *ppbInfo = pbNewInfo;
  265. *pdwSize = dwRequiredSize;
  266. if(NULL != pbInfo)
  267. {
  268. LocalFree(pbInfo);
  269. }
  270. done:
  271. return dwErr;
  272. }
  273. DWORD
  274. DwGetEapInfo(HANDLE hToken,
  275. BOOL fRouter,
  276. PBYTE *ppbInfo,
  277. DWORD *pdwSize,
  278. HKEY *phkey
  279. )
  280. {
  281. LONG lr = ERROR_SUCCESS;
  282. HKEY hkey = NULL;
  283. DWORD dwDisposition;
  284. DWORD dwInfoSize = 0;
  285. DWORD dwType;
  286. PBYTE pbInfo = NULL;
  287. if( (NULL == ppbInfo)
  288. || (NULL == pdwSize))
  289. {
  290. lr = (LONG) E_INVALIDARG;
  291. goto done;
  292. }
  293. if( (NULL != hToken)
  294. && (INVALID_HANDLE_VALUE != hToken)
  295. && !fRouter)
  296. {
  297. //
  298. // If a valid token is passed then its most likely
  299. // a service trying to open users registry. Get the
  300. // sid of the user and open HKU in this case.
  301. //
  302. if(ERROR_SUCCESS != (lr = lrGetEapKeyFromToken(hToken,
  303. &hkey)))
  304. {
  305. goto done;
  306. }
  307. }
  308. else
  309. {
  310. //
  311. // Open the key. Create the key if its not present
  312. //
  313. if(ERROR_SUCCESS != (lr = RegCreateKeyEx(
  314. (fRouter)
  315. ? HKEY_LOCAL_MACHINE
  316. : HKEY_CURRENT_USER,
  317. (fRouter)
  318. ? cszEapKeyRouter
  319. : cszEapKeyRas,
  320. 0,
  321. NULL,
  322. REG_OPTION_NON_VOLATILE,
  323. KEY_ALL_ACCESS,
  324. NULL,
  325. &hkey,
  326. &dwDisposition)))
  327. {
  328. goto done;
  329. }
  330. }
  331. //
  332. // Get size of the binary value. If the value is not
  333. // found, return no information. This value will be
  334. // set the first time we store any eap information.
  335. //
  336. if( (ERROR_SUCCESS != (lr = RegQueryValueEx(
  337. hkey,
  338. cszEapValue,
  339. NULL,
  340. &dwType,
  341. NULL,
  342. &dwInfoSize)))
  343. && (ERROR_SUCCESS != lr))
  344. {
  345. goto done;
  346. }
  347. #if DBG
  348. ASSERT(REG_BINARY == dwType);
  349. #endif
  350. //
  351. // Allocate a buffer to hold the binary value
  352. //
  353. pbInfo = LocalAlloc(LPTR, dwInfoSize);
  354. if(NULL == pbInfo)
  355. {
  356. lr = (LONG) GetLastError();
  357. goto done;
  358. }
  359. //
  360. // Get the binary value
  361. //
  362. if(ERROR_SUCCESS != (lr = RegQueryValueEx(
  363. hkey,
  364. cszEapValue,
  365. NULL,
  366. &dwType,
  367. pbInfo,
  368. &dwInfoSize)))
  369. {
  370. goto done;
  371. }
  372. done:
  373. if(NULL != phkey)
  374. {
  375. *phkey = hkey;
  376. }
  377. else if (NULL != hkey)
  378. {
  379. RegCloseKey(hkey);
  380. }
  381. if(NULL != ppbInfo)
  382. {
  383. *ppbInfo = pbInfo;
  384. }
  385. else if(NULL != pbInfo)
  386. {
  387. LocalFree(pbInfo);
  388. }
  389. if(NULL != pdwSize)
  390. {
  391. *pdwSize = dwInfoSize;
  392. }
  393. if(ERROR_FILE_NOT_FOUND == lr)
  394. {
  395. lr = ERROR_SUCCESS;
  396. }
  397. return (DWORD) lr;
  398. }
  399. DWORD
  400. DwSetEapInfo(HKEY hkey,
  401. PBYTE pbInfo,
  402. DWORD dwSize)
  403. {
  404. LONG lr = ERROR_SUCCESS;
  405. if(ERROR_SUCCESS != (lr = RegSetValueEx(
  406. hkey,
  407. cszEapValue,
  408. 0,
  409. REG_BINARY,
  410. pbInfo,
  411. dwSize)))
  412. {
  413. goto done;
  414. }
  415. done:
  416. return (DWORD) lr;
  417. }
  418. DWORD
  419. DwRemoveEapUserInfo(GUID *pGuid,
  420. PBYTE pbInfo,
  421. PDWORD pdwSize,
  422. HKEY hkey,
  423. BOOL fWrite,
  424. DWORD dwEapTypeId)
  425. {
  426. DWORD dwErr = ERROR_SUCCESS;
  427. DWORD dwcb = 0;
  428. EAP_USER_INFO *pEapInfo = (EAP_USER_INFO *) pbInfo;
  429. DWORD dwNewSize;
  430. DWORD dwSize = *pdwSize;
  431. //
  432. // Find the binary blob with the
  433. // UID
  434. //
  435. while(dwcb < dwSize)
  436. {
  437. if( (0 == memcmp(
  438. (PBYTE) pGuid,
  439. (PBYTE) &pEapInfo->Guid,
  440. sizeof(GUID)))
  441. && (dwEapTypeId == pEapInfo->dwEapTypeId))
  442. {
  443. break;
  444. }
  445. dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
  446. pEapInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
  447. }
  448. if(dwcb >= dwSize)
  449. {
  450. goto done;
  451. }
  452. #if DBG
  453. ASSERT(dwSize >= dwcb
  454. + RASMAN_ALIGN8(pEapInfo->dwSize
  455. + sizeof(EAP_USER_INFO)));
  456. #endif
  457. dwNewSize = dwSize -
  458. RASMAN_ALIGN8(pEapInfo->dwSize + sizeof(EAP_USER_INFO));
  459. //
  460. // Remove the info
  461. //
  462. MoveMemory(
  463. pbInfo + dwcb,
  464. pbInfo + dwcb
  465. + RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize),
  466. dwSize - dwcb
  467. - RASMAN_ALIGN8(sizeof(EAP_USER_INFO) + pEapInfo->dwSize));
  468. if(fWrite)
  469. {
  470. dwErr = DwSetEapInfo(
  471. hkey,
  472. pbInfo,
  473. dwNewSize);
  474. }
  475. else
  476. {
  477. *pdwSize = dwNewSize;
  478. }
  479. done:
  480. return dwErr;
  481. }
  482. DWORD
  483. DwReplaceEapUserInfo(GUID *pGuid,
  484. PBYTE pbUserInfo,
  485. DWORD dwUserInfo,
  486. PBYTE pbInfo,
  487. DWORD dwSize,
  488. HKEY hkey,
  489. DWORD dwEapTypeId)
  490. {
  491. DWORD dwErr = ERROR_SUCCESS;
  492. DWORD dwNewSize = dwSize;
  493. PBYTE pbNewInfo = NULL;
  494. EAP_USER_INFO UNALIGNED *pEapInfo;
  495. if(NULL == pGuid)
  496. {
  497. ASSERT(FALSE);
  498. goto done;
  499. }
  500. //
  501. // Remove the existing eap information corresponding
  502. // to dwUID if any.
  503. //
  504. if(ERROR_SUCCESS != (dwErr = DwRemoveEapUserInfo(
  505. pGuid,
  506. pbInfo,
  507. &dwNewSize,
  508. hkey,
  509. FALSE,
  510. dwEapTypeId)))
  511. {
  512. goto done;
  513. }
  514. //
  515. // Local Alloc a new blob with enough space for the
  516. // eap information of the new entry
  517. //
  518. pbNewInfo = LocalAlloc(LPTR,
  519. dwNewSize
  520. + RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  521. + dwUserInfo));
  522. if(NULL == pbNewInfo)
  523. {
  524. dwErr = GetLastError();
  525. goto done;
  526. }
  527. RtlCopyMemory(
  528. pbNewInfo,
  529. pbInfo,
  530. dwNewSize);
  531. pEapInfo = (EAP_USER_INFO *) (pbNewInfo + dwNewSize);
  532. pEapInfo->Guid = *pGuid;
  533. pEapInfo->dwEapTypeId = dwEapTypeId;
  534. pEapInfo->dwSize = dwUserInfo;
  535. pEapInfo->dwSignature = EAP_SIG_2;
  536. dwNewSize += RASMAN_ALIGN8((sizeof(EAP_USER_INFO) + dwUserInfo));
  537. RtlCopyMemory(
  538. pEapInfo->abdata,
  539. pbUserInfo,
  540. dwUserInfo);
  541. dwErr = DwSetEapInfo(
  542. hkey,
  543. pbNewInfo,
  544. dwNewSize);
  545. done:
  546. if(NULL != pbNewInfo)
  547. {
  548. LocalFree(pbNewInfo);
  549. }
  550. return dwErr;
  551. }
  552. DWORD
  553. DwSetEapUserInfo(HANDLE hToken,
  554. GUID *pGuid,
  555. PBYTE pbUserInfo,
  556. DWORD dwInfoSize,
  557. BOOL fClear,
  558. BOOL fRouter,
  559. DWORD dwEapTypeId)
  560. {
  561. DWORD dwErr = ERROR_SUCCESS;
  562. PBYTE pbInfo = NULL;
  563. DWORD dwSize = 0;
  564. HKEY hkey = NULL;
  565. if(NULL == pGuid)
  566. {
  567. ASSERT(FALSE);
  568. goto done;
  569. }
  570. if(ERROR_SUCCESS != (dwErr = DwGetEapInfo(
  571. hToken,
  572. fRouter,
  573. &pbInfo,
  574. &dwSize,
  575. &hkey)))
  576. {
  577. goto done;
  578. }
  579. #if DBG
  580. ASSERT(NULL != hkey);
  581. #endif
  582. //
  583. // Check to see if the blob is one we recognize
  584. //
  585. if( !fClear
  586. && ( (sizeof(DWORD) > dwSize)
  587. || (((*((DWORD *) pbInfo)) != EAP_SIG))
  588. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  589. {
  590. EAP_USER_INFO *pEapInfo;
  591. //
  592. // Upgrade?? How? We will just blow away all the old data.
  593. //
  594. pEapInfo = (EAP_USER_INFO *) LocalAlloc(LPTR,
  595. RASMAN_ALIGN8(
  596. sizeof(EAP_USER_INFO)
  597. + dwInfoSize));
  598. if(NULL == pEapInfo)
  599. {
  600. dwErr = GetLastError();
  601. goto done;
  602. }
  603. pEapInfo->Guid = *pGuid;
  604. pEapInfo->dwEapTypeId = dwEapTypeId;
  605. pEapInfo->dwSize = dwInfoSize;
  606. pEapInfo->dwSignature = EAP_SIG_2;
  607. RtlCopyMemory(
  608. pEapInfo->abdata,
  609. pbUserInfo,
  610. dwInfoSize);
  611. dwErr = DwSetEapInfo(hkey,
  612. (PBYTE) pEapInfo,
  613. RASMAN_ALIGN8(sizeof(EAP_USER_INFO)
  614. + dwInfoSize));
  615. goto done;
  616. }
  617. else if ( (fClear)
  618. && ( (sizeof(DWORD) > dwSize)
  619. || (((*((DWORD *) pbInfo)) != EAP_SIG))
  620. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  621. {
  622. //
  623. // Blow away the old information
  624. //
  625. dwErr = RegDeleteValue(
  626. hkey,
  627. cszEapValue);
  628. goto done;
  629. }
  630. if(*((DWORD *) pbInfo) == EAP_SIG)
  631. {
  632. //
  633. // upgrade the blob so that its aligned
  634. // at 8-byte boundaries
  635. //
  636. dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
  637. if(ERROR_SUCCESS != dwErr)
  638. {
  639. goto done;
  640. }
  641. }
  642. if(fClear)
  643. {
  644. dwErr = DwRemoveEapUserInfo(pGuid,
  645. pbInfo,
  646. &dwSize,
  647. hkey,
  648. TRUE,
  649. dwEapTypeId);
  650. }
  651. else
  652. {
  653. dwErr = DwReplaceEapUserInfo(
  654. pGuid,
  655. pbUserInfo,
  656. dwInfoSize,
  657. pbInfo,
  658. dwSize,
  659. hkey,
  660. dwEapTypeId);
  661. }
  662. done:
  663. if(NULL != hkey)
  664. {
  665. RegCloseKey(hkey);
  666. }
  667. if(NULL != pbInfo)
  668. {
  669. LocalFree(pbInfo);
  670. }
  671. return dwErr;
  672. }
  673. DWORD
  674. DwGetEapUserInfo(HANDLE hToken,
  675. PBYTE pbEapInfo,
  676. DWORD *pdwInfoSize,
  677. GUID *pGuid,
  678. BOOL fRouter,
  679. DWORD dwEapTypeId)
  680. {
  681. DWORD dwErr = ERROR_SUCCESS;
  682. PBYTE pbInfo = NULL;
  683. DWORD dwSize;
  684. DWORD dwcb = 0;
  685. EAP_USER_INFO UNALIGNED *pEapUserInfo = NULL;
  686. HKEY hkey = NULL;
  687. if(NULL == pdwInfoSize)
  688. {
  689. dwErr = E_INVALIDARG;
  690. goto done;
  691. }
  692. // *pdwInfoSize = 0;
  693. if(NULL == pGuid)
  694. {
  695. ASSERT(FALSE);
  696. *pdwInfoSize = 0;
  697. goto done;
  698. }
  699. //
  700. // Get the binary blob from the registry
  701. //
  702. dwErr = DwGetEapInfo(hToken,
  703. fRouter,
  704. &pbInfo,
  705. &dwSize,
  706. &hkey);
  707. if( (ERROR_SUCCESS != dwErr)
  708. || (0 == dwSize))
  709. {
  710. goto done;
  711. }
  712. //
  713. // Check to see if the blob is one we recognize
  714. //
  715. if( (sizeof(DWORD) > dwSize)
  716. || (((*((DWORD *) pbInfo)) != EAP_SIG)
  717. && ( (*((DWORD *) pbInfo)) != EAP_SIG_2)))
  718. {
  719. //
  720. // Upgrade?? How? We will just blow away all the old data.
  721. //
  722. RegDeleteValue(hkey, cszEapValue);
  723. *pdwInfoSize = 0;
  724. goto done;
  725. }
  726. if(*((DWORD *) pbInfo) == EAP_SIG)
  727. {
  728. //
  729. // Upgrade the blob so that its
  730. // aligned correctly.
  731. //
  732. dwErr = DwUpgradeEapInfo(&pbInfo, &dwSize);
  733. if(ERROR_SUCCESS != dwErr)
  734. {
  735. goto done;
  736. }
  737. }
  738. //
  739. // Loop through the binary blob and look for the
  740. // eap info corresponding to the UID passed in.
  741. //
  742. pEapUserInfo = (EAP_USER_INFO *) pbInfo;
  743. while(dwcb < dwSize)
  744. {
  745. if( (0 == memcmp(
  746. (PBYTE) pGuid,
  747. (PBYTE) &pEapUserInfo->Guid,
  748. sizeof(GUID)))
  749. && (dwEapTypeId == pEapUserInfo->dwEapTypeId))
  750. {
  751. break;
  752. }
  753. dwcb += RASMAN_ALIGN8((sizeof(EAP_USER_INFO)
  754. + pEapUserInfo->dwSize));
  755. pEapUserInfo = (EAP_USER_INFO *) (pbInfo + dwcb);
  756. }
  757. if(dwcb >= dwSize)
  758. {
  759. *pdwInfoSize = 0;
  760. goto done;
  761. }
  762. if( (NULL != pbEapInfo)
  763. && (*pdwInfoSize >= pEapUserInfo->dwSize))
  764. {
  765. RtlCopyMemory(pbEapInfo,
  766. pEapUserInfo->abdata,
  767. pEapUserInfo->dwSize);
  768. }
  769. else
  770. {
  771. dwErr = ERROR_BUFFER_TOO_SMALL;
  772. }
  773. *pdwInfoSize = pEapUserInfo->dwSize;
  774. done:
  775. if(NULL != pbInfo)
  776. {
  777. LocalFree(pbInfo);
  778. }
  779. if(NULL != hkey)
  780. {
  781. RegCloseKey(hkey);
  782. }
  783. return dwErr;
  784. }