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.

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