2010-03-08 19 views
3

我試圖使用CredWrite,但得到一個ERROR_INVALID_PARAMETER 87 (0x57)錯誤。目的是要有一個安全的地方來保存我的.net WPF應用程序的用戶密碼。有沒有人在.NET中使用Win32 API函數CredWrite?

而且我的代碼:

public class CredMan 
{ 
    private const string TARGET_PREFIX = "myappname:"; 

    public static void SavePassword(string username, string password) 
    { 
     Win32CredMan.Credential cred = new Win32CredMan.Credential(); 
     cred.Flags = 0; 
     cred.Type = Win32CredMan.CRED_TYPE.GENERIC; 
     cred.TargetName = TARGET_PREFIX + username; 

     var encoding = new System.Text.UTF8Encoding(); 
     cred.CredentialBlob = encoding.GetBytes(password); 
     cred.Persist = Win32CredMan.CRED_PERSIST.LOCAL_MACHINE; 
     cred.UserName = username; 

     bool isGood = Win32CredMan.CredWrite(cred, 0); 
     int lastError = Marshal.GetLastWin32Error(); 

    } 
} 

這是Win32的包裝:(主要來自pinvoke.net搶下)

internal class Win32CredMan 
{ 
    [DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)] 
    public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, 
         [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(CredentialInMarshaler))]out Credential credential); 

    [DllImport("Advapi32.dll", EntryPoint = "CredFreeW", CharSet = CharSet.Unicode, SetLastError = true)] 
    public static extern void CredFree(IntPtr buffer); 

    [DllImport("Advapi32.dll", SetLastError = true, EntryPoint = "CredWriteW", CharSet = CharSet.Unicode)] 
    public static extern bool CredWrite([In] Credential userCredential, [In] UInt32 flags); 

    public enum CRED_TYPE : uint 
    { 
     GENERIC = 1, 
     DOMAIN_PASSWORD = 2, 
     DOMAIN_CERTIFICATE = 3, 
     DOMAIN_VISIBLE_PASSWORD = 4, 
     GENERIC_CERTIFICATE = 5, 
     DOMAIN_EXTENDED = 6, 
     MAXIMUM = 7,  // Maximum supported cred type 
     MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes 
    } 
    public enum CRED_PERSIST : uint 
    { 
     SESSION = 1, 
     LOCAL_MACHINE = 2, 
     ENTERPRISE = 3, 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct CREDENTIAL_ATTRIBUTE 
    { 
     string Keyword; 
     uint Flags; 
     uint ValueSize; 
     IntPtr Value; 
    } 

    //This type is deliberately not designed to be marshalled. 
    public class Credential 
    { 
     public UInt32 Flags; 
     public CRED_TYPE Type; 
     public string TargetName; 
     public string Comment; 
     public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten; 
     public byte[] CredentialBlob; 
     public CRED_PERSIST Persist; 
     public CREDENTIAL_ATTRIBUTE[] Attributes; 
     public string TargetAlias; 
     public string UserName; 
    } 
} 
+0

看看這裏.... http://stackoverflow.com/questions/2337672/credwrite-returns-win32-error-code-2-error-invalid-function-incorrect-function/2337753#2337753 – t0mm13b 2010-03-08 01:59:56

+1

只是重新讀取代碼,它看起來像Credential類沒有被編組(按照評論)....呃! :) – mlsteeves 2010-03-08 02:03:52

+4

http://blogs.msdn.com/peerchan/pages/487834.aspx - 有一個完整的解決方案,它的工作原理。 – mlsteeves 2010-03-08 02:18:55

回答

3

我現在遇到了同樣的問題。 我發現使用DOMAIN_PASSWORD選項作爲憑證類型發生了此問題。 原來TargetName包含一個不正確的值。

您應該只指定dns或ip地址(通配符可選), 但不包含完整的url或協議。 例如「* .microsoft.com」是正確的,但是「http://www.microsoft.com/」無效

我只是在這裏發佈此以防其他人遇到此問題。花了我一段時間才找到它。

+0

僅供參考:指定域的限制與用於Keychain服務的OSX SecKeychainItemCreateFromContent函數的限制類似 – 2016-03-11 19:11:22

相關問題