2010-05-17 4 views
0

J'essaye de signer numériquement des fichiers en utilisant la fonction CryptUIWizDigitalSign à partir d'une application .NET 2.0 compilée à AnyCPU. L'appel fonctionne correctement lors de l'exécution sur x86 mais échoue sur x64, il fonctionne également sur un système d'exploitation x64 lorsqu'il est compilé en x86. Une idée sur comment mieux marshall ou appel de x64?Appel de CryptUIWizDigitalSign à partir de .NET sur x64

L'erreur Win32exception renvoyée est "Erreur rencontrée lors de la signature numérique du fichier ..." avec un code d'erreur natif de -2146762749.

La partie pertinente du code sont les suivants:

[StructLayout(LayoutKind.Sequential)] 
public struct CRYPTUI_WIZ_DIGITAL_SIGN_INFO { 
public Int32 dwSize; 
public Int32 dwSubjectChoice; 
[MarshalAs(UnmanagedType.LPWStr)] 
public string pwszFileName; 
public Int32 dwSigningCertChoice; 
public IntPtr pSigningCertContext; 
[MarshalAs(UnmanagedType.LPWStr)] 
public string pwszTimestampURL; 
public Int32 dwAdditionalCertChoice; 
public IntPtr pSignExtInfo; 
} 

[DllImport("Cryptui.dll", CharSet=CharSet.Unicode, SetLastError=true)] 
public static extern bool CryptUIWizDigitalSign(int dwFlags, IntPtr hwndParent, string pwszWizardTitle, ref CRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo, ref IntPtr ppSignContext); 

CRYPTUI_WIZ_DIGITAL_SIGN_INFO digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO(); 
digitalSignInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO(); 
digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo); 
digitalSignInfo.dwSubjectChoice = 1; 
digitalSignInfo.dwSigningCertChoice = 1; 
digitalSignInfo.pSigningCertContext = pSigningCertContext; 
digitalSignInfo.pwszTimestampURL = timestampUrl; 
digitalSignInfo.dwAdditionalCertChoice = 0; 
digitalSignInfo.pSignExtInfo = IntPtr.Zero; 
digitalSignInfo.pwszFileName = filepath; 
CryptUIWizDigitalSign(1, IntPtr.Zero, null, ref digitalSignInfo, ref pSignContext)); 

Et voici comment le SigningCertContext est récupéré (moins diverses manipulations d'erreur)

public IntPtr GetCertContext(String pfxfilename, String pswd) 
IntPtr hMemStore = IntPtr.Zero; 
IntPtr hCertCntxt = IntPtr.Zero; 
IntPtr pProvInfo = IntPtr.Zero; 
uint provinfosize = 0; 
try {     
    byte[] pfxdata = PfxUtility.GetFileBytes(pfxfilename); 
    CRYPT_DATA_BLOB ppfx = new CRYPT_DATA_BLOB(); 
    ppfx.cbData = pfxdata.Length; 
    ppfx.pbData = Marshal.AllocHGlobal(pfxdata.Length); 
    Marshal.Copy(pfxdata, 0, ppfx.pbData, pfxdata.Length); 
    hMemStore = Win32.PFXImportCertStore(ref ppfx, pswd, CRYPT_USER_KEYSET); 
    pswd = null; 
    if (hMemStore != IntPtr.Zero) { 
    Marshal.FreeHGlobal(ppfx.pbData); 
    while ((hCertCntxt = Win32.CertEnumCertificatesInStore(hMemStore, hCertCntxt)) != IntPtr.Zero) { 
    if (Win32.CertGetCertificateContextProperty(hCertCntxt, CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref provinfosize)) 
    pProvInfo = Marshal.AllocHGlobal((int)provinfosize); 
    else 
    continue; 
    if (Win32.CertGetCertificateContextProperty(hCertCntxt, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, ref provinfosize)) 
    break; 
    }    
    } 
finally { 
if (pProvInfo != IntPtr.Zero) 
    Marshal.FreeHGlobal(pProvInfo); 
if (hMemStore != IntPtr.Zero) 
    Win32.CertCloseStore(hMemStore, 0); 
} 
return hCertCntxt; 
} 
+0

Je ne vois aucune erreur. Je ne vois pas comment pSigningCertContext a été initialisé. Décrivez "échoue" et la valeur de retour Marshal.GetLastWin32Error. –

Répondre

0

Lorsque les applications sont compilées avec l'objectif de AnyCPU, ils seront chargez 32 bits sur un système d'exploitation 32 bits et 64 bits sur un système d'exploitation 64 bits. Vous ne pouvez pas charger une DLL 32 bits à partir d'un processus 64 bits.

Vous avez dit que cela "fonctionne" lors de la compilation en x86. Pouvez-vous juste faire ça? Cela me conduit à croire que le cryptui.dll dans votre chemin de recherche est une DLL 32 bits.