<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Decrypt my World : CAPICOM</title><link>http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx</link><description>Tags: CAPICOM</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Does SignTool work on Windows 7?</title><link>http://blogs.msdn.com/alejacma/archive/2009/12/14/does-signtool-work-on-windows-7.aspx</link><pubDate>Mon, 14 Dec 2009 08:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9936424</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9936424.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9936424</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The answer to the question of the title is &lt;STRONG&gt;YES, OF COURSE&lt;/STRONG&gt;!&amp;nbsp;Why wouldn't it? Well, the reason of this question is the following: you may already know that &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; has been &lt;STRONG&gt;deprecated&lt;/STRONG&gt; on&lt;STRONG&gt; Windows 7&lt;/STRONG&gt; (&lt;A href="http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx"&gt;CAPICOM support on Windows 7&lt;/A&gt;). It was going to be deprecated when &lt;STRONG&gt;Vista&lt;/STRONG&gt; came out, but it didn't (&lt;A href="http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx"&gt;CAPICOM support on Windows Vista&lt;/A&gt;). And why wasn't it deprecated on Vista? Because a tool like &lt;STRONG&gt;SignTool depended on CAPICOM&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;So if SignTool depends on CAPICOM, will it work on Windows 7? Yes, because &lt;STRONG&gt;Signtool has been updated on Windows 7 &lt;/STRONG&gt;and it does not use CAPICOM anymore.&lt;/P&gt;
&lt;P&gt;Note: remember that Win7 version of SignTool comes with &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&amp;amp;displaylang=en"&gt;Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9936424" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Windows+7/default.aspx">Windows 7</category></item><item><title>x64 version of CAPICOM?</title><link>http://blogs.msdn.com/alejacma/archive/2009/12/14/x64-version-of-capicom.aspx</link><pubDate>Mon, 14 Dec 2009 07:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9936406</guid><dc:creator>alejacma</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9936406.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9936406</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;Now that we are progressively moving to &lt;STRONG&gt;x64&lt;/STRONG&gt; systems, many people ask me if there is an x64 version of &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; available. The answer is &lt;STRONG&gt;no&lt;/STRONG&gt;, there is not. And because CAPICOM is already &lt;STRONG&gt;deprecated&lt;/STRONG&gt; (&lt;A href="http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx"&gt;CAPICOM support on Windows 7&lt;/A&gt;), there won't ever be any. So if you are using a version of x64 Windows older than Windows 7/Server 2008 R2, you will have to use x86 version (which will only work with x86 apps), or move to i.e. .NET and forget about CAPICOM.&lt;/P&gt;
&lt;P&gt;I hope this helps.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9936406" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/x64/default.aspx">x64</category></item><item><title>2.1.0.3, a new CAPICOM version?</title><link>http://blogs.msdn.com/alejacma/archive/2009/12/04/2-1-0-3-a-new-capicom-version.aspx</link><pubDate>Fri, 04 Dec 2009 13:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9932508</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9932508.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9932508</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The other day I got surprised when a customer of mine told me that they had seen a new &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; version being installed by &lt;STRONG&gt;Office 2007 SP2&lt;/STRONG&gt;: &lt;STRONG&gt;2.1.0.3&lt;/STRONG&gt;. I've been dealing with many CAPICOM issues in the past, and I had no news of such a version. Is it a new version? Can it be used? Can it be redistributed?&lt;/P&gt;
&lt;P&gt;To my knowledge, version &lt;STRONG&gt;2.1.0.2&lt;/STRONG&gt; was the&amp;nbsp;lastest version available. Additionally, it was the only supported version on Vista/Server 2008&amp;nbsp;(&lt;A id=ctl00___ctl00___ctl02___Results___postlist___EntryItems_ctl07_PostTitle href="http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx"&gt;CAPICOM support on Windows Vista&lt;/A&gt;, &lt;A id=ctl00___ctl00___ctl02___Results___postlist___EntryItems_ctl06_PostTitle href="http://blogs.msdn.com/alejacma/archive/2008/03/06/capicom-support-on-windows-server-2008.aspx"&gt;CAPICOM support on Windows Server 2008&lt;/A&gt;).&amp;nbsp;Note that this is not the case on Windows&amp;nbsp;7/2008 R2&amp;nbsp;(&lt;A id=ctl00___ctl00___ctl02___Results___postlist___EntryItems_ctl00_PostTitle href="http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx"&gt;CAPICOM support on Windows 7&lt;/A&gt;). &lt;STRONG&gt;CAPICOM has been deprecated&lt;/STRONG&gt;, and you should seriously think about migrating to a .NET solution, for example.&lt;/P&gt;
&lt;P&gt;Anyway, after some research I was told that the code of&amp;nbsp;&lt;STRONG&gt;2.1.0.3 is exactly the same&amp;nbsp;as 2.1.0.2&lt;/STRONG&gt;, and only the version number is different. Office 2007 had to modify the version number of their copy of CAPICOM to work around some issue on their setup logic in SP2.&lt;/P&gt;
&lt;P&gt;So summing up, just forget about that dll that Office uses. Stick to the &lt;STRONG&gt;official version&lt;/STRONG&gt;,&amp;nbsp;2.1.0.2, that is available here: &lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CA930018-4A66-4DA6-A6C5-206DF13AF316&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CA930018-4A66-4DA6-A6C5-206DF13AF316&amp;amp;displaylang=en"&gt;Security Update for CAPICOM (KB931906)&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;I hope this helps.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9932508" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category></item><item><title>CAPICOM support on Windows 7</title><link>http://blogs.msdn.com/alejacma/archive/2009/10/15/capicom-support-on-windows-7.aspx</link><pubDate>Thu, 15 Oct 2009 18:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9907801</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9907801.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9907801</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; has finally been &lt;STRONG&gt;deprecated&lt;/STRONG&gt;, and it won't be supported on &lt;STRONG&gt;Windows 7&lt;/STRONG&gt;. This link is up to date and proposes &lt;STRONG&gt;alternatives&lt;/STRONG&gt; to CAPICOM classes by using &lt;STRONG&gt;.NET&lt;/STRONG&gt; classes and &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt;: &lt;A href="http://msdn.microsoft.com/en-us/library/cc778518(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc778518(VS.85).aspx"&gt;Alternatives to Using CAPICOM&lt;/A&gt;.&lt;BR&gt;&lt;BR&gt;The following article may help if you were using CAPICOM in your web site and you are planning on using .NET now: &lt;A href="http://www.c-sharpcorner.com/UploadFile/dsandor/ActiveXInNet11102005040748AM/ActiveXInNet.aspx" mce_href="http://www.c-sharpcorner.com/UploadFile/dsandor/ActiveXInNet11102005040748AM/ActiveXInNet.aspx"&gt;Writing an ActiveX Control in .NET&lt;/A&gt;.&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9907801" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Windows+7/default.aspx">Windows 7</category></item><item><title>How to sign EXE files with an Authenticode certificate (part 2)</title><link>http://blogs.msdn.com/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx</link><pubDate>Thu, 11 Dec 2008 12:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9196078</guid><dc:creator>alejacma</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9196078.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9196078</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;The other day a customer of mine was having an &lt;STRONG&gt;issue&lt;/STRONG&gt; with &lt;STRONG&gt;SignTool.exe&lt;/STRONG&gt; when &lt;STRONG&gt;signing&lt;/STRONG&gt; an &lt;STRONG&gt;EXE&lt;/STRONG&gt; file. The EXE file was getting &lt;STRONG&gt;corrupted&lt;/STRONG&gt;/unusable after signing it.&lt;/P&gt;
&lt;P&gt;When troubleshooting this issue, I had the chance to play a bit more&amp;nbsp;with SignTool and check what it does behind the scenes. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Note: I already talked a bit about signing EXEs in post &lt;/EM&gt;&lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx"&gt;&lt;EM&gt;How to sign EXE files with an Authenticode certificate (VB.NET)&lt;/EM&gt;&lt;/A&gt;&lt;EM&gt;. This new post will add more details and samples.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SignTool.exe&lt;/STRONG&gt; uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387712(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387712(VS.85).aspx"&gt;CAPICOM.SignedCode&lt;/A&gt; class and its &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387717(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387717(VS.85).aspx"&gt;Sign&lt;/A&gt; method to do the signing.&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;VBScript&lt;/STRONG&gt; shows how we may use &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; to do the signing programmatically:&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;Option Explicit

Dim szCertName, szExeToSign
szCertName = "My cert Subject"
szExeToSign = "MyApplication.exe"

Const CAPICOM_CURRENT_USER_STORE = 2
Const CAPICOM_STORE_OPEN_READ_ONLY = 0
Const CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1
Const CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION = 2

' Get certificate for signing
'
Dim objStore
Set objStore = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.Store&lt;/STRONG&gt;")
objStore.Open CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY
Dim objSigningCert
Set objSigningCert = objStore.&lt;STRONG&gt;Certificates.Find&lt;/STRONG&gt;(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, szCertName).Item(1)

' Create a signer for the code
'
Dim objSigner
Set objSigner = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.Signer&lt;/STRONG&gt;")
objSigner.&lt;STRONG&gt;Certificate&lt;/STRONG&gt; = objSigningCert

' Sign the file
'
Dim objSignedCode
Set objSignedCode = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.SignedCode&lt;/STRONG&gt;")
objSignedCode.&lt;STRONG&gt;FileName&lt;/STRONG&gt; = szExeToSign
objSignedCode.&lt;STRONG&gt;Sign&lt;/STRONG&gt; objSigner
objSignedCode.&lt;STRONG&gt;TimeStamp&lt;/STRONG&gt; "http://timestamp.globalsign.com/scripts/timstamp.dll"

WScript.Echo "Done!"
&lt;/PRE&gt;
&lt;P&gt;Note that&amp;nbsp;this sample also shows how to &lt;STRONG&gt;time stamp a signature&lt;/STRONG&gt; programmatically.&lt;/P&gt;
&lt;P&gt;This sample was also reproducing my customer's issue. So&amp;nbsp;I checked what CAPICOM does behind the scenes to further troubleshoot the issue.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;CAPICOM.SignedCode.Sign&lt;/STRONG&gt; uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa380292(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa380292(VS.85).aspx"&gt;CryptUIWizDigitalSign&lt;/A&gt; API to do the signing. &lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;VB.NET &lt;/STRONG&gt;sample uses &lt;STRONG&gt;CryptUIWizDigitalSign &lt;/STRONG&gt;through &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; to do the signing programmatically:&lt;/P&gt;&lt;PRE&gt;&amp;lt;SAMPLE file="Crypto.vb"&amp;gt;

Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class Crypto

    ' #define CRYPTUI_WIZ_NO_UI     1
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_NO_UI&lt;/STRONG&gt; As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE     0x01
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE&lt;/STRONG&gt; As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_CERT                    0x01
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_CERT&lt;/STRONG&gt; As Int32 = 1

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_INFO {  
    '   DWORD dwSize;  
    '   DWORD dwSubjectChoice;  
    '   union {    
    '       LPCWSTR pwszFileName;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO pSignBlobInfo;  
    '   };  
    '   DWORD dwSigningCertChoice;  
    '   union {    
    '       PCCERT_CONTEXT pSigningCertContext;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO pSigningCertStore;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pSigningCertPvkInfo;  
    '   };  
    '   LPCWSTR pwszTimestampURL;  
    '   DWORD dwAdditionalCertChoice;  
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO pSignExtInfo;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_INFO;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_INFO&lt;/STRONG&gt;
        Public dwSize As Int32
        Public dwSubjectChoice As Int32
        &amp;lt;MarshalAs(UnmanagedType.LPWStr)&amp;gt; Public pwszFileName As String
        Public dwSigningCertChoice As Int32
        Public pSigningCertContext As IntPtr
        Public pwszTimestampURL As String
        Public dwAdditionalCertChoice As Int32
        Public pSignExtInfo As IntPtr
    End Structure

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT {  
    '      DWORD dwSize;  
    '      DWORD cbBlob;  
    '      BYTE* pbBlob;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT&lt;/STRONG&gt;
        Public dwSize As Int32
        Public cbBlob As Int32
        Public pbBlob As IntPtr
    End Structure

    ' BOOL WINAPI CryptUIWizDigitalSign(
    '      DWORD dwFlags,
    '      HWND hwndParent,
    '      LPCWSTR pwszWizardTitle,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT* ppSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Unicode, SetLastError:=True)&amp;gt; _
    Public Shared Function &lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt;( _
        ByVal dwFlags As Int32, _
        ByVal hwndParent As IntPtr, _
        ByVal pwszWizardTitle As String, _
        ByRef pDigitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO, _
        ByRef ppSignContext As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptUIWizFreeDigitalSignContext(
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT pSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function &lt;STRONG&gt;CryptUIWizFreeDigitalSignContext&lt;/STRONG&gt;( _
        ByVal pSignContext As IntPtr _
    ) As Boolean
    End Function

End Class

&amp;lt;/SAMPLE&amp;gt;

&amp;lt;SAMPLE file="Module1.vb"&amp;gt;

Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports SignExe.Crypto
Imports System.Security.Cryptography.X509Certificates
Imports System.IO

Module Module1

    Sub Main()

        ' Parameters
        Dim certPath As String = "MyCert.pfx"
        Dim exePath As String = "MyApplication.exe"
        Dim sigPath As String = "signature.sig"

        ' Variables
        '
        Dim cert As X509Certificate2
        Dim digitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO
        Dim pSignContext As IntPtr
        Dim pSigningCertContext As IntPtr
        Dim signContext As CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
        Dim fileOut As FileStream
        Dim binWriter As BinaryWriter
        Dim blob() As Byte

        Try
            ' Get certificate context
            '
            cert = New &lt;STRONG&gt;X509Certificate2&lt;/STRONG&gt;(certPath, "")
            pSigningCertContext = cert.Handle

            ' Prepare signing info: exe and cert
            '
            digitalSignInfo = New CRYPTUI_WIZ_DIGITAL_SIGN_INFO
            digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo)
            digitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE
            digitalSignInfo.pwszFileName = exePath
            digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT
            digitalSignInfo.pSigningCertContext = pSigningCertContext
            digitalSignInfo.pwszTimestampURL = vbNullString
            digitalSignInfo.dwAdditionalCertChoice = 0
            digitalSignInfo.pSignExtInfo = IntPtr.Zero

            ' Sign exe
            '
            If (Not &lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt;( _
                CRYPTUI_WIZ_NO_UI, _
                IntPtr.Zero, _
                vbNullString, _
                digitalSignInfo, _
                pSignContext _
            )) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign")
            End If

            ' Get the blob with the signature
            '
            signContext = Marshal.PtrToStructure(pSignContext, GetType(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT))
            blob = New Byte(signContext.cbBlob) {}
            Marshal.Copy(signContext.pbBlob, blob, 0, signContext.cbBlob)

            ' Store the signature in a new file
            '
            fileOut = File.Open(sigPath, FileMode.Create)
            binWriter = New BinaryWriter(fileOut)
            binWriter.Write(blob)
            binWriter.Close()
            fileOut.Close()

            ' Free blob
            '
            If (Not &lt;STRONG&gt;CryptUIWizFreeDigitalSignContext&lt;/STRONG&gt;(pSignContext)) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizFreeDigitalSignContext")
            End If

            ' We are done
            Console.WriteLine("Done!!!")

        Catch ex As Win32Exception
            ' Any expected errors?
            '
            Console.WriteLine(ex.Message + " error#" + ex.NativeErrorCode.ToString)
        Catch ex As Exception
            ' Any unexpected errors?
            '
            Console.WriteLine(ex.Message)
        End Try

        ' We are done
        '
        Console.WriteLine("&amp;lt;&amp;lt; Press any key to continue &amp;gt;&amp;gt;")
        Console.ReadKey()

    End Sub

End Module

&amp;lt;/SAMPLE&amp;gt;&lt;/PRE&gt;
&lt;P&gt;This sample was also reproducing the issue. So I checked what CryptUIWizDigitalSign does behind the scenes.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt; API uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387734(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387734(VS.85).aspx"&gt;SignerSignEx&lt;/A&gt; API to do the signing.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following &lt;STRONG&gt;VC++&lt;/STRONG&gt; sample uses &lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt; API to do the signing programmatically:&lt;/P&gt;&lt;PRE&gt;#include "windows.h"
#include "Wincrypt.h"
#include "stdio.h"
#include "conio.h"


// STRUCTS

typedef &lt;STRONG&gt;struct _SIGNER_FILE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszFileName;  
	HANDLE hFile;
} SIGNER_FILE_INFO,  *PSIGNER_FILE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_BLOB_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	GUID *pGuidSubject;  
	DWORD cbBlob;  
	BYTE *pbBlob;  
	LPCWSTR pwszDisplayName;
} SIGNER_BLOB_INFO,  *PSIGNER_BLOB_INFO;

typedef&lt;STRONG&gt; struct _SIGNER_SUBJECT_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD *pdwIndex;  
	DWORD dwSubjectChoice;  
	union {    
		SIGNER_FILE_INFO *pSignerFileInfo;    
		SIGNER_BLOB_INFO *pSignerBlobInfo;  
	} ;
} SIGNER_SUBJECT_INFO,  *PSIGNER_SUBJECT_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CERT_STORE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	PCCERT_CONTEXT pSigningCert;  
	DWORD dwCertPolicy;  
	HCERTSTORE hCertStore;
} SIGNER_CERT_STORE_INFO,  *PSIGNER_CERT_STORE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_SPC_CHAIN_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszSpcFile;  
	DWORD dwCertPolicy;  
	HCERTSTORE hCertStore;
} SIGNER_SPC_CHAIN_INFO,  *PSIGNER_SPC_CHAIN_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CERT&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD dwCertChoice;  
	union {    
		LPCWSTR pwszSpcFile;    
		SIGNER_CERT_STORE_INFO *pCertStoreInfo;    
		SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;  
	} ;  
	HWND hwnd;
} SIGNER_CERT,  *PSIGNER_CERT;

