How to P/Invoke CryptUIWizExport Function using .N

2019-05-21 12:52发布

问题:

Can anyone translate these two cryptui.dll functions/structures into C#.NET [dllimport] wrappers? I would like to P/Invoke the CryptUIWizExport function to display the Windows Certificate Export Wizard. In particular, I need to pass a .NET X509Certificate as a parameter into the CryptUIWizExport function. You help is much appreciated!!!

CryptUIWizExport function

BOOL WINAPI CryptUIWizExport(
  __in  DWORD dwFlags,
  __in  HWND hwndParent,
  __in  LPCWSTR pwszWizardTitle,
  __in  PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
  __in  void *pvoid
);

typedef struct _CRYPTUI_WIZ_EXPORT_INFO {
  DWORD      dwSize;
  LPCWSTR    pwszExportFileName;
  DWORD      dwSubjectChoice;
  union {
    PCCERT_CONTEXT pCertContext;
    PCCTL_CONTEXT  pCTLContext;
    PCCRL_CONTEXT   pCRLContext;
    HCERTSTORE     hCertStore;
  } ;
  DWORD      cStores;
  HCERTSTORE *rghStores;
} CRYPTUI_WIZ_EXPORT_INFO, *PCRYPTUI_WIZ_EXPORT_INFO;

回答1:

You can use CryptUIWizExport function in different situations. Here is an example to export a certificate. This example can be easy modified for using it to the situations in which you need it.

using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;

namespace CryptUIWizExportTest {
    using HCERTSTORE = IntPtr;
    using HWND = IntPtr;

    static internal class NativeMethods {
        internal enum CryptuiExportChoice : uint {
            CRYPTUI_WIZ_EXPORT_CERT_CONTEXT = 1,
            CRYPTUI_WIZ_EXPORT_CTL_CONTEXT = 2,
            CRYPTUI_WIZ_EXPORT_CRL_CONTEXT = 3,
            CRYPTUI_WIZ_EXPORT_CERT_STORE = 4,
            CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY = 5,
            CRYPTUI_WIZ_EXPORT_FORMAT_CRL = 6,
            CRYPTUI_WIZ_EXPORT_FORMAT_CTL = 7
        }

        [StructLayout (LayoutKind.Sequential)]
        internal struct CRYPTUI_WIZ_EXPORT_INFO {
            internal uint dwSize;
            //Required: should be set to sizeof(CRYPTUI_WIZ_EXPORT_INFO)

            internal string pwszExportFileName;
            //Required if the CRYPTUI_WIZ_NO_UI flag is set, Optional otherwise.
            //The fully qualified file name to export to, if this is
            //non-NULL and the CRYPTUI_WIZ_NO_UI flag is NOT set, then it is
            //displayed to the user as the default file name

            internal CryptuiExportChoice dwSubjectChoice;
            //Required: indicate the type of the subject:
            //          If can one of the following:
            //          CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
            //          CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
            //          CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
            //          CRYPTUI_WIZ_EXPORT_CERT_STORE
            //          CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY

            internal IntPtr pCertContext;
            //union
            //{
            //    PCCERT_CONTEXT      pCertContext;
            //    PCCTL_CONTEXT       pCTLContext;
            //    PCCRL_CONTEXT       pCRLContext;
            //    HCERTSTORE          hCertStore;
            //};

            internal uint cStores;
            // Optional: count of extra stores to search for the certs in the
            //           trust chain if the chain is being exported with a cert.
            //           this is ignored if dwSubjectChoice is anything other
            //           than CRYPTUI_WIZ_EXPORT_CERT_CONTEXT

            internal HCERTSTORE rghStores;
            // HCERTSTORE* !!!!
            // Optional: array of extra stores to search for the certs in the
            //           trust chain if the chain is being exported with a cert.
            //           this is ignored if dwSubjectChoice is anything other
            //           than CRYPTUI_WIZ_EXPORT_CERT_CONTEXT

        };

        [DllImport ("Cryptui.dll", CharSet = CharSet.Unicode,
                    ExactSpelling = true, SetLastError = true)]
        [return: MarshalAs (UnmanagedType.Bool)]
        internal static extern bool CryptUIWizExport (uint dwFlags,
            HWND hwndParent, string pwszWizardTitle,
            IntPtr pExportInfo, IntPtr pvoid);
    }
    class Program {
        static void Main (string[] args) {
            X509Certificate2 x509 = new X509Certificate2(@"c:\Test.pfx", "test");
            if (x509 == null)
                return;

            NativeMethods.CRYPTUI_WIZ_EXPORT_INFO exportInfo =
                new NativeMethods.CRYPTUI_WIZ_EXPORT_INFO ();
            exportInfo.dwSize = (uint)Marshal.SizeOf (
                typeof (NativeMethods.CRYPTUI_WIZ_EXPORT_INFO));
            //exportInfo.pwszExportFileName = @"C:\TEMP\tt.cer";
            exportInfo.dwSubjectChoice =
                NativeMethods.CryptuiExportChoice.CRYPTUI_WIZ_EXPORT_CERT_CONTEXT;
            exportInfo.pCertContext = x509.Handle;
            exportInfo.cStores = 0;

            IntPtr pExportInfo = Marshal.AllocHGlobal ((int)exportInfo.dwSize);
            Marshal.StructureToPtr (exportInfo, pExportInfo, false);
            NativeMethods.CryptUIWizExport (0, IntPtr.Zero,
                "Export of Certificate", pExportInfo, IntPtr.Zero);
        }
    }
}


回答2:

Try using the PInvoke Interop Assistant. You can point it to a header file and it will generate p/invoke signatures for you.