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.

864 lines
21 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. crconv.c
  5. Abstract:
  6. This module contains credential conversion routines shared between advapi32.dll and crtest.exe
  7. Author:
  8. Cliff Van Dyke (CliffV) February 25, 2000
  9. Revision History:
  10. --*/
  11. DWORD
  12. CredpConvertStringSize (
  13. IN WTOA_ENUM WtoA,
  14. IN LPWSTR String OPTIONAL
  15. )
  16. /*++
  17. Routine Description:
  18. Determines the size of the converted string
  19. Arguments:
  20. WtoA - Specifies the direction of the string conversion.
  21. String - The string to convert
  22. Return Values:
  23. Returns the size (in bytes) of the converted string.
  24. --*/
  25. {
  26. ULONG Size = 0;
  27. UNICODE_STRING UnicodeString;
  28. ANSI_STRING AnsiString;
  29. if ( String == NULL ) {
  30. return Size;
  31. }
  32. switch ( WtoA ) {
  33. case DoWtoA:
  34. RtlInitUnicodeString( &UnicodeString, String );
  35. Size = RtlUnicodeStringToAnsiSize( &UnicodeString );
  36. break;
  37. case DoAtoW:
  38. RtlInitAnsiString( &AnsiString, (LPSTR)String );
  39. Size = RtlAnsiStringToUnicodeSize( &AnsiString );
  40. break;
  41. case DoWtoW:
  42. Size = (wcslen( String ) + 1) * sizeof(WCHAR);
  43. break;
  44. }
  45. return Size;
  46. }
  47. DWORD
  48. CredpConvertString (
  49. IN WTOA_ENUM WtoA,
  50. IN LPWSTR String OPTIONAL,
  51. OUT LPWSTR *OutString,
  52. IN OUT LPBYTE *WherePtr
  53. )
  54. /*++
  55. Routine Description:
  56. Determines the size of the converted string
  57. Arguments:
  58. WtoA - Specifies the direction of the string conversion.
  59. String - The string to convert
  60. OutString - Returns the pointer to the marshaled string
  61. WherePtr - Specifies the address of the first byte to write the string to.
  62. Returns a pointer to the first byte after the marshaled string
  63. Return Values:
  64. Returns the status of the conversion
  65. --*/
  66. {
  67. NTSTATUS Status;
  68. ULONG Size;
  69. UNICODE_STRING UnicodeString;
  70. ANSI_STRING AnsiString;
  71. LPBYTE Where = *WherePtr;
  72. if ( String == NULL ) {
  73. *OutString = NULL;
  74. return NO_ERROR;
  75. }
  76. *OutString = (LPWSTR)Where;
  77. switch ( WtoA ) {
  78. case DoWtoA:
  79. RtlInitUnicodeString( &UnicodeString, String );
  80. AnsiString.Buffer = (PCHAR)Where;
  81. AnsiString.MaximumLength = 0xFFFF;
  82. Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
  83. if ( !NT_SUCCESS(Status) ) {
  84. return RtlNtStatusToDosError( Status );
  85. }
  86. Where += AnsiString.Length + sizeof(CHAR);
  87. break;
  88. case DoAtoW:
  89. RtlInitAnsiString( &AnsiString, (LPSTR)String );
  90. UnicodeString.Buffer = (LPWSTR)Where;
  91. UnicodeString.MaximumLength = 0xFFFF;
  92. Status = RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
  93. if ( !NT_SUCCESS(Status) ) {
  94. return RtlNtStatusToDosError( Status );
  95. }
  96. Where += UnicodeString.Length + sizeof(WCHAR);
  97. break;
  98. case DoWtoW:
  99. Size = (wcslen( String ) + 1) * sizeof(WCHAR);
  100. RtlCopyMemory( Where, String, Size );
  101. Where += Size;
  102. break;
  103. }
  104. *WherePtr = Where;
  105. return NO_ERROR;
  106. }
  107. DWORD
  108. CredpConvertOneCredentialSize (
  109. IN WTOA_ENUM WtoA,
  110. IN PCREDENTIALW InCredential
  111. )
  112. /*++
  113. Routine Description:
  114. Computes the size of a converted credential
  115. Arguments:
  116. WtoA - Specifies the direction of the string conversion.
  117. InCredential - Input credential
  118. Return Values:
  119. Returns the size (in bytes) the CredpConvertOneCredential will need to
  120. copy this credential into a buffer.
  121. --*/
  122. {
  123. DWORD WinStatus;
  124. ULONG Size;
  125. ULONG i;
  126. //
  127. // Compute the initial size
  128. //
  129. Size = ROUND_UP_COUNT( sizeof(ENCRYPTED_CREDENTIALW), ALIGN_WORST ) +
  130. ROUND_UP_COUNT( InCredential->AttributeCount * sizeof(CREDENTIAL_ATTRIBUTEW), ALIGN_WORST );
  131. if ( InCredential->CredentialBlobSize != 0 ) {
  132. ULONG CredBlobSize;
  133. // Leave room for the encoding over the wire
  134. CredBlobSize = AllocatedCredBlobSize( InCredential->CredentialBlobSize );
  135. // Align the data following the credential blob
  136. Size += ROUND_UP_COUNT( CredBlobSize, ALIGN_WORST );
  137. }
  138. //
  139. // Compute the size of the strings in the right character set.
  140. //
  141. Size += CredpConvertStringSize( WtoA, InCredential->TargetName );
  142. Size += CredpConvertStringSize( WtoA, InCredential->Comment );
  143. Size += CredpConvertStringSize( WtoA, InCredential->TargetAlias );
  144. Size += CredpConvertStringSize( WtoA, InCredential->UserName );
  145. //
  146. // Compute the size of the attributes
  147. //
  148. if ( InCredential->AttributeCount != 0 ) {
  149. for ( i=0; i<InCredential->AttributeCount; i++ ) {
  150. Size += CredpConvertStringSize( WtoA, InCredential->Attributes[i].Keyword );
  151. Size += ROUND_UP_COUNT(InCredential->Attributes[i].ValueSize, ALIGN_WORST);
  152. }
  153. }
  154. Size = ROUND_UP_COUNT( Size, ALIGN_WORST );
  155. return Size;
  156. }
  157. DWORD
  158. CredpConvertOneCredential (
  159. IN WTOA_ENUM WtoA,
  160. IN ENCODE_BLOB_ENUM DoDecode,
  161. IN PCREDENTIALW InCredential,
  162. IN OUT LPBYTE *WherePtr
  163. )
  164. /*++
  165. Routine Description:
  166. Converts one credential from Ansi to Unicode or vice-versa.
  167. Arguments:
  168. WtoA - Specifies the direction of the string conversion.
  169. DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither.
  170. If DoBlobDecode, then InCredential really points to a PENCRYPTED_CREDENTIALW.
  171. InCredential - Input credentials
  172. WherePtr - Specifies the address of the first byte to write the credential to.
  173. On input, the strucure should be aligned ALIGN_WORST.
  174. Returns a pointer to the first byte after the marshaled credential.
  175. The output credential is actually a ENCRYPTED_CREDENTIALW. The caller
  176. can use it as a CREDENTIALW depending on the DoDecode value.
  177. Return Values:
  178. Window status code
  179. --*/
  180. {
  181. DWORD WinStatus;
  182. ULONG i;
  183. LPBYTE Where = *WherePtr;
  184. LPBYTE OldWhere;
  185. PENCRYPTED_CREDENTIALW OutCredential;
  186. //
  187. // Initialize the base structure
  188. //
  189. OutCredential = (PENCRYPTED_CREDENTIALW) Where;
  190. RtlZeroMemory( OutCredential, sizeof(*OutCredential) );
  191. Where += sizeof(*OutCredential);
  192. // Align the running pointer again
  193. OldWhere = Where;
  194. Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST );
  195. RtlZeroMemory( OldWhere, Where-OldWhere );
  196. //
  197. // Copy the fixed size data
  198. //
  199. OutCredential->Cred.Flags = InCredential->Flags;
  200. OutCredential->Cred.Type = InCredential->Type;
  201. OutCredential->Cred.LastWritten = InCredential->LastWritten;
  202. OutCredential->Cred.CredentialBlobSize = InCredential->CredentialBlobSize;
  203. OutCredential->Cred.Persist = InCredential->Persist;
  204. OutCredential->Cred.AttributeCount = InCredential->AttributeCount;
  205. //
  206. // Copy the data we don't know the alignment for.
  207. // (ALIGN_WORST so our caller can't blame us.)
  208. //
  209. if ( InCredential->CredentialBlobSize != 0 ) {
  210. ULONG CredBlobSize;
  211. OutCredential->Cred.CredentialBlob = Where;
  212. RtlCopyMemory( Where, InCredential->CredentialBlob, InCredential->CredentialBlobSize );
  213. Where += InCredential->CredentialBlobSize;
  214. // Leave room for the encoding over the wire
  215. CredBlobSize = AllocatedCredBlobSize( InCredential->CredentialBlobSize );
  216. // Align the running pointer again
  217. OldWhere = Where;
  218. // Align the data following the credential blob
  219. Where = (LPBYTE) ROUND_UP_POINTER( OldWhere+(CredBlobSize-InCredential->CredentialBlobSize), ALIGN_WORST );
  220. RtlZeroMemory( OldWhere, Where-OldWhere );
  221. //
  222. // Encode or decode the Credential blob as requested
  223. //
  224. switch (DoDecode) {
  225. case DoBlobDecode:
  226. OutCredential->ClearCredentialBlobSize = ((PENCRYPTED_CREDENTIALW)InCredential)->ClearCredentialBlobSize;
  227. #ifndef _CRTEST_EXE_
  228. CredpDecodeCredential( OutCredential );
  229. #endif // _CRTEST_EXE_
  230. break;
  231. case DoBlobEncode:
  232. OutCredential->ClearCredentialBlobSize = InCredential->CredentialBlobSize;
  233. #ifndef _CRTEST_EXE_
  234. if (!CredpEncodeCredential( OutCredential ) ) {
  235. return ERROR_INVALID_PARAMETER;
  236. }
  237. #endif // _CRTEST_EXE_
  238. break;
  239. case DoBlobNeither:
  240. OutCredential->ClearCredentialBlobSize = InCredential->CredentialBlobSize;
  241. break;
  242. default:
  243. return ERROR_INVALID_PARAMETER;
  244. }
  245. }
  246. if ( InCredential->AttributeCount != 0 ) {
  247. //
  248. // Push an array of attribute structs
  249. //
  250. OutCredential->Cred.Attributes = (PCREDENTIAL_ATTRIBUTEW) Where;
  251. Where += InCredential->AttributeCount * sizeof(CREDENTIAL_ATTRIBUTEW);
  252. // Align the running pointer again
  253. OldWhere = Where;
  254. Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST );
  255. RtlZeroMemory( OldWhere, Where-OldWhere );
  256. //
  257. // Fill it in.
  258. //
  259. for ( i=0; i<InCredential->AttributeCount; i++ ) {
  260. OutCredential->Cred.Attributes[i].Flags = InCredential->Attributes[i].Flags;
  261. OutCredential->Cred.Attributes[i].ValueSize = InCredential->Attributes[i].ValueSize;
  262. if ( InCredential->Attributes[i].ValueSize != 0 ) {
  263. OutCredential->Cred.Attributes[i].Value = Where;
  264. RtlCopyMemory( Where, InCredential->Attributes[i].Value, InCredential->Attributes[i].ValueSize );
  265. Where += InCredential->Attributes[i].ValueSize;
  266. // Align the running pointer again
  267. OldWhere = Where;
  268. Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST );
  269. RtlZeroMemory( OldWhere, Where-OldWhere );
  270. } else {
  271. OutCredential->Cred.Attributes[i].Value = NULL;
  272. }
  273. }
  274. }
  275. //
  276. // Convert the strings to the right character set.
  277. //
  278. WinStatus = CredpConvertString( WtoA, InCredential->TargetName, &OutCredential->Cred.TargetName, &Where );
  279. if ( WinStatus != NO_ERROR ) {
  280. goto Cleanup;
  281. }
  282. WinStatus = CredpConvertString( WtoA, InCredential->Comment, &OutCredential->Cred.Comment, &Where );
  283. if ( WinStatus != NO_ERROR ) {
  284. goto Cleanup;
  285. }
  286. WinStatus = CredpConvertString( WtoA, InCredential->TargetAlias, &OutCredential->Cred.TargetAlias, &Where );
  287. if ( WinStatus != NO_ERROR ) {
  288. goto Cleanup;
  289. }
  290. WinStatus = CredpConvertString( WtoA, InCredential->UserName, &OutCredential->Cred.UserName, &Where );
  291. if ( WinStatus != NO_ERROR ) {
  292. goto Cleanup;
  293. }
  294. if ( InCredential->AttributeCount != 0 ) {
  295. for ( i=0; i<InCredential->AttributeCount; i++ ) {
  296. WinStatus = CredpConvertString( WtoA, InCredential->Attributes[i].Keyword, &OutCredential->Cred.Attributes[i].Keyword, &Where );
  297. if ( WinStatus != NO_ERROR ) {
  298. goto Cleanup;
  299. }
  300. }
  301. }
  302. // Align the running pointer again
  303. OldWhere = Where;
  304. Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST );
  305. RtlZeroMemory( OldWhere, Where-OldWhere );
  306. *WherePtr = Where;
  307. WinStatus = NO_ERROR;
  308. //
  309. // Be tidy
  310. //
  311. Cleanup:
  312. return WinStatus;
  313. }
  314. #ifndef _CRTEST_EXE_
  315. DWORD
  316. APIENTRY
  317. CredpConvertCredential (
  318. IN WTOA_ENUM WtoA,
  319. IN ENCODE_BLOB_ENUM DoDecode,
  320. IN PCREDENTIALW InCredential,
  321. OUT PCREDENTIALW *OutCredential
  322. )
  323. /*++
  324. Routine Description:
  325. Converts a credential from Ansi to Unicode or vice-versa.
  326. Arguments:
  327. WtoA - Specifies the direction of the string conversion.
  328. DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither.
  329. InCredential - Input credentials
  330. OutCredential - Output credential
  331. This credential should be freed using MIDL_user_free.
  332. Return Values:
  333. Window status code
  334. --*/
  335. {
  336. DWORD WinStatus;
  337. ULONG Size = 0;
  338. LPBYTE Where;
  339. //
  340. // BVTs pass NULL explicitly. We could let the AV be caught in the try/except, but
  341. // that would prevent them from being able to run under a debugger. So, handle NULL
  342. // explicitly.
  343. //
  344. if ( InCredential == NULL ) {
  345. return ERROR_INVALID_PARAMETER;
  346. }
  347. //
  348. // Use an exception handle to prevent bad user parameter from AVing in our code.
  349. //
  350. #ifndef _CRTEST_EXE_
  351. try {
  352. #endif // _CRTEST_EXE_
  353. //
  354. // Compute the size needed for the output credential
  355. //
  356. Size = CredpConvertOneCredentialSize( WtoA, InCredential );
  357. //
  358. // Allocate a buffer for the resultant credential
  359. //
  360. *OutCredential = (PCREDENTIALW) MIDL_user_allocate( Size );
  361. if ( *OutCredential == NULL ) {
  362. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  363. goto Cleanup;
  364. }
  365. //
  366. // Convert the credential into the allocated buffer
  367. //
  368. Where = (LPBYTE) *OutCredential;
  369. WinStatus = CredpConvertOneCredential( WtoA, DoDecode, InCredential, &Where );
  370. if ( WinStatus != NO_ERROR ) {
  371. MIDL_user_free( *OutCredential );
  372. *OutCredential = NULL;
  373. } else {
  374. ASSERT( (ULONG)(Where - ((LPBYTE)*OutCredential)) == Size );
  375. }
  376. Cleanup: NOTHING;
  377. #ifndef _CRTEST_EXE_
  378. } except( EXCEPTION_EXECUTE_HANDLER ) {
  379. WinStatus = ERROR_INVALID_PARAMETER;
  380. }
  381. #endif // _CRTEST_EXE_
  382. return WinStatus;
  383. }
  384. DWORD
  385. APIENTRY
  386. CredpConvertTargetInfo (
  387. IN WTOA_ENUM WtoA,
  388. IN PCREDENTIAL_TARGET_INFORMATIONW InTargetInfo,
  389. OUT PCREDENTIAL_TARGET_INFORMATIONW *OutTargetInfo,
  390. OUT PULONG OutTargetInfoSize OPTIONAL
  391. )
  392. /*++
  393. Routine Description:
  394. Converts a target info from Ansi to Unicode or vice-versa.
  395. Arguments:
  396. WtoA - Specifies the direction of the string conversion.
  397. InTargetInfo - Input TargetInfo
  398. OutTargetInfo - Output TargetInfo
  399. This TargetInfo should be freed using CredFree.
  400. OutTargetInfoSize - Size (in bytes) of the buffer returned in OutTargetInfo
  401. Return Values:
  402. Window status code
  403. --*/
  404. {
  405. DWORD WinStatus;
  406. ULONG Size;
  407. LPBYTE Where;
  408. *OutTargetInfo = NULL;
  409. //
  410. // BVTs pass NULL explicitly. We could let the AV be caught in the try/except, but
  411. // that would prevent them from being able to run under a debugger. So, handle NULL
  412. // explicitly.
  413. //
  414. if ( InTargetInfo == NULL ) {
  415. return ERROR_INVALID_PARAMETER;
  416. }
  417. //
  418. // Use an exception handle to prevent bad user parameter from AVing in our code.
  419. //
  420. #ifndef _CRTEST_EXE_
  421. try {
  422. #endif // _CRTEST_EXE_
  423. //
  424. // Compute the size needed for the output target info
  425. //
  426. Size = sizeof(CREDENTIAL_TARGET_INFORMATIONW);
  427. //
  428. // Compute the size of the strings in the right character set.
  429. //
  430. Size += CredpConvertStringSize( WtoA, InTargetInfo->TargetName );
  431. Size += CredpConvertStringSize( WtoA, InTargetInfo->NetbiosServerName );
  432. Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsServerName );
  433. Size += CredpConvertStringSize( WtoA, InTargetInfo->NetbiosDomainName );
  434. Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsDomainName );
  435. Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsTreeName );
  436. Size += CredpConvertStringSize( WtoA, InTargetInfo->PackageName );
  437. Size += InTargetInfo->CredTypeCount * sizeof(DWORD);
  438. //
  439. // Allocate a buffer for the resultant credential
  440. //
  441. *OutTargetInfo = (PCREDENTIAL_TARGET_INFORMATIONW) MIDL_user_allocate( Size );
  442. if ( *OutTargetInfo == NULL ) {
  443. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  444. goto Cleanup;
  445. }
  446. if ( ARGUMENT_PRESENT(OutTargetInfoSize) ) {
  447. *OutTargetInfoSize = Size;
  448. }
  449. Where = (LPBYTE)((*OutTargetInfo) + 1);
  450. //
  451. // Copy the fixed size data
  452. //
  453. (*OutTargetInfo)->Flags = InTargetInfo->Flags;
  454. //
  455. // Copy the DWORD aligned data
  456. //
  457. (*OutTargetInfo)->CredTypeCount = InTargetInfo->CredTypeCount;
  458. if ( InTargetInfo->CredTypeCount != 0 ) {
  459. (*OutTargetInfo)->CredTypes = (LPDWORD) Where;
  460. RtlCopyMemory( Where, InTargetInfo->CredTypes, InTargetInfo->CredTypeCount * sizeof(DWORD) );
  461. Where += InTargetInfo->CredTypeCount * sizeof(DWORD);
  462. } else {
  463. (*OutTargetInfo)->CredTypes = NULL;
  464. }
  465. //
  466. // Convert the strings to the right character set.
  467. //
  468. WinStatus = CredpConvertString( WtoA, InTargetInfo->TargetName, &(*OutTargetInfo)->TargetName, &Where );
  469. if ( WinStatus != NO_ERROR ) {
  470. goto Cleanup;
  471. }
  472. WinStatus = CredpConvertString( WtoA, InTargetInfo->NetbiosServerName, &(*OutTargetInfo)->NetbiosServerName, &Where );
  473. if ( WinStatus != NO_ERROR ) {
  474. goto Cleanup;
  475. }
  476. WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsServerName, &(*OutTargetInfo)->DnsServerName, &Where );
  477. if ( WinStatus != NO_ERROR ) {
  478. goto Cleanup;
  479. }
  480. WinStatus = CredpConvertString( WtoA, InTargetInfo->NetbiosDomainName, &(*OutTargetInfo)->NetbiosDomainName, &Where );
  481. if ( WinStatus != NO_ERROR ) {
  482. goto Cleanup;
  483. }
  484. WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsDomainName, &(*OutTargetInfo)->DnsDomainName, &Where );
  485. if ( WinStatus != NO_ERROR ) {
  486. goto Cleanup;
  487. }
  488. WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsTreeName, &(*OutTargetInfo)->DnsTreeName, &Where );
  489. if ( WinStatus != NO_ERROR ) {
  490. goto Cleanup;
  491. }
  492. WinStatus = CredpConvertString( WtoA, InTargetInfo->PackageName, &(*OutTargetInfo)->PackageName, &Where );
  493. if ( WinStatus != NO_ERROR ) {
  494. goto Cleanup;
  495. }
  496. ASSERT( (ULONG)(Where - ((LPBYTE)*OutTargetInfo)) == Size );
  497. Cleanup: NOTHING;
  498. #ifndef _CRTEST_EXE_
  499. } except( EXCEPTION_EXECUTE_HANDLER ) {
  500. WinStatus = ERROR_INVALID_PARAMETER;
  501. }
  502. #endif // _CRTEST_EXE_
  503. //
  504. // Be tidy
  505. //
  506. if ( WinStatus != NO_ERROR ) {
  507. if ( *OutTargetInfo != NULL ) {
  508. MIDL_user_free( *OutTargetInfo );
  509. *OutTargetInfo = NULL;
  510. }
  511. }
  512. return WinStatus;
  513. }
  514. #endif // _CRTEST_EXE_
  515. DWORD
  516. CredpConvertCredentials (
  517. IN WTOA_ENUM WtoA,
  518. IN ENCODE_BLOB_ENUM DoDecode,
  519. IN PCREDENTIALW *InCredential,
  520. IN ULONG InCredentialCount,
  521. OUT PCREDENTIALW **OutCredential
  522. )
  523. /*++
  524. Routine Description:
  525. Converts a set of credentials from Ansi to Unicode or vice-versa.
  526. Arguments:
  527. WtoA - Specifies the direction of the string conversion.
  528. DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither.
  529. InCredential - Input credentials
  530. OutCredential - Output credential
  531. This credential should be freed using MIDL_user_free.
  532. Return Values:
  533. Window status code
  534. --*/
  535. {
  536. DWORD WinStatus;
  537. ULONG Size = 0;
  538. ULONG i;
  539. LPBYTE Where;
  540. LPBYTE OldWhere;
  541. *OutCredential = NULL;
  542. //
  543. // Use an exception handle to prevent bad user parameter from AVing in our code.
  544. //
  545. #ifndef _CRTEST_EXE_
  546. try {
  547. #endif // _CRTEST_EXE_
  548. //
  549. // Compute the size needed for the output credentials
  550. //
  551. for ( i=0; i<InCredentialCount; i++ ) {
  552. Size += CredpConvertOneCredentialSize( WtoA, InCredential[i] );
  553. }
  554. //
  555. // Allocate a buffer for the resultant credential array
  556. //
  557. Size += ROUND_UP_COUNT( InCredentialCount * sizeof(PCREDENTIALW), ALIGN_WORST );
  558. *OutCredential = (PCREDENTIALW *)MIDL_user_allocate( Size );
  559. if ( *OutCredential == NULL ) {
  560. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  561. goto Cleanup;
  562. }
  563. //
  564. // Convert the credential into the allocated buffer
  565. //
  566. Where = (LPBYTE) *OutCredential;
  567. Where += InCredentialCount * sizeof(PCREDENTIALW);
  568. // Align the running pointer again
  569. OldWhere = Where;
  570. Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST );
  571. RtlZeroMemory( OldWhere, Where-OldWhere );
  572. for ( i=0; i<InCredentialCount; i++ ) {
  573. //
  574. // Save a pointer to this credential
  575. //
  576. (*OutCredential)[i] = (PCREDENTIALW) Where;
  577. //
  578. // Marshal the credential
  579. //
  580. WinStatus = CredpConvertOneCredential( WtoA, DoDecode, InCredential[i], &Where );
  581. if ( WinStatus != NO_ERROR ) {
  582. goto Cleanup;
  583. }
  584. }
  585. ASSERT( (ULONG)(Where - ((LPBYTE)*OutCredential)) == Size );
  586. WinStatus = NO_ERROR;
  587. Cleanup: NOTHING;
  588. #ifndef _CRTEST_EXE_
  589. } except( EXCEPTION_EXECUTE_HANDLER ) {
  590. WinStatus = ERROR_INVALID_PARAMETER;
  591. }
  592. #endif // _CRTEST_EXE_
  593. if ( WinStatus != NO_ERROR ) {
  594. if ( *OutCredential != NULL ) {
  595. MIDL_user_free( *OutCredential );
  596. *OutCredential = NULL;
  597. }
  598. }
  599. return WinStatus;
  600. }