typedef&lt;STRONG&gt; struct _SIGNER_ATTR_AUTHCODE&lt;/STRONG&gt; {  
	DWORD cbSize;  
	BOOL fCommercial;  
	BOOL fIndividual;  
	LPCWSTR pwszName;  
	LPCWSTR pwszInfo;
} SIGNER_ATTR_AUTHCODE,  *PSIGNER_ATTR_AUTHCODE;

typedef &lt;STRONG&gt;struct _SIGNER_SIGNATURE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	ALG_ID algidHash;  
	DWORD dwAttrChoice;  
	union {    
		SIGNER_ATTR_AUTHCODE *pAttrAuthcode;  
	} ;  
	PCRYPT_ATTRIBUTES psAuthenticated;  
	PCRYPT_ATTRIBUTES psUnauthenticated;
} SIGNER_SIGNATURE_INFO,  *PSIGNER_SIGNATURE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_PROVIDER_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszProviderName;  
	DWORD dwProviderType;  
	DWORD dwKeySpec;  
	DWORD dwPvkChoice;  
	union {    
		LPWSTR pwszPvkFileName;    
		LPWSTR pwszKeyContainer;  
	} ;
} SIGNER_PROVIDER_INFO,  *PSIGNER_PROVIDER_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CONTEXT&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD cbBlob;  
	BYTE *pbBlob;
} SIGNER_CONTEXT,  *PSIGNER_CONTEXT;


