@@ -3979,24 +3979,24 @@ public void AddValidationData(string PackageIdentifier,string gitHubUserName = "
39793979 //Extend/reference CredWriteW as CredWrite.
39803980
39813981 [ DllImport ( "Advapi32.dll" , SetLastError = true , EntryPoint = "CredFree" , CharSet = CharSet . Unicode ) ]
3982- private static extern bool CredRelease ( [ In ] IntPtr credentialPtr ) ;
3983- //Extend/reference CredFree as CredWrite .
3982+ private static extern void CredRelease ( [ In ] IntPtr credentialPtr ) ;
3983+ //Extend/reference CredFree as CredRelease .
39843984
39853985 public static Credential GetUserCredential ( string target ) {
39863986 CredentialMem credMem ;
39873987 IntPtr credPtr ;
39883988 if ( CredRead ( target , 1 , 0 , out credPtr ) ) { //If found, returns true and adds to credPtr, else false and error.
3989- credMem = Marshal . PtrToStructure < CredentialMem > ( credPtr ) ;
3990- //"Marshals data from an unmanaged block of memory to a newly allocated managed object of the type specified by a generic type parameter."
3991- byte [ ] passwordBytes = new byte [ credMem . credentialBlobSize ] ; //Make a new byte array passwordBytes of size credentialBlobSize.
3992- Marshal . Copy ( credMem . credentialBlob , passwordBytes , 0 , credMem . credentialBlobSize ) ;
3993- //Copies data from an unmanaged memory pointer to a managed 8-bit unsigned integer array.
3994- //
3995- Credential cred = new Credential ( credMem . targetName , credMem . userName , Encoding . Unicode . GetString ( passwordBytes ) ) ; //Make a new Credential object cred.
3996- //Original example doesn't include these:
3997- CredRelease ( credPtr ) ;
3998- CredRelease ( credMem . credentialBlob ) ;
3999- return cred ;
3989+ try {
3990+ credMem = Marshal . PtrToStructure < CredentialMem > ( credPtr ) ;
3991+ //"Marshals data from an unmanaged block of memory to a newly allocated managed object of the type specified by a generic type parameter."
3992+ byte [ ] passwordBytes = new byte [ credMem . credentialBlobSize ] ; //Make a new byte array passwordBytes of size credentialBlobSize.
3993+ Marshal . Copy ( credMem . credentialBlob , passwordBytes , 0 , credMem . credentialBlobSize ) ;
3994+ //Copies data from an unmanaged memory pointer to a managed 8-bit unsigned integer array.
3995+ return new Credential ( credMem . targetName , credMem . userName , Encoding . Unicode . GetString ( passwordBytes ) ) ; //Make a new Credential object cred.
3996+ } finally {
3997+ //credentialBlob is an interior pointer into credPtr; free the buffer once via CredFree.
3998+ if ( credPtr != IntPtr . Zero ) { CredRelease ( credPtr ) ; }
3999+ }
40004000 } else {
40014001 throw new Exception ( "Failed to retrieve credentials" ) ;
40024002 }
@@ -4014,11 +4014,14 @@ public static void SetUserCredential(string target, string userName, string pass
40144014 userCredential . credentialBlobSize = ( int ) bpassword . Length ;
40154015 userCredential . credentialBlob = Marshal . StringToCoTaskMemUni ( password ) ;
40164016 //If write fails, emit last error.
4017- if ( ! CredWrite ( ref userCredential , 0 ) ) {
4018- throw new System . ComponentModel . Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
4017+ try {
4018+ if ( ! CredWrite ( ref userCredential , 0 ) ) {
4019+ throw new System . ComponentModel . Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
4020+ }
4021+ } finally {
4022+ //Match StringToCoTaskMemUni allocation with FreeCoTaskMem.
4023+ Marshal . FreeCoTaskMem ( userCredential . credentialBlob ) ;
40194024 }
4020- //Original example doesn't include this. Was going to use FreeCoTaskMem as recommended, but this gave an error.
4021- Marshal . FreeCoTaskMem ( userCredential . credentialBlob ) ;
40224025 }
40234026
40244027 [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Unicode ) ]
0 commit comments