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.

1446 lines
39 KiB

  1. /*
  2. File thunk.c
  3. Provides api's to convert one-the-wire structures to the host structures
  4. for the mpr api's.
  5. The MprApi's provide many structures with embedded pointers. These pointers
  6. are converted to 32 bit offsets before transmitting them on the wire. In
  7. order to preserve compatibility accross 64bit and 32bit machines, the
  8. following thunking code is required. RPC doesn't do this for us in the
  9. cases where we marshall our own data.
  10. */
  11. #include <windows.h>
  12. #include <mprapip.h>
  13. #include <rpc.h>
  14. #include <rpcndr.h>
  15. //
  16. // Call: MprUtilGetSizeOfMultiSz
  17. //
  18. // Returns: size in bytes of lpwsDialoutHoursRestriction
  19. //
  20. // Description: Utility to calculate the size in bytes of MULTI_SZ
  21. //
  22. DWORD
  23. MprUtilGetSizeOfMultiSz(
  24. IN LPWSTR lpwsMultiSz)
  25. {
  26. LPWSTR lpwsPtr = lpwsMultiSz;
  27. DWORD dwcbBytes = 0;
  28. DWORD dwCurCount;
  29. if ( lpwsPtr == NULL )
  30. {
  31. return( 0 );
  32. }
  33. while( *lpwsPtr != L'\0' )
  34. {
  35. dwCurCount = ( wcslen( lpwsPtr ) + 1 );
  36. dwcbBytes += dwCurCount;
  37. lpwsPtr += dwCurCount;
  38. }
  39. //
  40. // One more for the last NULL terminator
  41. //
  42. dwcbBytes++;
  43. dwcbBytes *= sizeof( WCHAR );
  44. return( dwcbBytes );
  45. }
  46. //
  47. // Generic allocation for the thunking api's
  48. //
  49. PVOID
  50. MprThunkAlloc(
  51. IN DWORD dwSize)
  52. {
  53. return LocalAlloc( LMEM_FIXED , dwSize);
  54. }
  55. //
  56. // Generic free for the thunking api's
  57. //
  58. VOID
  59. MprThunkFree(
  60. IN PVOID pvData)
  61. {
  62. LocalFree( pvData );
  63. }
  64. //
  65. // Cleans up after MprThunkInterface_HtoW
  66. //
  67. DWORD
  68. MprThunkInterfaceFree(
  69. IN PVOID pvInfo,
  70. IN DWORD dwLevel)
  71. {
  72. #ifdef _WIN64
  73. if ( pvInfo )
  74. {
  75. LocalFree( pvInfo );
  76. }
  77. #else
  78. if ( dwLevel == 1 || dwLevel == 2 )
  79. {
  80. if ( pvInfo )
  81. {
  82. LocalFree( pvInfo );
  83. }
  84. }
  85. #endif
  86. return NO_ERROR;
  87. }
  88. //
  89. // Converts an array of MPRI_INTERFACE_0 structures to an array
  90. // of MPR_INTERFACE_0 structures on a 64 bit machine. On a 32
  91. // bit machine, the structures are identical.
  92. //
  93. DWORD
  94. MprThunkInterface_32to64_0(
  95. IN MPRI_INTERFACE_0* pIfs32,
  96. IN DWORD dwBufferSize,
  97. IN DWORD dwCount,
  98. IN BOOL fAllocate,
  99. IN MprThunk_Allocation_Func pAlloc,
  100. IN MprThunk_Free_Func pFree,
  101. OUT MPR_INTERFACE_0** ppIfs0)
  102. {
  103. DWORD dwErr = NO_ERROR, i;
  104. MPR_INTERFACE_0 *pCur64 = NULL, *pIfs64 = NULL;
  105. MPRI_INTERFACE_0* pCur32 = NULL;
  106. if (dwCount == 0)
  107. {
  108. *ppIfs0 = NULL;
  109. return NO_ERROR;
  110. }
  111. do
  112. {
  113. // Allocate the new structures
  114. //
  115. if (fAllocate)
  116. {
  117. pIfs64 = (MPR_INTERFACE_0*)
  118. pAlloc(dwCount * sizeof(MPR_INTERFACE_0));
  119. if (pIfs64 == NULL)
  120. {
  121. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  122. break;
  123. }
  124. }
  125. else
  126. {
  127. pIfs64 = *ppIfs0;
  128. }
  129. // Copy over all of the information
  130. //
  131. for (i = 0, pCur32 = pIfs32, pCur64 = pIfs64;
  132. i < dwCount;
  133. i++, pCur32++, pCur64++)
  134. {
  135. wcscpy(pCur64->wszInterfaceName, pCur32->wszInterfaceName);
  136. pCur64->hInterface = UlongToPtr(pCur32->dwInterface);
  137. pCur64->fEnabled = pCur32->fEnabled;
  138. pCur64->dwIfType = pCur32->dwIfType;
  139. pCur64->dwConnectionState = pCur32->dwConnectionState;
  140. pCur64->fUnReachabilityReasons = pCur32->fUnReachabilityReasons;
  141. pCur64->dwLastError = pCur32->dwLastError;
  142. }
  143. // Assign the return value
  144. //
  145. *ppIfs0 = pIfs64;
  146. } while (FALSE);
  147. // Cleanup
  148. //
  149. {
  150. if (dwErr != NO_ERROR)
  151. {
  152. if (pIfs64 && fAllocate)
  153. {
  154. pFree(pIfs64);
  155. }
  156. }
  157. }
  158. return dwErr;
  159. }
  160. //
  161. // Converts an array of MPRI_INTERFACE_1 structures to an array
  162. // of MPR_INTERFACE_1 structures on a 64 bit machine. On a 32
  163. // bit machine, the structures are identical.
  164. //
  165. DWORD
  166. MprThunkInterface_32to64_1(
  167. IN MPRI_INTERFACE_1* pIfs32,
  168. IN DWORD dwBufferSize,
  169. IN MprThunk_Allocation_Func pAlloc,
  170. IN MprThunk_Free_Func pFree,
  171. OUT MPR_INTERFACE_1** ppIfs1)
  172. {
  173. DWORD dwErr = NO_ERROR, i, dwSize;
  174. MPR_INTERFACE_1 *pIfs64 = NULL;
  175. if (pIfs32 == NULL)
  176. {
  177. *ppIfs1 = NULL;
  178. return NO_ERROR;
  179. }
  180. do
  181. {
  182. // Compute the size of the buffer to allocate for storing
  183. // the level-one information. The size the sum of the
  184. // size of the on-the-wire buffer plus the extra space for
  185. // 64 bit embedded pointers.
  186. //
  187. dwSize =
  188. dwBufferSize +
  189. (sizeof(MPR_INTERFACE_1) - sizeof(MPRI_INTERFACE_1));
  190. pIfs64 = (MPR_INTERFACE_1*)pAlloc(dwSize);
  191. if (pIfs64 == NULL)
  192. {
  193. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  194. break;
  195. }
  196. // Thunk the common level-zero stuff
  197. //
  198. dwErr = MprThunkInterface_32to64_0(
  199. (MPRI_INTERFACE_0*)pIfs32,
  200. dwBufferSize,
  201. 1,
  202. FALSE,
  203. pAlloc,
  204. pFree,
  205. (MPR_INTERFACE_0**)&pIfs64);
  206. if (dwErr != NO_ERROR)
  207. {
  208. break;
  209. }
  210. // Thunk the level-one specific stuff
  211. //
  212. pIfs64->lpwsDialoutHoursRestriction =
  213. UlongToPtr(pIfs32->dwDialoutHoursRestrictionOffset);
  214. // Copy over the variable-length data.
  215. //
  216. CopyMemory(
  217. (PVOID)(pIfs64 + 1),
  218. (CONST VOID*)(pIfs32 + 1),
  219. dwBufferSize - sizeof(MPRI_INTERFACE_1));
  220. // Assign the return value
  221. //
  222. *ppIfs1 = pIfs64;
  223. } while (FALSE);
  224. // Cleanup
  225. //
  226. {
  227. if (dwErr != NO_ERROR)
  228. {
  229. if (pIfs64)
  230. {
  231. pFree(pIfs64);
  232. }
  233. }
  234. }
  235. return dwErr;
  236. }
  237. //
  238. // Converts an array of MPRI_INTERFACE_2 structures to an array
  239. // of MPR_INTERFACE_2 structures on a 64 bit machine. On a 32
  240. // bit machine, the structures are identical.
  241. //
  242. DWORD
  243. MprThunkInterface_32to64_2(
  244. IN MPRI_INTERFACE_2* pIfs32,
  245. IN DWORD dwBufferSize,
  246. IN MprThunk_Allocation_Func pAlloc,
  247. IN MprThunk_Free_Func pFree,
  248. OUT MPR_INTERFACE_2** ppIfs2)
  249. {
  250. DWORD dwErr = NO_ERROR, i, dwSize;
  251. MPR_INTERFACE_2 *pIfs64 = NULL;
  252. if (pIfs32 == NULL)
  253. {
  254. *ppIfs2 = NULL;
  255. return NO_ERROR;
  256. }
  257. do
  258. {
  259. // Compute the size of the buffer to allocate for storing
  260. // the level-one information. The size the sum of the
  261. // size of the on-the-wire buffer plus the extra space for
  262. // 64 bit embedded pointers.
  263. //
  264. dwSize =
  265. dwBufferSize +
  266. (sizeof(MPR_INTERFACE_2) - sizeof(MPRI_INTERFACE_2));
  267. pIfs64 = (MPR_INTERFACE_2*)pAlloc(dwSize);
  268. if (pIfs64 == NULL)
  269. {
  270. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  271. break;
  272. }
  273. // Thunk the common level-zero stuff
  274. //
  275. dwErr = MprThunkInterface_32to64_0(
  276. (MPRI_INTERFACE_0*)pIfs32,
  277. dwBufferSize,
  278. 1,
  279. FALSE,
  280. pAlloc,
  281. pFree,
  282. (MPR_INTERFACE_0**)&pIfs64);
  283. if (dwErr != NO_ERROR)
  284. {
  285. break;
  286. }
  287. // Thunk the level-two specific stuff
  288. //
  289. pIfs64->dwfOptions = pIfs32->dwfOptions;
  290. pIfs64->ipaddr = pIfs32->ipaddr;
  291. pIfs64->ipaddrDns = pIfs32->ipaddrDns;
  292. pIfs64->ipaddrDnsAlt = pIfs32->ipaddrDnsAlt;
  293. pIfs64->ipaddrWins = pIfs32->ipaddrWins;
  294. pIfs64->ipaddrWinsAlt = pIfs32->ipaddrWinsAlt;
  295. pIfs64->dwfNetProtocols = pIfs32->dwfNetProtocols;
  296. pIfs64->dwChannels = pIfs32->dwChannels;
  297. pIfs64->dwSubEntries = pIfs32->dwSubEntries;
  298. pIfs64->dwDialMode = pIfs32->dwDialMode;
  299. pIfs64->dwDialExtraPercent = pIfs32->dwDialExtraPercent;
  300. pIfs64->dwDialExtraSampleSeconds = pIfs32->dwDialExtraSampleSeconds;
  301. pIfs64->dwHangUpExtraPercent = pIfs32->dwHangUpExtraPercent;
  302. pIfs64->dwHangUpExtraSampleSeconds= pIfs32->dwHangUpExtraSampleSeconds;
  303. pIfs64->dwIdleDisconnectSeconds = pIfs32->dwIdleDisconnectSeconds;
  304. pIfs64->dwType = pIfs32->dwType;
  305. pIfs64->dwEncryptionType = pIfs32->dwEncryptionType;
  306. pIfs64->dwCustomAuthKey = pIfs32->dwCustomAuthKey;
  307. pIfs64->dwCustomAuthDataSize = pIfs32->dwCustomAuthDataSize;
  308. pIfs64->guidId = pIfs32->guidId;
  309. pIfs64->dwVpnStrategy = pIfs32->dwVpnStrategy;
  310. // The following get set in the post-thunk processing when
  311. // pointers to variable length data are adjusted.
  312. //
  313. // pIfs64->szAlternates;
  314. // pIfs64->lpbCustomAuthData;
  315. wcscpy(pIfs64->szLocalPhoneNumber, pIfs32->szLocalPhoneNumber);
  316. wcscpy(pIfs64->szDeviceType, pIfs32->szDeviceType);
  317. wcscpy(pIfs64->szDeviceName, pIfs32->szDeviceName);
  318. wcscpy(pIfs64->szX25PadType, pIfs32->szX25PadType);
  319. wcscpy(pIfs64->szX25Address, pIfs32->szX25Address);
  320. wcscpy(pIfs64->szX25Facilities, pIfs32->szX25Facilities);
  321. wcscpy(pIfs64->szX25UserData, pIfs32->szX25UserData);
  322. // Copy over the variable-length data.
  323. //
  324. CopyMemory(
  325. (PVOID)(pIfs64 + 1),
  326. (CONST VOID*)(pIfs32 + 1),
  327. dwBufferSize - sizeof(MPRI_INTERFACE_2));
  328. // Assign the return value
  329. //
  330. *ppIfs2 = pIfs64;
  331. } while (FALSE);
  332. // Cleanup
  333. //
  334. {
  335. if (dwErr != NO_ERROR)
  336. {
  337. if (pIfs64)
  338. {
  339. pFree(pIfs64);
  340. }
  341. }
  342. }
  343. return dwErr;
  344. }
  345. //
  346. // Converts an array of MPR_INTERFACE_0 structures to an array
  347. // of MPRI_INTERFACE_0 structures on a 64 bit machine. On a 32
  348. // bit machine, the structures are identical.
  349. //
  350. DWORD
  351. MprThunkInterface_64to32_0(
  352. IN MPR_INTERFACE_0* pIf64,
  353. OUT MPRI_INTERFACE_0* pIf0)
  354. {
  355. wcscpy(pIf0->wszInterfaceName, pIf64->wszInterfaceName);
  356. pIf0->dwInterface = PtrToUlong(pIf64->hInterface);
  357. pIf0->fEnabled = pIf64->fEnabled;
  358. pIf0->dwIfType = pIf64->dwIfType;
  359. pIf0->dwConnectionState = pIf64->dwConnectionState;
  360. pIf0->fUnReachabilityReasons = pIf64->fUnReachabilityReasons;
  361. pIf0->dwLastError = pIf64->dwLastError;
  362. return NO_ERROR;
  363. }
  364. //
  365. // Converts an MPR_INTERFACE_1 structure to a of MPRI_INTERFACE_1
  366. // structure on a 64 bit machine. On a 32 bit machine, the
  367. // structures are identical.
  368. //
  369. DWORD
  370. MprThunkInterface_64to32_1(
  371. IN MPR_INTERFACE_1* pIf64,
  372. OUT MPRI_INTERFACE_1* pIf1)
  373. {
  374. DWORD dwErr = NO_ERROR, i;
  375. do
  376. {
  377. // Thunk the common level-zero stuff
  378. //
  379. dwErr = MprThunkInterface_64to32_0(
  380. (MPR_INTERFACE_0*)pIf64,
  381. (MPRI_INTERFACE_0*)pIf1);
  382. if (dwErr != NO_ERROR)
  383. {
  384. break;
  385. }
  386. } while (FALSE);
  387. return dwErr;
  388. }
  389. //
  390. // Converts an array of MPR_INTERFACE_2 structures to an array
  391. // of MPRI_INTERFACE_2 structures on a 64 bit machine. On a 32
  392. // bit machine, the structures are identical.
  393. //
  394. DWORD
  395. MprThunkInterface_64to32_2(
  396. IN MPR_INTERFACE_2* pIf64,
  397. OUT MPRI_INTERFACE_2* pIf2)
  398. {
  399. DWORD dwErr = NO_ERROR, i;
  400. do
  401. {
  402. // Thunk the common level-zero stuff
  403. //
  404. dwErr = MprThunkInterface_64to32_0(
  405. (MPR_INTERFACE_0*)pIf64,
  406. (MPRI_INTERFACE_0*)pIf2);
  407. if (dwErr != NO_ERROR)
  408. {
  409. break;
  410. }
  411. // Thunk the level-two specific stuff
  412. //
  413. pIf2->dwfOptions = pIf64->dwfOptions;
  414. pIf2->ipaddr = pIf64->ipaddr;
  415. pIf2->ipaddrDns = pIf64->ipaddrDns;
  416. pIf2->ipaddrDnsAlt = pIf64->ipaddrDnsAlt;
  417. pIf2->ipaddrWins = pIf64->ipaddrWins;
  418. pIf2->ipaddrWinsAlt = pIf64->ipaddrWinsAlt;
  419. pIf2->dwfNetProtocols = pIf64->dwfNetProtocols;
  420. pIf2->dwChannels = pIf64->dwChannels;
  421. pIf2->dwSubEntries = pIf64->dwSubEntries;
  422. pIf2->dwDialMode = pIf64->dwDialMode;
  423. pIf2->dwDialExtraPercent = pIf64->dwDialExtraPercent;
  424. pIf2->dwDialExtraSampleSeconds = pIf64->dwDialExtraSampleSeconds;
  425. pIf2->dwHangUpExtraPercent = pIf64->dwHangUpExtraPercent;
  426. pIf2->dwHangUpExtraSampleSeconds= pIf64->dwHangUpExtraSampleSeconds;
  427. pIf2->dwIdleDisconnectSeconds = pIf64->dwIdleDisconnectSeconds;
  428. pIf2->dwType = pIf64->dwType;
  429. pIf2->dwEncryptionType = pIf64->dwEncryptionType;
  430. pIf2->dwCustomAuthKey = pIf64->dwCustomAuthKey;
  431. pIf2->dwCustomAuthDataSize = pIf64->dwCustomAuthDataSize;
  432. pIf2->guidId = pIf64->guidId;
  433. pIf2->dwVpnStrategy = pIf64->dwVpnStrategy;
  434. wcscpy(pIf2->szLocalPhoneNumber, pIf64->szLocalPhoneNumber);
  435. wcscpy(pIf2->szDeviceType, pIf64->szDeviceType);
  436. wcscpy(pIf2->szDeviceName, pIf64->szDeviceName);
  437. wcscpy(pIf2->szX25PadType, pIf64->szX25PadType);
  438. wcscpy(pIf2->szX25Address, pIf64->szX25Address);
  439. wcscpy(pIf2->szX25Facilities, pIf64->szX25Facilities);
  440. wcscpy(pIf2->szX25UserData, pIf64->szX25UserData);
  441. } while (FALSE);
  442. return dwErr;
  443. }
  444. //
  445. // Convert interface structs from the wire representation to the
  446. // host representation
  447. //
  448. DWORD
  449. MprThunkInterface_WtoH(
  450. IN DWORD dwLevel,
  451. IN LPBYTE lpbBuffer,
  452. IN DWORD dwBufferSize,
  453. IN DWORD dwCount,
  454. IN MprThunk_Allocation_Func pAlloc,
  455. IN MprThunk_Free_Func pFree,
  456. OUT LPBYTE* lplpbBuffer)
  457. {
  458. MPR_INTERFACE_0* pIfs0 = NULL;
  459. MPR_INTERFACE_1* pIf1 = NULL;
  460. MPR_INTERFACE_2* pIf2 = NULL;
  461. DWORD dwErr = NO_ERROR, i;
  462. #ifdef _WIN64
  463. //
  464. // Generate the 64 bit host structures based on the 32 bit
  465. // wire structures.
  466. //
  467. switch (dwLevel)
  468. {
  469. case 0:
  470. dwErr = MprThunkInterface_32to64_0(
  471. (MPRI_INTERFACE_0*)lpbBuffer,
  472. dwBufferSize,
  473. dwCount,
  474. TRUE,
  475. pAlloc,
  476. pFree,
  477. &pIfs0);
  478. *lplpbBuffer = (LPBYTE)pIfs0;
  479. break;
  480. case 1:
  481. dwErr = MprThunkInterface_32to64_1(
  482. (MPRI_INTERFACE_1*)lpbBuffer,
  483. dwBufferSize,
  484. pAlloc,
  485. pFree,
  486. &pIf1);
  487. *lplpbBuffer = (LPBYTE)pIf1;
  488. break;
  489. case 2:
  490. dwErr = MprThunkInterface_32to64_2(
  491. (MPRI_INTERFACE_2*)lpbBuffer,
  492. dwBufferSize,
  493. pAlloc,
  494. pFree,
  495. &pIf2);
  496. *lplpbBuffer = (LPBYTE)pIf2;
  497. break;
  498. }
  499. // Free the unthunked data
  500. //
  501. pFree(lpbBuffer);
  502. if (dwErr != NO_ERROR)
  503. {
  504. return dwErr;
  505. }
  506. #else
  507. // 32 bit -- nothing to do since the structures
  508. // match
  509. //
  510. *lplpbBuffer = lpbBuffer;
  511. #endif
  512. // By this point in the code, the structures have been converted from
  513. // their wire format to the host format and stored in *lplpbBuffer.
  514. // Now we perform some post-processing to adjust the pointers to
  515. // variable length data.
  516. switch (dwLevel)
  517. {
  518. case 0:
  519. break;
  520. case 1:
  521. pIf1 = (MPR_INTERFACE_1*)(*lplpbBuffer);
  522. if ( pIf1->lpwsDialoutHoursRestriction != NULL )
  523. {
  524. pIf1->lpwsDialoutHoursRestriction = (PWCHAR)(pIf1 + 1);
  525. }
  526. break;
  527. case 2:
  528. pIf2 = (MPR_INTERFACE_2*)(*lplpbBuffer);
  529. if ( pIf2->dwCustomAuthDataSize )
  530. {
  531. pIf2->lpbCustomAuthData = (LPBYTE)(pIf2 + 1);
  532. }
  533. if ( pIf2->szAlternates )
  534. {
  535. pIf2->szAlternates = (PWCHAR)
  536. (*lplpbBuffer +
  537. sizeof(MPR_INTERFACE_2) +
  538. pIf2->dwCustomAuthDataSize
  539. );
  540. }
  541. break;
  542. }
  543. return dwErr;
  544. }
  545. DWORD
  546. MprThunkInterface_HtoW(
  547. IN DWORD dwLevel,
  548. IN LPBYTE lpbBuffer,
  549. OUT LPBYTE* lplpbBuffer,
  550. OUT LPDWORD lpdwSize)
  551. {
  552. DWORD dwErr = NO_ERROR, dwSize, dwOffset;
  553. LPBYTE lpbRet = NULL;
  554. switch ( dwLevel )
  555. {
  556. case 0:
  557. dwSize = sizeof(MPRI_INTERFACE_0);
  558. #ifdef _WIN64
  559. // Allocate and thunk a wire structure
  560. //
  561. lpbRet = MprThunkAlloc(dwSize);
  562. if (lpbRet == NULL)
  563. {
  564. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  565. break;
  566. }
  567. dwErr =
  568. MprThunkInterface_64to32_0(
  569. (MPR_INTERFACE_0*)lpbBuffer,
  570. (MPRI_INTERFACE_0*)lpbRet);
  571. #else
  572. // Nothing to do host and wire structures are identical
  573. // and there is no variable length data
  574. //
  575. lpbRet = lpbBuffer;
  576. #endif
  577. break;
  578. case 1:
  579. {
  580. MPR_INTERFACE_1 * pIf1 = (MPR_INTERFACE_1*)lpbBuffer;
  581. MPRI_INTERFACE_1 * pIfi1 = NULL;
  582. DWORD cbDialoutHoursRestriction;
  583. // Allocate a buffer to store the on-the-wire info
  584. //
  585. cbDialoutHoursRestriction =
  586. MprUtilGetSizeOfMultiSz(
  587. pIf1->lpwsDialoutHoursRestriction );
  588. dwSize =
  589. sizeof( MPRI_INTERFACE_1 ) + cbDialoutHoursRestriction;
  590. lpbRet = MprThunkAlloc(dwSize);
  591. if ( lpbRet == NULL )
  592. {
  593. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  594. break;
  595. }
  596. #ifdef _WIN64
  597. dwErr =
  598. MprThunkInterface_64to32_1(
  599. pIf1,
  600. (MPRI_INTERFACE_1*)lpbRet);
  601. if (dwErr != NO_ERROR)
  602. {
  603. break;
  604. }
  605. #else
  606. CopyMemory(lpbRet, pIf1, sizeof(MPR_INTERFACE_1));
  607. #endif
  608. // Level 1 specific embedded pointers. Set them to non-zero
  609. // to indicate whether there is variable length data.
  610. //
  611. pIfi1 = (MPRI_INTERFACE_1*)lpbRet;
  612. pIfi1->dwDialoutHoursRestrictionOffset =
  613. !!(PtrToUlong(pIf1->lpwsDialoutHoursRestriction));
  614. // Copy in variable length data
  615. //
  616. if ( cbDialoutHoursRestriction > 0 )
  617. {
  618. CopyMemory(
  619. lpbRet + sizeof(MPRI_INTERFACE_1),
  620. pIf1->lpwsDialoutHoursRestriction,
  621. cbDialoutHoursRestriction );
  622. }
  623. }
  624. break;
  625. case 2:
  626. {
  627. MPR_INTERFACE_2 * pIf2 = (MPR_INTERFACE_2*)lpbBuffer;
  628. MPRI_INTERFACE_2 * pIfi2 = NULL;
  629. DWORD dwAltSize = MprUtilGetSizeOfMultiSz(pIf2->szAlternates);
  630. // Calcluate the size of the variable length structure
  631. //
  632. dwSize =
  633. sizeof( MPRI_INTERFACE_2 ) +
  634. dwAltSize +
  635. pIf2->dwCustomAuthDataSize;
  636. // Allocate the buffer
  637. //
  638. lpbRet = MprThunkAlloc(dwSize);
  639. if ( lpbRet == NULL )
  640. {
  641. dwErr = GetLastError();
  642. break;
  643. }
  644. // Copy over the base strucuture
  645. //
  646. #ifdef _WIN64
  647. dwErr =
  648. MprThunkInterface_64to32_2(
  649. pIf2,
  650. (MPRI_INTERFACE_2*)lpbRet);
  651. if (dwErr != NO_ERROR)
  652. {
  653. break;
  654. }
  655. #else
  656. CopyMemory(lpbRet, pIf2, sizeof(MPR_INTERFACE_2));
  657. #endif
  658. // Level 2 specific embedded pointers. Set them to non-zero
  659. // to indicate whether there is variable length data.
  660. //
  661. pIfi2 = (MPRI_INTERFACE_2*)lpbRet;
  662. pIfi2->dwAlternatesOffset = !!(PtrToUlong(pIf2->szAlternates));
  663. pIfi2->dwCustomAuthDataOffset = !!pIf2->dwCustomAuthDataSize;
  664. // Copy the custom auth data if any
  665. //
  666. dwOffset = sizeof( MPRI_INTERFACE_2 );
  667. if ( pIf2->dwCustomAuthDataSize )
  668. {
  669. CopyMemory(
  670. lpbRet + dwOffset,
  671. pIf2->lpbCustomAuthData,
  672. pIf2->dwCustomAuthDataSize);
  673. }
  674. // Copy the alternates list if any
  675. //
  676. dwOffset += pIf2->dwCustomAuthDataSize;
  677. if ( dwAltSize > 0 )
  678. {
  679. CopyMemory(
  680. lpbRet + dwOffset,
  681. pIf2->szAlternates,
  682. dwAltSize );
  683. }
  684. }
  685. break;
  686. default:
  687. return( ERROR_NOT_SUPPORTED );
  688. }
  689. if (dwErr == NO_ERROR)
  690. {
  691. *lplpbBuffer = lpbRet;
  692. *lpdwSize = dwSize;
  693. }
  694. else
  695. {
  696. MprThunkInterfaceFree(lpbRet, dwLevel);
  697. }
  698. return dwErr;
  699. }
  700. //
  701. // Converts an array of RASI_PORT_0 structures to an array
  702. // of RAS_PORT_0 structures on a 64 bit machine. On a 32
  703. // bit machine, the structures are identical.
  704. //
  705. DWORD
  706. MprThunkPort_32to64_0(
  707. IN RASI_PORT_0* pPorts32,
  708. IN DWORD dwBufferSize,
  709. IN DWORD dwCount,
  710. IN MprThunk_Allocation_Func pAlloc,
  711. IN MprThunk_Free_Func pFree,
  712. OUT RAS_PORT_0** ppPorts0)
  713. {
  714. DWORD dwErr = NO_ERROR, i;
  715. RAS_PORT_0 *pCur64 = NULL, *pPorts64 = NULL;
  716. RASI_PORT_0* pCur32 = NULL;
  717. if (dwCount == 0)
  718. {
  719. *ppPorts0 = NULL;
  720. return NO_ERROR;
  721. }
  722. do
  723. {
  724. // Allocate the new structures
  725. //
  726. pPorts64 = (RAS_PORT_0*)
  727. pAlloc(dwCount * sizeof(RAS_PORT_0));
  728. if (pPorts64 == NULL)
  729. {
  730. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  731. break;
  732. }
  733. // Copy over all of the information
  734. //
  735. for (i = 0, pCur32 = pPorts32, pCur64 = pPorts64;
  736. i < dwCount;
  737. i++, pCur32++, pCur64++)
  738. {
  739. pCur64->hPort = UlongToPtr(pCur32->dwPort);
  740. pCur64->hConnection = UlongToPtr(pCur32->dwConnection);
  741. pCur64->dwPortCondition = pCur32->dwPortCondition;
  742. pCur64->dwTotalNumberOfCalls = pCur32->dwTotalNumberOfCalls;
  743. pCur64->dwConnectDuration = pCur32->dwConnectDuration;
  744. wcscpy(pCur64->wszPortName, pCur32->wszPortName);
  745. wcscpy(pCur64->wszMediaName, pCur32->wszMediaName);
  746. wcscpy(pCur64->wszDeviceName, pCur32->wszDeviceName);
  747. wcscpy(pCur64->wszDeviceType, pCur32->wszDeviceType);
  748. }
  749. // Assign the return value
  750. //
  751. *ppPorts0 = pPorts64;
  752. } while (FALSE);
  753. // Cleanup
  754. //
  755. {
  756. if (dwErr != NO_ERROR)
  757. {
  758. if (pPorts64)
  759. {
  760. pFree(pPorts64);
  761. }
  762. }
  763. }
  764. return dwErr;
  765. }
  766. //
  767. // Converts an array of RASI_PORT_1 structures to an array
  768. // of RAS_PORT_1 structures on a 64 bit machine. On a 32
  769. // bit machine, the structures are identical.
  770. //
  771. DWORD
  772. MprThunkPort_32to64_1(
  773. IN RASI_PORT_1* pPorts32,
  774. IN DWORD dwBufferSize,
  775. IN DWORD dwCount,
  776. IN MprThunk_Allocation_Func pAlloc,
  777. IN MprThunk_Free_Func pFree,
  778. OUT RAS_PORT_1** ppPorts1)
  779. {
  780. DWORD dwErr = NO_ERROR, i;
  781. RAS_PORT_1 *pCur64 = NULL, *pPorts64 = NULL;
  782. RASI_PORT_1* pCur32 = NULL;
  783. if (dwCount == 0)
  784. {
  785. *ppPorts1 = NULL;
  786. return NO_ERROR;
  787. }
  788. do
  789. {
  790. // Allocate the new structures
  791. //
  792. pPorts64 = (RAS_PORT_1*)
  793. pAlloc(dwCount * sizeof(RAS_PORT_1));
  794. if (pPorts64 == NULL)
  795. {
  796. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  797. break;
  798. }
  799. // Copy over all of the information
  800. //
  801. for (i = 0, pCur32 = pPorts32, pCur64 = pPorts64;
  802. i < dwCount;
  803. i++, pCur32++, pCur64++)
  804. {
  805. pCur64->hPort = UlongToPtr(pCur32->dwPort);
  806. pCur64->hConnection = UlongToPtr(pCur32->dwConnection);
  807. pCur64->dwHardwareCondition = pCur32->dwHardwareCondition;
  808. pCur64->dwLineSpeed = pCur32->dwLineSpeed;
  809. pCur64->dwBytesXmited = pCur32->dwBytesXmited;
  810. pCur64->dwBytesRcved = pCur32->dwBytesRcved;
  811. pCur64->dwFramesXmited = pCur32->dwFramesXmited;
  812. pCur64->dwFramesRcved = pCur32->dwFramesRcved;
  813. pCur64->dwCrcErr = pCur32->dwCrcErr;
  814. pCur64->dwTimeoutErr = pCur32->dwTimeoutErr;
  815. pCur64->dwAlignmentErr = pCur32->dwAlignmentErr;
  816. pCur64->dwHardwareOverrunErr = pCur32->dwHardwareOverrunErr;
  817. pCur64->dwFramingErr = pCur32->dwFramingErr;
  818. pCur64->dwBufferOverrunErr = pCur32->dwBufferOverrunErr;
  819. pCur64->dwCompressionRatioIn = pCur32->dwCompressionRatioIn;
  820. pCur64->dwCompressionRatioOut= pCur32->dwCompressionRatioOut;
  821. }
  822. // Assign the return value
  823. //
  824. *ppPorts1 = pPorts64;
  825. } while (FALSE);
  826. // Cleanup
  827. //
  828. {
  829. if (dwErr != NO_ERROR)
  830. {
  831. if (pPorts64)
  832. {
  833. pFree(pPorts64);
  834. }
  835. }
  836. }
  837. return dwErr;
  838. }
  839. //
  840. // Convert port structs from the wire representation to the
  841. // host representation
  842. //
  843. DWORD
  844. MprThunkPort_WtoH(
  845. IN DWORD dwLevel,
  846. IN LPBYTE lpbBuffer,
  847. IN DWORD dwBufferSize,
  848. IN DWORD dwCount,
  849. IN MprThunk_Allocation_Func pAlloc,
  850. IN MprThunk_Free_Func pFree,
  851. OUT LPBYTE* lplpbBuffer)
  852. {
  853. DWORD dwErr = NO_ERROR, i;
  854. LPBYTE lpbTemp = NULL;
  855. #ifdef _WIN64
  856. //
  857. // Generate the 64 bit host structures based on the 32 bit
  858. // wire structures.
  859. //
  860. switch (dwLevel)
  861. {
  862. case 0:
  863. dwErr = MprThunkPort_32to64_0(
  864. (RASI_PORT_0*)lpbBuffer,
  865. dwBufferSize,
  866. dwCount,
  867. pAlloc,
  868. pFree,
  869. (RAS_PORT_0**)&lpbTemp);
  870. *lplpbBuffer = lpbTemp;
  871. break;
  872. case 1:
  873. dwErr = MprThunkPort_32to64_1(
  874. (RASI_PORT_1*)lpbBuffer,
  875. dwBufferSize,
  876. dwCount,
  877. pAlloc,
  878. pFree,
  879. (RAS_PORT_1**)&lpbTemp);
  880. *lplpbBuffer = lpbTemp;
  881. break;
  882. }
  883. // Free the unthunked data
  884. //
  885. pFree(lpbBuffer);
  886. #else
  887. // 32 bit -- nothing to do since the structures
  888. // match
  889. //
  890. *lplpbBuffer = lpbBuffer;
  891. #endif
  892. return dwErr;
  893. }
  894. //
  895. // Converts an array of RASI_CONNECTION_0 structures to an array
  896. // of RAS_CONNECTION_0 structures on a 64 bit machine. On a 32
  897. // bit machine, the structures are identical.
  898. //
  899. DWORD
  900. MprThunkConnection_32to64_0(
  901. IN RASI_CONNECTION_0* pConnections32,
  902. IN DWORD dwBufferSize,
  903. IN DWORD dwCount,
  904. IN MprThunk_Allocation_Func pAlloc,
  905. IN MprThunk_Free_Func pFree,
  906. OUT RAS_CONNECTION_0** ppConnections0)
  907. {
  908. DWORD dwErr = NO_ERROR, i;
  909. RAS_CONNECTION_0 *pCur64 = NULL, *pConns64 = NULL;
  910. RASI_CONNECTION_0* pCur32 = NULL;
  911. if (dwCount == 0)
  912. {
  913. *ppConnections0 = NULL;
  914. return NO_ERROR;
  915. }
  916. do
  917. {
  918. // Allocate the new structures
  919. //
  920. pConns64 = (RAS_CONNECTION_0*)
  921. pAlloc(dwCount * sizeof(RAS_CONNECTION_0));
  922. if (pConns64 == NULL)
  923. {
  924. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  925. break;
  926. }
  927. // Copy over all of the information
  928. //
  929. for (i = 0, pCur32 = pConnections32, pCur64 = pConns64;
  930. i < dwCount;
  931. i++, pCur32++, pCur64++)
  932. {
  933. pCur64->hConnection = UlongToPtr(pCur32->dwConnection);
  934. pCur64->hInterface = UlongToPtr(pCur32->dwInterface);
  935. pCur64->dwConnectDuration = pCur32->dwConnectDuration;
  936. pCur64->dwInterfaceType = pCur32->dwInterfaceType;
  937. pCur64->dwConnectionFlags = pCur32->dwConnectionFlags;
  938. wcscpy(pCur64->wszInterfaceName, pCur32->wszInterfaceName);
  939. wcscpy(pCur64->wszUserName, pCur32->wszUserName);
  940. wcscpy(pCur64->wszLogonDomain, pCur32->wszLogonDomain);
  941. wcscpy(pCur64->wszRemoteComputer,pCur32->wszRemoteComputer);
  942. }
  943. // Assign the return value
  944. //
  945. *ppConnections0 = pConns64;
  946. } while (FALSE);
  947. // Cleanup
  948. //
  949. {
  950. if (dwErr != NO_ERROR)
  951. {
  952. if (pConns64)
  953. {
  954. pFree(pConns64);
  955. }
  956. }
  957. }
  958. return dwErr;
  959. }
  960. //
  961. // Converts an array of RASI_CONNECTION_1 structures to an array
  962. // of RAS_CONNECTION_1 structures on a 64 bit machine. On a 32
  963. // bit machine, the structures are identical.
  964. //
  965. DWORD
  966. MprThunkConnection_32to64_1(
  967. IN RASI_CONNECTION_1* pConnections32,
  968. IN DWORD dwBufferSize,
  969. IN DWORD dwCount,
  970. IN MprThunk_Allocation_Func pAlloc,
  971. IN MprThunk_Free_Func pFree,
  972. OUT RAS_CONNECTION_1** ppConnections1)
  973. {
  974. DWORD dwErr = NO_ERROR, i;
  975. RAS_CONNECTION_1 *pCur64 = NULL, *pConns64 = NULL;
  976. RASI_CONNECTION_1* pCur32 = NULL;
  977. if (dwCount == 0)
  978. {
  979. *ppConnections1 = NULL;
  980. return NO_ERROR;
  981. }
  982. do
  983. {
  984. // Allocate the new structures
  985. //
  986. pConns64 = (RAS_CONNECTION_1*)
  987. pAlloc(dwCount * sizeof(RAS_CONNECTION_1));
  988. if (pConns64 == NULL)
  989. {
  990. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  991. break;
  992. }
  993. // Copy over all of the information
  994. //
  995. for (i = 0, pCur32 = pConnections32, pCur64 = pConns64;
  996. i < dwCount;
  997. i++, pCur32++, pCur64++)
  998. {
  999. pCur64->hConnection = UlongToPtr(pCur32->dwConnection);
  1000. pCur64->hInterface = UlongToPtr(pCur32->dwInterface);
  1001. pCur64->PppInfo = pCur32->PppInfo;
  1002. pCur64->dwBytesXmited = pCur32->dwBytesXmited;
  1003. pCur64->dwBytesRcved = pCur32->dwBytesRcved;
  1004. pCur64->dwFramesXmited = pCur32->dwFramesXmited;
  1005. pCur64->dwFramesRcved = pCur32->dwFramesRcved;
  1006. pCur64->dwCrcErr = pCur32->dwCrcErr;
  1007. pCur64->dwTimeoutErr = pCur32->dwTimeoutErr;
  1008. pCur64->dwAlignmentErr = pCur32->dwAlignmentErr;
  1009. pCur64->dwHardwareOverrunErr = pCur32->dwHardwareOverrunErr;
  1010. pCur64->dwFramingErr = pCur32->dwFramingErr;
  1011. pCur64->dwBufferOverrunErr = pCur32->dwBufferOverrunErr;
  1012. pCur64->dwCompressionRatioIn = pCur32->dwCompressionRatioIn;
  1013. pCur64->dwCompressionRatioOut= pCur32->dwCompressionRatioOut;
  1014. }
  1015. // Assign the return value
  1016. //
  1017. *ppConnections1 = pConns64;
  1018. } while (FALSE);
  1019. // Cleanup
  1020. //
  1021. {
  1022. if (dwErr != NO_ERROR)
  1023. {
  1024. if (pConns64)
  1025. {
  1026. pFree(pConns64);
  1027. }
  1028. }
  1029. }
  1030. return dwErr;
  1031. }
  1032. //
  1033. // Converts an array of RASI_CONNECTION_2 structures to an array
  1034. // of RAS_CONNECTION_2 structures on a 64 bit machine. On a 32
  1035. // bit machine, the structures are identical.
  1036. //
  1037. DWORD
  1038. MprThunkConnection_32to64_2(
  1039. IN RASI_CONNECTION_2* pConnections32,
  1040. IN DWORD dwBufferSize,
  1041. IN DWORD dwCount,
  1042. IN MprThunk_Allocation_Func pAlloc,
  1043. IN MprThunk_Free_Func pFree,
  1044. OUT RAS_CONNECTION_2** ppConnections2)
  1045. {
  1046. DWORD dwErr = NO_ERROR, i;
  1047. RAS_CONNECTION_2 *pCur64 = NULL, *pConns64 = NULL;
  1048. RASI_CONNECTION_2* pCur32 = NULL;
  1049. if (dwCount == 0)
  1050. {
  1051. *ppConnections2 = NULL;
  1052. return NO_ERROR;
  1053. }
  1054. do
  1055. {
  1056. // Allocate the new structures
  1057. //
  1058. pConns64 = (RAS_CONNECTION_2*)
  1059. pAlloc(dwCount * sizeof(RAS_CONNECTION_2));
  1060. if (pConns64 == NULL)
  1061. {
  1062. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1063. break;
  1064. }
  1065. // Copy over all of the information
  1066. //
  1067. for (i = 0, pCur32 = pConnections32, pCur64 = pConns64;
  1068. i < dwCount;
  1069. i++, pCur32++, pCur64++)
  1070. {
  1071. pCur64->hConnection = UlongToPtr(pCur32->dwConnection);
  1072. pCur64->dwInterfaceType = pCur32->dwInterfaceType;
  1073. pCur64->guid = pCur32->guid;
  1074. pCur64->PppInfo2 = pCur32->PppInfo2;
  1075. wcscpy(pCur64->wszUserName, pCur32->wszUserName);
  1076. }
  1077. // Assign the return value
  1078. //
  1079. *ppConnections2 = pConns64;
  1080. } while (FALSE);
  1081. // Cleanup
  1082. //
  1083. {
  1084. if (dwErr != NO_ERROR)
  1085. {
  1086. if (pConns64)
  1087. {
  1088. pFree(pConns64);
  1089. }
  1090. }
  1091. }
  1092. return dwErr;
  1093. }
  1094. //
  1095. // Convert connection structs from the wire representation to the
  1096. // host representation
  1097. //
  1098. DWORD
  1099. MprThunkConnection_WtoH(
  1100. IN DWORD dwLevel,
  1101. IN LPBYTE lpbBuffer,
  1102. IN DWORD dwBufferSize,
  1103. IN DWORD dwCount,
  1104. IN MprThunk_Allocation_Func pAlloc,
  1105. IN MprThunk_Free_Func pFree,
  1106. OUT LPBYTE* lplpbBuffer)
  1107. {
  1108. DWORD dwErr = NO_ERROR, i;
  1109. LPBYTE lpbTemp = NULL;
  1110. #ifdef _WIN64
  1111. //
  1112. // Generate the 64 bit host structures based on the 32 bit
  1113. // wire structures.
  1114. //
  1115. switch (dwLevel)
  1116. {
  1117. case 0:
  1118. dwErr = MprThunkConnection_32to64_0(
  1119. (RASI_CONNECTION_0*)lpbBuffer,
  1120. dwBufferSize,
  1121. dwCount,
  1122. pAlloc,
  1123. pFree,
  1124. (RAS_CONNECTION_0**)&lpbTemp);
  1125. *lplpbBuffer = lpbTemp;
  1126. break;
  1127. case 1:
  1128. dwErr = MprThunkConnection_32to64_1(
  1129. (RASI_CONNECTION_1*)lpbBuffer,
  1130. dwBufferSize,
  1131. dwCount,
  1132. pAlloc,
  1133. pFree,
  1134. (RAS_CONNECTION_1**)&lpbTemp);
  1135. *lplpbBuffer = lpbTemp;
  1136. break;
  1137. case 2:
  1138. dwErr = MprThunkConnection_32to64_2(
  1139. (RASI_CONNECTION_2*)lpbBuffer,
  1140. dwBufferSize,
  1141. dwCount,
  1142. pAlloc,
  1143. pFree,
  1144. (RAS_CONNECTION_2**)&lpbTemp);
  1145. *lplpbBuffer = lpbTemp;
  1146. break;
  1147. }
  1148. // Free the unthunked data
  1149. //
  1150. pFree(lpbBuffer);
  1151. #else
  1152. // 32 bit -- nothing to do since the structures
  1153. // match
  1154. //
  1155. *lplpbBuffer = lpbBuffer;
  1156. #endif
  1157. return dwErr;
  1158. }
  1159. DWORD
  1160. MprThunkCredentials_WtoH(
  1161. IN DWORD dwLevel,
  1162. IN MPR_CREDENTIALSEXI *pCredsI,
  1163. IN MprThunk_Allocation_Func pAlloc,
  1164. OUT PBYTE *lplpbBuffer)
  1165. {
  1166. DWORD dwRetCode = NO_ERROR;
  1167. if(NULL == pCredsI)
  1168. {
  1169. dwRetCode = E_INVALIDARG;
  1170. goto done;
  1171. }
  1172. switch(dwLevel)
  1173. {
  1174. case 0:
  1175. case 1:
  1176. case 2:
  1177. {
  1178. //
  1179. // the credentials structure is structurally the
  1180. // same for all levels. We just use the strcuture
  1181. // for level 0 for all cases.
  1182. //
  1183. MPR_CREDENTIALSEX_0 *pCred0 = NULL;
  1184. pCred0 = pAlloc(
  1185. pCredsI->dwSize
  1186. + sizeof(MPR_CREDENTIALSEX_0));
  1187. if(NULL == pCred0)
  1188. {
  1189. dwRetCode = GetLastError();
  1190. break;
  1191. }
  1192. pCred0->dwSize = pCredsI->dwSize;
  1193. pCred0->lpbCredentialsInfo = (PBYTE) (pCred0 + 1);
  1194. CopyMemory(
  1195. pCred0->lpbCredentialsInfo,
  1196. ((PBYTE) pCredsI) + pCredsI->dwOffset,
  1197. pCredsI->dwSize);
  1198. *lplpbBuffer = (PBYTE) pCred0;
  1199. break;
  1200. }
  1201. default:
  1202. {
  1203. dwRetCode = E_INVALIDARG;
  1204. break;
  1205. }
  1206. }
  1207. done:
  1208. return dwRetCode;
  1209. }
  1210. DWORD
  1211. MprThunkCredentials_HtoW(
  1212. IN DWORD dwLevel,
  1213. IN BYTE *pBuffer,
  1214. IN MprThunk_Allocation_Func pAlloc,
  1215. OUT DWORD *pdwSize,
  1216. OUT PBYTE *lplpbBuffer)
  1217. {
  1218. DWORD dwRetCode = NO_ERROR;
  1219. MPR_CREDENTIALSEX_0 *pCreds0 = (MPR_CREDENTIALSEX_0 *) pBuffer;
  1220. if( (NULL == pCreds0)
  1221. || (NULL == lplpbBuffer)
  1222. || (NULL == pdwSize))
  1223. {
  1224. dwRetCode = E_INVALIDARG;
  1225. goto done;
  1226. }
  1227. if(NULL == pAlloc)
  1228. {
  1229. pAlloc = MprThunkAlloc;
  1230. }
  1231. switch(dwLevel)
  1232. {
  1233. case 0:
  1234. case 1:
  1235. case 2:
  1236. {
  1237. MPR_CREDENTIALSEXI *pCredsI;
  1238. //
  1239. // allocate for pCredsI
  1240. //
  1241. *pdwSize = pCreds0->dwSize + sizeof(MPR_CREDENTIALSEXI);
  1242. pCredsI = (MPR_CREDENTIALSEXI *) pAlloc(*pdwSize);
  1243. if(NULL == pCredsI)
  1244. {
  1245. dwRetCode = GetLastError();
  1246. break;
  1247. }
  1248. ZeroMemory(pCredsI, *pdwSize);
  1249. pCredsI->dwSize = pCreds0->dwSize;
  1250. pCredsI->dwOffset = FIELD_OFFSET(MPR_CREDENTIALSEXI, bData);
  1251. CopyMemory((pCredsI->bData),
  1252. (PBYTE) pCreds0->lpbCredentialsInfo,
  1253. pCreds0->dwSize);
  1254. *lplpbBuffer = (BYTE *) pCredsI;
  1255. break;
  1256. }
  1257. default:
  1258. {
  1259. dwRetCode = E_INVALIDARG;
  1260. break;
  1261. }
  1262. }
  1263. done:
  1264. return dwRetCode;
  1265. }