// EXPORTS 

typedef HRESULT (WINAPI* &lt;STRONG&gt;SignerFreeSignerContextType&lt;/STRONG&gt;)(
  __in  SIGNER_CONTEXT *pSignerContext
);

typedef HRESULT (WINAPI *&lt;STRONG&gt;SignerSignExType&lt;/STRONG&gt;)(
  __in      DWORD dwFlags,
  __in      SIGNER_SUBJECT_INFO *pSubjectInfo,
  __in      SIGNER_CERT *pSignerCert,
  __in      SIGNER_SIGNATURE_INFO *pSignatureInfo,
  __in_opt  SIGNER_PROVIDER_INFO *pProviderInfo,
  __in_opt  LPCWSTR pwszHttpTimeStamp,
  __in_opt  PCRYPT_ATTRIBUTES psRequest,
  __in_opt  LPVOID pSipData,
  __out     SIGNER_CONTEXT **ppSignerContext
);


// MAIN

void main()
{
	// PARAMETERS

	// File to sign
	LPCWSTR pwszFileName = L"C:\\TEST\\MyApplication.exe";

	// Signing Cert Subject
	LPCWSTR pwszCertSubject = L"My cert Subject";

	// VARIABLES
	HRESULT hResult = S_OK;
	BOOL bResult = TRUE;
	HMODULE hMssign32 = NULL;
	SignerSignExType pfSignerSignEx = NULL;
	SignerFreeSignerContextType pfSignerFreeSignerContext = NULL;
	HANDLE hFile = NULL;
	HCERTSTORE hCertStore = NULL; 
	PCCERT_CONTEXT pCertContext = NULL;
	DWORD dwIndex = 0;
	SIGNER_FILE_INFO signerFileInfo;
	SIGNER_SUBJECT_INFO signerSubjectInfo;
	SIGNER_CERT_STORE_INFO signerCertStoreInfo;
	SIGNER_CERT signerCert;
	SIGNER_SIGNATURE_INFO signerSignatureInfo;
	SIGNER_CONTEXT * pSignerContext = NULL;

	// MAIN

	// Attach a debugger now!
	printf("&amp;lt;&amp;lt; Press any key to continue&amp;gt;&amp;gt;\n");
	_getch();

	// Load library containing SignerSignEx and SignerFreeSignerContext
	printf("LoadLibrary...");
	hMssign32 = &lt;STRONG&gt;LoadLibrary&lt;/STRONG&gt;(L"&lt;STRONG&gt;Mssign32.dll&lt;/STRONG&gt;");
	if (!hMssign32)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Get SignerSignEx function
	printf("GetProcAddress(SignerSignEx)...");
	pfSignerSignEx = (SignerSignExType) &lt;STRONG&gt;GetProcAddress&lt;/STRONG&gt;(hMssign32, "&lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt;");
	if (!pfSignerSignEx)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Get SignerFreeSignerContext function
	printf("GetProcAddress(SignerFreeSignerContext)...");
	pfSignerFreeSignerContext = (SignerFreeSignerContextType) &lt;STRONG&gt;GetProcAddress&lt;/STRONG&gt;(hMssign32, "&lt;STRONG&gt;SignerFreeSignerContext&lt;/STRONG&gt;");
	if (!pfSignerFreeSignerContext)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Open file to sign
	printf("CreateFile...");
	hFile = &lt;STRONG&gt;CreateFile&lt;/STRONG&gt;(
		pwszFileName,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
	if (!hFile)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Open MY cert store
	printf("CertOpenStore...");
	hCertStore = &lt;STRONG&gt;CertOpenStore&lt;/STRONG&gt;(
		CERT_STORE_PROV_SYSTEM, 
		0,
		NULL,
		CERT_SYSTEM_STORE_CURRENT_USER,
		L"MY"
	);                 
	if (!hCertStore)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Find signing cert in MY cert store
	printf("CertFindCertificateInStore...");
	pCertContext = &lt;STRONG&gt;CertFindCertificateInStore&lt;/STRONG&gt;(
		hCertStore,
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		0,
		CERT_FIND_SUBJECT_STR,
		(void *)pwszCertSubject,
		NULL
	);
	if (!pCertContext)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Prepare SIGNER_FILE_INFO struct
	signerFileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
	signerFileInfo.pwszFileName = pwszFileName;
	signerFileInfo.hFile = hFile;

	// Prepare SIGNER_SUBJECT_INFO struct
	signerSubjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
	dwIndex = 0;
	signerSubjectInfo.pdwIndex = &amp;amp;dwIndex;
	signerSubjectInfo.dwSubjectChoice = 1; // SIGNER_SUBJECT_FILE
	signerSubjectInfo.pSignerFileInfo = &amp;amp;signerFileInfo;

	// Prepare SIGNER_CERT_STORE_INFO struct
	signerCertStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
	signerCertStoreInfo.pSigningCert = pCertContext;
	signerCertStoreInfo.dwCertPolicy = 2; // SIGNER_CERT_POLICY_CHAIN
	signerCertStoreInfo.hCertStore = NULL;

	// Prepare SIGNER_CERT struct
	signerCert.cbSize = sizeof(SIGNER_CERT);
	signerCert.dwCertChoice = 2; // SIGNER_CERT_STORE
	signerCert.pCertStoreInfo = &amp;amp;signerCertStoreInfo;
	signerCert.hwnd = NULL;

	// Prepare SIGNER_SIGNATURE_INFO struct
	signerSignatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
	signerSignatureInfo.algidHash = CALG_SHA1;
	signerSignatureInfo.dwAttrChoice = 0; // SIGNER_NO_ATTR
	signerSignatureInfo.pAttrAuthcode = NULL;
	signerSignatureInfo.psAuthenticated = NULL;
	signerSignatureInfo.psUnauthenticated = NULL;

	// Sign file with cert
	printf("SignerSignEx...");
	hResult = pf&lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt;(
		0,
		&amp;amp;signerSubjectInfo,
		&amp;amp;signerCert,
		&amp;amp;signerSignatureInfo,
		NULL,
		NULL,
		NULL,
		NULL,
		&amp;amp;pSignerContext
	);
	if (S_OK != hResult)
	{
		printf("Error #%d\n", hResult); goto cleanup;
	}
	printf("Done!\n");

	printf("\nSUCCESS!!!\n");

	// Clean up
cleanup:

	if (pSignerContext)
	{
		hResult = pf&lt;STRONG&gt;SignerFreeSignerContext&lt;/STRONG&gt;(pSignerContext);
	}

	if (pCertContext)
	{
		bResult = &lt;STRONG&gt;CertFreeCertificateContext&lt;/STRONG&gt;(pCertContext);
	}

	if (hCertStore)
	{
		bResult = &lt;STRONG&gt;CertCloseStore&lt;/STRONG&gt;(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
	}

	if (hFile)
	{
		bResult = &lt;STRONG&gt;CloseHandle&lt;/STRONG&gt;(hFile);
	}

	if (hMssign32)
	{
		bResult = &lt;STRONG&gt;FreeLibrary&lt;/STRONG&gt;(hMssign32);
	}

	// Exit
	printf("&amp;lt;&amp;lt; Press any key to exit &amp;gt;&amp;gt;\n");
	_getch();
	return;
}
&lt;/PRE&gt;
&lt;P&gt;This sample was also reproducing the issue.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Finally we saw that the &lt;STRONG&gt;issue&lt;/STRONG&gt; was not in SignTool.exe / CAPICOM.SignCode.Sign / CryptUIWizDigitalSign / SignerSignEx, but in the &lt;STRONG&gt;EXE itself&lt;/STRONG&gt;!&lt;/P&gt;
&lt;P&gt;I run Visual Studio's &lt;A class="" href="http://support.microsoft.com/kb/177429/en-us" mce_href="http://support.microsoft.com/kb/177429/en-us"&gt;Dumpbin.exe&lt;/A&gt; with its &lt;STRONG&gt;"/HEADER"&lt;/STRONG&gt; parameter to list the problematic EXE's &lt;STRONG&gt;PE&lt;/STRONG&gt; &lt;STRONG&gt;header&lt;/STRONG&gt; information before and after signing it (the &lt;A class="" href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx" mce_href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx"&gt;Microsoft Portable Executable and Common Object File Format Specification &lt;/A&gt;gives detailed information about PE header information).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Before signing&lt;/STRONG&gt;, I could see the following &lt;STRONG&gt;Optional Header Value&lt;/STRONG&gt;:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;1400&lt;/STRONG&gt; [ &lt;STRONG&gt;C40&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;BR&gt;&lt;/EM&gt;&lt;BR&gt;&lt;STRONG&gt;After signing&lt;/STRONG&gt;, I could see the following value:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;1400&lt;/STRONG&gt; [ &lt;STRONG&gt;1650&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;BR&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Certificates Directory &lt;/STRONG&gt;points to the &lt;STRONG&gt;location of the code signing signature in the binary&lt;/STRONG&gt;. So an &lt;STRONG&gt;EXE which has not been signed&lt;/STRONG&gt; should contain the following values:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;0&lt;/STRONG&gt; [ &lt;STRONG&gt;0&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;/EM&gt;&lt;BR&gt;&lt;BR&gt;Which was not our case. So SignerSignEx was not corrupting the EXE when signing it. It was already corrupted before that, even if it was successfully running before signing!&lt;/P&gt;
&lt;P&gt;Just for testing, I opened the problematic EXE with a &lt;STRONG&gt;binary editor&lt;/STRONG&gt; before signing it. I looked for "00 14 00 00 04 0c 00 00" bytes (correspondent to "1400 [ C40] RVA [size] of Certificates Directory" values), changed them to "00 00 00 00 00 00 00 00" and signed the EXE. It worked! Now the EXE is not corrupted and I can see the Digital Signature in Explorer, the certificate I used to sign, launch the EXE and run it as expected.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Manually modifying the PE header is not supported by Microsoft.&lt;/STRONG&gt; If you face a similar issue, you should work with the team that developed the EXE and focus on why the EXE got generated with an invalid PE header in the first place. &lt;/P&gt;
&lt;P&gt;I looked on the Internet and found that there are some &lt;STRONG&gt;third-party tools&lt;/STRONG&gt; which may help us to &lt;STRONG&gt;see&lt;/STRONG&gt; &lt;STRONG&gt;and modify the PE header&lt;/STRONG&gt; if needed for testing purposes, for example &lt;A class="" href="http://www.pazera-software.com/products/peinfo/" mce_href="http://www.pazera-software.com/products/peinfo/"&gt;PEInfo 0.9 BETA&lt;/A&gt; which I haven't tried so I can't neither recommend nor discourage its use.&lt;/P&gt;
&lt;P&gt;I&amp;nbsp;hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;A href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9196078" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category></item><item><title>How to modify an Interop assembly to change the return type of a method (VB.NET)</title><link>http://blogs.msdn.com/alejacma/archive/2008/08/04/How-to-modify-an-Interop-assembly-to-change-the-return-type-of-a-method-_2800_VB.NET_2900_.aspx</link><pubDate>Mon, 04 Aug 2008 09:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8828576</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8828576.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8828576</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P mce_keep="true"&gt;In some situations we may need to &lt;STRONG&gt;reference&lt;/STRONG&gt; a &lt;STRONG&gt;COM dll&lt;/STRONG&gt; in our &lt;STRONG&gt;Visual Studio&lt;/STRONG&gt; project in order to use a specific &lt;STRONG&gt;COM object&lt;/STRONG&gt; within our &lt;STRONG&gt;.NET&lt;/STRONG&gt; application, and thanks to &lt;STRONG&gt;COM Interop&lt;/STRONG&gt; we can do it. When we add a reference to a COM dll in our project, a &lt;STRONG&gt;COM Interop assembly&lt;/STRONG&gt; gets generated so we can use COM objects in the dll &lt;EM&gt;almost&lt;/EM&gt; like any other .NET object. And I say almost because i.e. .NET needs to &lt;STRONG&gt;translate COM types&lt;/STRONG&gt; to .NET types and it doesn't always do the conversion the way we like or need. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's see this with the following real &lt;STRONG&gt;example&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P mce_keep="true"&gt;We are writing an &lt;STRONG&gt;Exit Module&lt;/STRONG&gt; for our &lt;STRONG&gt;Certification Authority&lt;/STRONG&gt;. We are trying to obtain the &lt;STRONG&gt;raw binary data&lt;/STRONG&gt; for a certificate issued by our CA. We are calling &lt;STRONG&gt;CCertServerExit.GetCertificateProperty("RawCertificate", PROPTYPE_BINARY)&lt;/STRONG&gt; (&lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa385074(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa385074(VS.85).aspx"&gt;ICertServerExit::GetCertificateProperty Method&lt;/A&gt;) to achieve that. But GetCertificateProperty is returning a String and not an array of bytes, because .NET &lt;STRONG&gt;interop layer&lt;/STRONG&gt; is converting a VARIANT of type &lt;STRONG&gt;BSTR&lt;/STRONG&gt; (vt = VT_BSTR) to a &lt;STRONG&gt;.NET&amp;nbsp;String&lt;/STRONG&gt;. Because of this return type, .NET is &lt;STRONG&gt;trimming the last byte&lt;/STRONG&gt; of the binary certificate when the number of bytes is odd. .NET strings &lt;STRONG&gt;cannot represent&lt;/STRONG&gt; BSTRs that contain an &lt;STRONG&gt;odd number of bytes&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Fortunately we can &lt;STRONG&gt;modify the Interop assembly&lt;/STRONG&gt; and choose a different return type for that method. This modification will allow us to get all the bytes in the certificate. These are the &lt;STRONG&gt;steps&lt;/STRONG&gt; to do this:&lt;/P&gt;
&lt;P mce_keep="true"&gt;1) &lt;STRONG&gt;Extract IL&lt;/STRONG&gt; from &lt;STRONG&gt;Interop.CertClientLib.dll&lt;/STRONG&gt; interop assembly generated by VS IDE when we added &lt;STRONG&gt;CertCli COM reference&lt;/STRONG&gt; to our VS project:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;EM&gt;ildasm.exe Interop.CertClientLib.dll /out:temp.il&lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&lt;BR&gt;2) Delete Interop.CertClientLib.dll file. &lt;/P&gt;
&lt;P mce_keep="true"&gt;3) Delete CertCli COM reference from our project.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;4) &lt;STRONG&gt;Modify temp.il&lt;/STRONG&gt; and change the declaration of &lt;STRONG&gt;GetCertificateProperty&lt;/STRONG&gt; in base and derived classes to take an IntPtr for the last output parameter instead of a VARIANT *:&lt;/P&gt;&lt;PRE&gt;instance void 
GetCertificateProperty([in] string  marshal( bstr) strPropertyName,
                       [in] int32 PropertyType,
                       [out] native int pvarPropertyValue) runtime managed internalcall
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;5) &lt;STRONG&gt;Generate&lt;/STRONG&gt; a new &lt;STRONG&gt;Interop.CertClientLib.dll&lt;/STRONG&gt; which includes these modifications:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;EM&gt;ilasm.exe /DLL temp.il /res:temp.res /out=Interop.CertClientLib.dll&lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&lt;BR&gt;6) Modify our project's references to use this new DLL.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;7) Change our &lt;STRONG&gt;.NET code&lt;/STRONG&gt; to use the IntPtr calling convention. Manage Variant objects from IntPtr and free the memory after its use. &lt;STRONG&gt;Sample&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;&amp;lt;DllImport("Oleaut32.dll", PreserveSig:=False)&amp;gt; _
Private Shared Sub VariantClear(ByVal var As IntPtr)
End Sub

'Exit Module Notify callback
Public Sub Notify(ByVal ExitEvent As Integer, ByVal Context As Integer) Implements CERTEXITLib.ICertExit.Notify

    Trace.WriteLine("&amp;gt;&amp;gt; Notify")

    Dim oCSE As New CERTCLIENTLib.CCertServerExit
    oCSE.SetContext(Context)

    Trace.WriteLine(String.Format("ExitEvent = {0}", ExitEvent))
    If ExitEvent = 1 Then 'Issue

        ' Allocate memory to hold VARIANT
        '
        Dim variantObjectPtr As IntPtr
        variantObjectPtr = Marshal.AllocHGlobal(2048)

        ' Get VARIANT containing certificate bytes
        '
        oCSE.GetCertificateProperty("RawCertificate", DataTypeEnum.Binary, variantObjectPtr)

        ' Read ANSI BSTR information from the VARIANT as we know RawCertificate property 
        ' is ANSI BSTR. Please note that the below code is written based on how the 
        ' VARIANT structure looks like in C/C++
        '
        Dim bstrPtr As IntPtr
        bstrPtr = Marshal.ReadIntPtr(variantObjectPtr, 8)

        Dim bstrLen As Integer
        bstrLen = Marshal.ReadInt32(bstrPtr, -4)

        Dim certBytes(bstrLen - 1) As Byte
        Marshal.Copy(bstrPtr, certBytes, 0, bstrLen)

        Trace.WriteLine(String.Format("Certificate length = {0}", certBytes.Length))

        ' Clear the VARIANT which will free the memory allocated for the VARIANT members
        '
        VariantClear(variantObjectPtr)

        ' Get certificate
        '
        Dim x509 As New X509Certificate(certBytes)

        ' Store the certificate in the certificate store
        '
        Dim store As New StoreClass
        Dim cert As New CertificateClass
        Dim data As String = Convert.ToBase64String(x509.GetRawCertData)

        cert.Import(data)
        store.Open(CAPICOM_STORE_LOCATION.CAPICOM_LOCAL_MACHINE_STORE, _
                    "My", _
                    CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_WRITE)
        store.Add(cert)

        ' Get VARIANT containing Serial Number
        '
        oCSE.GetCertificateProperty("SerialNumber", DataTypeEnum.String, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        Dim variantObject As Object
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Serial Number
        '
        Dim serialNo As String = variantObject

        Trace.WriteLine(String.Format("Serial Number = {0}", serialNo))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Distinguished Name
        '
        oCSE.GetCertificateProperty("DistinguishedName", DataTypeEnum.String, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Serial Number
        '
        Dim distinguishedName As String = variantObject

        Trace.WriteLine(String.Format("DistinguishedName = {0}", distinguishedName))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Not Before date
        '
        oCSE.GetCertificateProperty("NotBefore", DataTypeEnum.Date, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Not Before date
        '
        Dim validFrom As Date = variantObject

        Trace.WriteLine(String.Format("Not Before = {0}", validFrom.ToString))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Not After date
        '
        oCSE.GetCertificateProperty("NotAfter", DataTypeEnum.Date, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Not After date
        '
        Dim validTo As Date = variantObject

        Trace.WriteLine(String.Format("Not After = {0}", validTo.ToString))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Free the memory block allocated to hold VARIANT 
        '
        Marshal.FreeHGlobal(variantObjectPtr)

    End If

    Trace.WriteLine("&amp;lt;&amp;lt; Notify")

End Sub

&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Note: Becareful when translating the sample to &lt;STRONG&gt;C#&lt;/STRONG&gt;: "&lt;EM&gt;Dim certBytes(bstrLen - 1) As Byte&lt;/EM&gt;" will translate to "&lt;EM&gt;byte[] rawCert = new byte[bstrLen];&lt;/EM&gt;".&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;BR&gt;I've also seen this kind of issues when referencing &lt;STRONG&gt;CAPICOM.dll&lt;/STRONG&gt; (&lt;STRONG&gt;Interop.CAPICOM.dll&lt;/STRONG&gt; &lt;STRONG&gt;interop assembly&lt;/STRONG&gt;). These errors may appear when we are i.e. decrypting a string:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;&lt;STRONG&gt;System.Runtime.InteropServices.COMException: ASN1 unexpected end of data. &lt;BR&gt;System.Runtime.InteropServices.COMException: ASN1 bad tag value met.&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;For instance, &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa388181.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa388181.aspx"&gt;CAPICOM.Utilities.ByteArrayToBinaryString&lt;/A&gt; returns a BSTR that represents the binary data being passed as an input parameter. The interop layer assigns the BSTR to a .NET string which removes the last byte and makes the data even. By using an IntPtr as return type we can access the complete binary data as we've already seen. In this case we'll replace "&lt;EM&gt;string marhal(bstr)&lt;/EM&gt;" to "&lt;EM&gt;native int&lt;/EM&gt;" just before each ByteArrayToBinaryString occurrence in the IL file.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Credits: Sample code has been provided by my colleague Prabagar Ramadasse. Thank you Prabagar!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8828576" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Interop/default.aspx">Interop</category></item><item><title>How to read certificate extensions with CAPICOM (C#)</title><link>http://blogs.msdn.com/alejacma/archive/2008/05/19/how-to-read-certificate-extensions-with-capicom-c.aspx</link><pubDate>Mon, 19 May 2008 18:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8519150</guid><dc:creator>alejacma</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8519150.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8519150</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;I recently had a customer who needed to retrieve&amp;nbsp;&lt;STRONG&gt;extensions&lt;/STRONG&gt; from &lt;STRONG&gt;certificates&lt;/STRONG&gt; the easy way in &lt;STRONG&gt;.NET 1.1&lt;/STRONG&gt;, and they wanted to use &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; for that. In &lt;STRONG&gt;.NET 2.0&lt;/STRONG&gt; and later we may use &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(VS.80).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(VS.80).aspx"&gt;X509Certificate2&lt;/A&gt;&amp;nbsp;to achieve the same results (I strongly recommend this approach), but in &lt;STRONG&gt;.NET 1.1 &lt;/STRONG&gt;we only have &lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate(VS.80).aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate(VS.80).aspx"&gt;X509Certificate&lt;/A&gt; class which is much more limited. &lt;/P&gt;
&lt;P&gt;Note that the same ideas shown in the same below may be taken into account when using CAPICOM from i.e. &lt;STRONG&gt;VBScript&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;The following sample shows how to use CAPICOM from a &lt;STRONG&gt;C# &lt;/STRONG&gt;app to read a couple of extensions from&amp;nbsp;a test cert&amp;nbsp;(remember to add CAPICOM as a reference to the project first):&lt;/P&gt;&lt;PRE&gt;using CAPICOM;

...

// Load the cert
Certificate CAPICOMCertClass = new CertificateClass();
CAPICOMCertClass.Load("C:\\test.cer", null, CAPICOM_KEY_STORAGE_FLAG.CAPICOM_KEY_STORAGE_DEFAULT, CAPICOM_KEY_LOCATION.CAPICOM_CURRENT_USER_KEY);

// Find the extensions we are interested in
foreach (Extension CertExtension in CAPICOMCertClass.Extensions())
{

  // Does the extension have a Friendly Name? Yes? Use it!
  if (CertExtension.OID.FriendlyName == "Subject Alternative Name")
  {
    String stringSubjectAltName = CertExtension.EncodedData.Format(true);
    MessageBox.Show(stringSubjectAltName);
  }

  // The extension has no Friendly Name, but we can use its OID instead
  if (CertExtension.OID.Value.ToString() == "1.3.6.1.4.1.5734.1.33")
  {
    // For demostration purposes of Utilities class, let's assume the value of the OID is an hex string which represents the chars of a string but we need the string itself
    
    // This property is in Hexadecimal
    String stringOIDHex = CertExtension.EncodedData.Format(true).Replace(" ", "");

    // We convert it to binary
    Utilities utils = new UtilitiesClass();
    String stringOIDBinary = utils.HexToBinary(stringOIDHex);
    byte[] OIDBinary = (byte[])utils.BinaryStringToByteArray(stringOIDBinary);

    // We convert it to string
    String stringOID = System.Text.Encoding.ASCII.GetString(OIDBinary);
    MessageBox.Show(stringOID);
  }
}
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;References to the classes I've used: &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa376092(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa376092(VS.85).aspx"&gt;Certificate&lt;/A&gt;,&amp;nbsp;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa382409(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa382409(VS.85).aspx"&gt;Extensions&lt;/A&gt;, &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa382408(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa382408(VS.85).aspx"&gt;Extension&lt;/A&gt;, &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387022(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387022(VS.85).aspx"&gt;OID&lt;/A&gt;,&amp;nbsp;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx"&gt;Utilities&lt;/A&gt;.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8519150" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category></item><item><title>Certificate has private key but we get "the keyset does not exist" error</title><link>http://blogs.msdn.com/alejacma/archive/2008/04/18/certificate-has-private-key-but-we-can-t-find-it.aspx</link><pubDate>Fri, 18 Apr 2008 11:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8372147</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8372147.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8372147</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;The other day we were using &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; in a&amp;nbsp;&lt;STRONG&gt;client script&lt;/STRONG&gt; run in &lt;STRONG&gt;Internet Explorer&lt;/STRONG&gt;. We were trying to &lt;STRONG&gt;sign&lt;/STRONG&gt; some string with the &lt;STRONG&gt;private key&lt;/STRONG&gt; of a &lt;STRONG&gt;certificate&lt;/STRONG&gt; we previously installed in the client machine, but we kept getting the error "&lt;STRONG&gt;the keyset does not exist&lt;/STRONG&gt;", like if the private key didn't exist. But the certificate had been installed from a &lt;STRONG&gt;PFX&lt;/STRONG&gt; file, it appeared in the &lt;STRONG&gt;Personal&lt;/STRONG&gt; &lt;STRONG&gt;store &lt;/STRONG&gt;and we could see the message "&lt;STRONG&gt;You have a private key that corresponds to this certificate&lt;/STRONG&gt;" when double-clicking on the cert. What was going on?&lt;/P&gt;
&lt;P&gt;The issue was happening in &lt;STRONG&gt;Windows XP SP2&lt;/STRONG&gt;. As we saw in &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2007/12/13/key-containers-basics.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/12/13/key-containers-basics.aspx"&gt;Key Containers: Basics&lt;/A&gt;, the &lt;STRONG&gt;keysets&lt;/STRONG&gt; (key containers) for the user should be in her profile here &lt;STRONG&gt;C:\Documents and Settings\&amp;lt;user_name&amp;gt;\Application Data\Microsoft\Crypto\RSA\&amp;lt;user_SID&amp;gt;&lt;/STRONG&gt;. But we realized this folder was empty, even after re-installing the cert. Weird. When&amp;nbsp;we install a new cert (and no smart cards are involved), a file containing the keys associated with it gets created in there...&lt;/P&gt;
&lt;P&gt;Additionally, if we imported the PFX into a &lt;STRONG&gt;smart card&lt;/STRONG&gt;, everything worked just fine.&lt;/P&gt;
&lt;P&gt;Well, we finally realized what was happening: &lt;/P&gt;
&lt;P&gt;When importing a PFX with &lt;STRONG&gt;Windows Certificate Import Wizard&lt;/STRONG&gt; we can click "&lt;STRONG&gt;Browse&lt;/STRONG&gt;" to select a cert store and "&lt;STRONG&gt;Place all certificates in the following store&lt;/STRONG&gt;". We can then check "&lt;STRONG&gt;Show physical stores&lt;/STRONG&gt;". In our particular scenario, we had two &lt;STRONG&gt;physical stores&lt;/STRONG&gt; under "&lt;STRONG&gt;Personal&lt;/STRONG&gt;" store:&amp;nbsp;"3rd Party Smart card SW" first and "&lt;STRONG&gt;Registry&lt;/STRONG&gt;" second. "3rd Party Smart card SW" was an store for smart cards related to some third-party smart card CSP. &lt;/P&gt;
&lt;P&gt;It turned out that if we chose "&lt;STRONG&gt;Automatically select the certificate store based on the type of certificate&lt;/STRONG&gt;" in the wizard instead of browsing for a store, the cert was going to "3rd Party Smart card SW" physical store&amp;nbsp;automatically and the key file wasn't being created in the user's profile. For this reason CAPICOM was failing, as it couldn't find that file.&lt;/P&gt;
&lt;P&gt;So we solved the issue by re-installing the cert&amp;nbsp;and manually browsing for "Registry" physical store in "Personal" store. This way the keyset file got created in Microsoft\Crypto\RSA\&amp;lt;userSID&amp;gt; folder, CAPICOM was able to get the private key and everything worked just fine.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8372147" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category></item><item><title>CAPICOM Security Alerts are not localized</title><link>http://blogs.msdn.com/alejacma/archive/2008/03/24/capicom-security-alerts-are-not-localized.aspx</link><pubDate>Mon, 24 Mar 2008 14:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8333427</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8333427.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8333427</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P mce_keep="true"&gt;When we use &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt;, we may get some &lt;STRONG&gt;messages&lt;/STRONG&gt; like the following:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Security Alert: This Web site needs to decrypt data using your private key.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Security Alert: This Web site needs to create a digital signature using your private key.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Security Alert: This Web site needs to add digital certificates to this computer.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Security Alert: This Web site needs access to digital certificates on this computer.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Security Alert: This Web site needs to delete digital certificates from this computer.&lt;BR&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Some people would like to have them &lt;STRONG&gt;localized&lt;/STRONG&gt; to i.e. Spanish, or at least be able to &lt;STRONG&gt;turn&lt;/STRONG&gt; them &lt;STRONG&gt;off&lt;/STRONG&gt;. Unfortunately there are no localized versions of CAPICOM.dll and those messages can't be turned off.&lt;/P&gt;
&lt;P&gt;Additionally, there are no plans to create such localized versions in the future. CAPICOM support is very limited already (will it be available in next version of Windows? Who knows...), and it's pretty much dedicated to fix security bugs if ever found.&lt;/P&gt;
&lt;P&gt;As always, my recommendation is to use &lt;STRONG&gt;.NET&lt;/STRONG&gt; and &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.aspx"&gt;System.Security.Cryptography&lt;/A&gt; classes whenever possible.&lt;/P&gt;
&lt;P&gt;If you need to use .NET assemblies from &lt;STRONG&gt;client side scripting&lt;/STRONG&gt; (main use of CAPICOM for many people), for instance, here you can find a sample to create an &lt;STRONG&gt;ActiveX&lt;/STRONG&gt; from an assembly, so &lt;STRONG&gt;System.Security.Cryptography&lt;/STRONG&gt; classes can be used in Internet Explorer: &lt;A class="" href="http://www.c-sharpcorner.com/UploadFile/dsandor/ActiveXInNet11102005040748AM/ActiveXInNet.aspx" mce_href="http://www.c-sharpcorner.com/UploadFile/dsandor/ActiveXInNet11102005040748AM/ActiveXInNet.aspx"&gt;Writing an ActiveX Control in .NET&lt;/A&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8333427" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category></item><item><title>CAPICOM support on Windows Server 2008</title><link>http://blogs.msdn.com/alejacma/archive/2008/03/06/capicom-support-on-windows-server-2008.aspx</link><pubDate>Thu, 06 Mar 2008 09:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8067431</guid><dc:creator>alejacma</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8067431.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8067431</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Tahoma','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Hi all, welcome back,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Tahoma','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Tahoma','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;If you remember all the confusion there was regarding &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx"&gt;CAPICOM support on Vista&lt;/A&gt;, now everything seems much clearer on Windows Server 2008. Our documentation team has done its homework, as we can see in &lt;A class="" href="http://msdn2.microsoft.com/en-gb/library/aa375732.aspx" mce_href="http://msdn2.microsoft.com/en-gb/library/aa375732.aspx"&gt;CAPICOM Reference&lt;/A&gt;:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;FONT face=Tahoma&gt;"CAPICOM is &lt;STRONG&gt;available&lt;/STRONG&gt; for use in the following operating systems: &lt;STRONG&gt;Windows Server 2008&lt;/STRONG&gt;, &lt;STRONG&gt;Windows Vista&lt;/STRONG&gt;, Windows XP, and Windows 2000. It may be altered or unavailable in subsequent versions. &lt;STRONG&gt;Instead, use the .NET Framework&lt;/STRONG&gt; to implement security features."&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;I hope this helps.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;Cheers,&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;BR&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8067431" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Windows+Server+2008/default.aspx">Windows Server 2008</category></item><item><title>CAPICOM support on Windows Vista</title><link>http://blogs.msdn.com/alejacma/archive/2007/10/19/capicom-support-on-windows-vista.aspx</link><pubDate>Fri, 19 Oct 2007 10:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5520294</guid><dc:creator>alejacma</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/5520294.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=5520294</wfw:commentRss><description>&lt;P&gt;I know there has been a lot of confusion about this, because some articles on the web (i.e. MSDN) say &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; is not supported on &lt;STRONG&gt;Vista&lt;/STRONG&gt;, while others say it is.&lt;/P&gt;
&lt;P&gt;I have good news for you people, especially for those who want to do cryptographic operations from scripting: CAPICOM is officially supported on Vista, but only on its version &lt;STRONG&gt;2.1.0.2&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;This version can be downloaded from here: &lt;/P&gt;
&lt;P&gt;Platform SDK Redistributable: CAPICOM&lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&amp;amp;DisplayLang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&amp;amp;DisplayLang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&amp;amp;DisplayLang=en&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;(Note: at the time of this writing, this article DOES NOT say that CAPICOM is supported on Vista).&lt;/P&gt;
&lt;P&gt;This new version of CAPICOM was released, among other reasons,&amp;nbsp;because of a security update on CAPICOM:&lt;/P&gt;
&lt;P&gt;Security Update for CAPICOM (KB931906)&lt;BR&gt;&lt;A href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CA930018-4A66-4DA6-A6C5-206DF13AF316&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=CA930018-4A66-4DA6-A6C5-206DF13AF316&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyId=CA930018-4A66-4DA6-A6C5-206DF13AF316&amp;amp;displaylang=en&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;(Note: this article DOES say that CAPICOM is supported on Vista)&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If we try to use version 2.1.0.1 on Vista, for instance,&amp;nbsp;a small .NET sample which uses CAPICOM like the following: &lt;BR&gt;"&lt;BR&gt;&lt;EM&gt;StoreClass store = new StoreClass();&lt;BR&gt;store.Open(CAPICOM_STORE_LOCATION.CAPICOM_SMART_CARD_USER_STORE, null, CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_WRITE);&lt;/EM&gt;&lt;BR&gt;"&lt;BR&gt;Will return the following exception:&lt;BR&gt;"&lt;BR&gt;&lt;EM&gt;System.Runtime.InteropServices.COMException (0x80880900): Exception from HRESULT: 0x80880900&lt;/EM&gt;&lt;BR&gt;"&lt;BR&gt;Which means:&lt;BR&gt;"&lt;BR&gt;&lt;EM&gt;# for hex 0x80880900 / decimal -2138568448&lt;BR&gt;&amp;nbsp; CAPICOM_E_NOT_SUPPORTED&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; capicom.h&lt;/EM&gt;&lt;BR&gt;"&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Anyway, my recommendation is to use .NET Framework classes instead of CAPICOM whenever possible.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5520294" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Windows+Vista/default.aspx">Windows Vista</category></item></channel></rss>