<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Toolkits</title>
        <link>http://geekswithblogs.net/robp/category/6422.aspx</link>
        <description>Development toolkits, neat things that enhance efficiency, and all the fun little toys we like to bring to our jobs.</description>
        <language>en-US</language>
        <copyright>Robert Paveza</copyright>
        <managingEditor>robp@terralever.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>C#: Determining if a file has a valid digital signature</title>
            <link>http://geekswithblogs.net/robp/archive/2007/05/04/112250.aspx</link>
            <description>&lt;p&gt;One of the neat things Microsoft incorporated into Windows with the release of Internet Explorer 4 (which was provided for Windows 95 and Windows NT 4.0 with Service Pack 3) was the &lt;a target="_blank" href="http://msdn2.microsoft.com/en-us/library/aa380256.aspx"&gt;CryptoAPI&lt;/a&gt;, which provided not only services for &lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; Z-INDEX: 255; BORDER-BOTTOM-WIDTH: 0px; MARGIN: 0px; POSITION: relative; BORDER-RIGHT-WIDTH: 0px" height="315" alt="" width="489" align="right" border="0" src="http://geekswithblogs.net/images/geekswithblogs_net/robp/WindowsLiveWriter/CDeterminingifafilehasavaliddigitalsigna_9F3C/UAC_Signed_thumb%5B12%5D.jpg" /&gt;secure hashing and stream ciphers, but also implemented Microsoft's Authenticode (r) code-signing verification.  Authenticode is the technology that allows a Certification Authority (CA) such as Verisign to issue certificates to its clients in order to establish that software has been signed and is still authentic (that is, it has not been modified by any third parties).  This is beneficial for obvious reasons, of course - when you're installing the Flash plugin, for instance, having an Authenticode signature verifies to you that the code is actually from Adobe, and that it hasn't been modified for some malicious purpose by a third party (such as a hacker).&lt;/p&gt;
&lt;p&gt;Windows Vista has incorporated this further by presenting User Account Control (UAC) dialogs based on the code-signing policy defined by the system.  When prompting for elevation, Windows Vista chooses one of &lt;a target="_blank" href="http://technet2.microsoft.com/WindowsVista/en/library/00d04415-2b2f-422c-b70e-b18ff918c2811033.mspx?mfr=true"&gt;four dialogs&lt;/a&gt; based on the security policy and code signature of the target executable.&lt;/p&gt;
&lt;p&gt;As a software developer, verifying code integrity can be important; as a .NET developer, you of course have the Strong Name tool (sn.exe) to generate a private/public key pair with which to grant trust to assemblies (avoiding a trojan horse assembly in the process).  However, there may be times where we want to validate the digital signatures of non-CLR assemblies, macros, or some other entity that was digitally signed.  This will get you started by verifying the digital signature of a file; however, it can be used for other entities as described in the documentation.&lt;/p&gt;
&lt;p&gt;For this we will use the &lt;a href="http://msdn2.microsoft.com/en-us/library/aa388208.aspx"&gt;WinVerifyTrust&lt;/a&gt; API.  WinVerifyTrust takes a handle and two pointers - I hope you're excited for some new adventures in Platform Invoke!  The first thing I put together quickly was an UnmanagedPointer class - by implementing IDisposable, it helps me to avoid memory leaks.  Here's the quick low-down:&lt;/p&gt;
&lt;div class="CodeFormatContainer"&gt;&lt;style type="text/css"&gt;&lt;!--
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
	z-index: 1;
	position: relative;
}

.csharpcode .lnum { color: #606060; }

--&gt;&lt;/style&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; UnmanagedPointer &lt;span class="kwrd"&gt;class&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;sealed&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UnmanagedPointer : IDisposable&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; IntPtr m_ptr;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; AllocMethod m_meth;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;            &lt;span class="kwrd"&gt;internal&lt;/span&gt; UnmanagedPointer(IntPtr ptr, AllocMethod method)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;                m_meth = method;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                m_ptr = ptr;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            ~UnmanagedPointer()&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                Dispose(&lt;span class="kwrd"&gt;false&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; IDisposable Members&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposing)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (m_ptr != IntPtr.Zero)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (m_meth == AllocMethod.HGlobal)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                        Marshal.FreeHGlobal(m_ptr);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (m_meth == AllocMethod.CoTaskMem)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;                    {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;                        Marshal.FreeCoTaskMem(m_ptr);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;                    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;                    m_ptr = IntPtr.Zero;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (disposing)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                    GC.SuppressFinalize(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;                Dispose(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;implicit&lt;/span&gt; &lt;span class="kwrd"&gt;operator&lt;/span&gt; IntPtr(UnmanagedPointer ptr)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; ptr.m_ptr;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The AllocMethod enumeration simply specifies the HGlobal and CoTaskMem members, which indicates how Marshal originally allocated the memory.  With this class, I can now drop the memory blocks into using statements to have them automatically cleaned up, dodging a memory leak.&lt;/p&gt;
&lt;p&gt;When using file lookups, you need to utilize the &lt;a target="_blank" href="http://msdn2.microsoft.com/en-us/library/aa388206.aspx"&gt;WINTRUST_FILE_INFO&lt;/a&gt; structure, which can be represented in C# as:&lt;/p&gt;
&lt;div class="CodeFormatContainer"&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; WINTRUST_FILE_INFO : IDisposable&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; WINTRUST_FILE_INFO(&lt;span class="kwrd"&gt;string&lt;/span&gt; fileName, Guid subject)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                cbStruct = (&lt;span class="kwrd"&gt;uint&lt;/span&gt;)Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(WINTRUST_FILE_INFO));&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                pcwszFilePath = fileName;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (subject != Guid.Empty)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                    pgKnownSubject = Marshal.AllocHGlobal(Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Guid)));&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                    Marshal.StructureToPtr(subject, pgKnownSubject, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                    pgKnownSubject = IntPtr.Zero;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                hFile = IntPtr.Zero;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;uint&lt;/span&gt; cbStruct;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;            [MarshalAs(UnmanagedType.LPTStr)]&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; pcwszFilePath;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr hFile;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr pgKnownSubject;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; IDisposable Members&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;                Dispose(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposing)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (pgKnownSubject != IntPtr.Zero)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;                    Marshal.DestroyStructure(&lt;span class="kwrd"&gt;this&lt;/span&gt;.pgKnownSubject, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Guid));&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;                    Marshal.FreeHGlobal(&lt;span class="kwrd"&gt;this&lt;/span&gt;.pgKnownSubject);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that this class allocates unmanaged memory for the pgKnownSubject member - it is actually a pointer to a GUID structure, not the GUID structure itself.  Since we're not making a P/Invoke call, but a marshalable structure, we can't define a "ref" field.  I could have alternatively used a Guid* pointer type in place of that IntPtr, but I decided to stick with verifiable code.  (Note that this is also true in the upcoming code, where a WINTRUST_FILE_INFO pointer is one of the fields.&lt;/p&gt;
&lt;p&gt;Finally, we can build out the actual structure used by the API call, the &lt;a target="_blank" href="http://msdn2.microsoft.com/en-us/library/aa388205.aspx"&gt;WINTRUST_DATA&lt;/a&gt; structure:&lt;/p&gt;
&lt;div class="CodeFormatContainer"&gt;&lt;style type="text/css"&gt;&lt;!--
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
	z-index: 1;
}

.csharpcode .lnum { color: #606060; }

--&gt;&lt;/style&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        [StructLayout(LayoutKind.Sequential)]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; WINTRUST_DATA : IDisposable&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; WINTRUST_DATA(WINTRUST_FILE_INFO fileInfo)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.cbStruct = (&lt;span class="kwrd"&gt;uint&lt;/span&gt;)Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(WINTRUST_DATA));&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;                pInfoStruct = Marshal.AllocHGlobal(Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(WINTRUST_FILE_INFO)));&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;                Marshal.StructureToPtr(fileInfo, pInfoStruct, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.dwUnionChoice = UnionChoice.File;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                pPolicyCallbackData = IntPtr.Zero;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                pSIPCallbackData = IntPtr.Zero;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                dwUIChoice = UiChoice.NoUI;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                fdwRevocationChecks = RevocationCheckFlags.None;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                dwStateAction = StateAction.Ignore;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                hWVTStateData = IntPtr.Zero;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                pwszURLReference = IntPtr.Zero;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                dwProvFlags = TrustProviderFlags.Safer;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;                dwUIContext = UIContext.Execute;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;uint&lt;/span&gt; cbStruct;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr pPolicyCallbackData;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr pSIPCallbackData;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; UiChoice dwUIChoice;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; RevocationCheckFlags fdwRevocationChecks;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; UnionChoice dwUnionChoice;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr pInfoStruct;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; StateAction dwStateAction;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr hWVTStateData;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; IntPtr pwszURLReference;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; TrustProviderFlags dwProvFlags;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; UIContext dwUIContext;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            &lt;span class="preproc"&gt;#region&lt;/span&gt; IDisposable Members&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;                Dispose(&lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose(&lt;span class="kwrd"&gt;bool&lt;/span&gt; disposing)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (dwUnionChoice == UnionChoice.File)&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;                {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;                    WINTRUST_FILE_INFO info = &lt;span class="kwrd"&gt;new&lt;/span&gt; WINTRUST_FILE_INFO();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;                    Marshal.PtrToStructure(pInfoStruct, info);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;                    info.Dispose();&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;                    Marshal.DestroyStructure(pInfoStruct, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(WINTRUST_FILE_INFO));&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;                }&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;                Marshal.FreeHGlobal(pInfoStruct);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;            &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The WINTRUST_DATA structure defines a union where I defined the pInfoStruct field.  It's possible to create something similar to a union in C#, by setting StructLayout as Explicit, and by putting each of the fields in the union at the same field offset.  The drawback is that each field needs an explicit offset, which makes the structure not cross-platform (as 32-bit and 64-bit platforms will require diferrent field offsets).  I decided again to go the path of the IntPtr and do the custom marshaling myself.  You should note I use several enumerations - these are all defined on the API specification for WINTRUST_DATA.  &lt;/p&gt;
&lt;p&gt;FINALLY!  We're at the point where we actually can define and call the method.  I do both of these within a class called Interop, and translate it in an external method.  Here are the definitions:  &lt;/p&gt;
&lt;style type="text/css"&gt;&lt;!--
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
	z-index: 1;
}

.csharpcode .lnum { color: #606060; }

--&gt;&lt;/style&gt;
&lt;div class="CodeFormatContainer"&gt;
&lt;div class="CodeFormatContainer"&gt;
&lt;div class="csharpcode"&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;uint&lt;/span&gt; WinVerifyTrust(&lt;span class="kwrd"&gt;string&lt;/span&gt; fileName)&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        {&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;            Guid wintrust_action_generic_verify_v2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Guid(&lt;span class="str"&gt;"{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}"&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;            WINTRUST_FILE_INFO fileInfo = &lt;span class="kwrd"&gt;new&lt;/span&gt; WINTRUST_FILE_INFO(fileName, Guid.Empty);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            WINTRUST_DATA data = &lt;span class="kwrd"&gt;new&lt;/span&gt; WINTRUST_DATA(fileInfo);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            &lt;span class="kwrd"&gt;uint&lt;/span&gt; result = 0;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (UnmanagedPointer guidPtr = &lt;span class="kwrd"&gt;new&lt;/span&gt; UnmanagedPointer(Marshal.AllocHGlobal(Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Guid))), AllocMethod.HGlobal))&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (UnmanagedPointer wvtDataPtr = &lt;span class="kwrd"&gt;new&lt;/span&gt; UnmanagedPointer(Marshal.AllocHGlobal(Marshal.SizeOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(WINTRUST_DATA))), AllocMethod.HGlobal))&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            {&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;                IntPtr pGuid = guidPtr;&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                IntPtr pData = wvtDataPtr;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;                Marshal.StructureToPtr(wintrust_action_generic_verify_v2, pGuid, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                Marshal.StructureToPtr(data, pData, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                result = WinVerifyTrust(IntPtr.Zero, pGuid, pData);&lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt; &lt;/pre&gt;
&lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The hardest part of utilizing this code is dealing with the myriad of return values (which I will not go over here).  Essentially, if the API returns 0, then the file is signed; if not, you can use Marshal.GetLastError() to determine the results.&lt;/p&gt;
&lt;p&gt;Kudos go out to Microsoft for the &lt;a target="_blank" href="http://msdn2.microsoft.com/en-us/library/aa382384.aspx"&gt;example C program&lt;/a&gt; on which this article is based!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=112250"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=112250" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/robp/aggbug/112250.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Robert Paveza</dc:creator>
            <guid>http://geekswithblogs.net/robp/archive/2007/05/04/112250.aspx</guid>
            <pubDate>Fri, 04 May 2007 18:19:33 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/robp/comments/112250.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/robp/archive/2007/05/04/112250.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/robp/comments/commentRss/112250.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/robp/services/trackbacks/112250.aspx</trackback:ping>
        </item>
        <item>
            <title>ASP.NET 1.1 with VS 2005 </title>
            <link>http://geekswithblogs.net/robp/archive/2007/03/27/110013.aspx</link>
            <description>&lt;P&gt;Thank God I don't have to install Visual Studio 2003 onto Vista.&lt;/P&gt;
&lt;P&gt;Well, that may be a bit premature.&amp;nbsp; I have to make sure that debugging and the like will still work.&amp;nbsp; But I don't see why it wouldn't.&amp;nbsp; So yes, it does turn out that you can work on .NET 1.1 projects in Visual Studio 2005 with a couple of project templates called "&lt;A href="http://dotnet.org.za/armand/archive/2005/11/01/47857.aspx"&gt;Everett Compiler&lt;/A&gt;".&amp;nbsp; The Everett Compiler project templates include Console Application and Class Library templates that use a custom MSBuild .targets file that directs the compiler to target the C# 1.1 compiler ("Everett") instead of the typical 2.0 compiler.&amp;nbsp; The original theory was that if 2005 could be redirected to use the LINQ/C# 3.0 compiler, why couldn't it be redirected to use the 2.0 compiler?&lt;/P&gt;
&lt;P&gt;When first creating and loading a C# 1.1 project, you'll see the following dialog:&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="Visual Studio 2005 - prompt for loading custom build targets" src="http://www.jinxbot.net/pub/loadCustomBuildTargets.png"&gt;&lt;/P&gt;
&lt;P&gt;As you will learn by clicking on "More Info," you can disable this dialog by adding a string value to HKLM\Software\Microsoft\VisualStudio\8.0\MSBuild\SafeImports with the value "C:\Program Files\Everett\Everett.targets" or "C:\Program Files (x86)\Everett\Everett.targets" if you're on x64 or Itanium systems:&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="Adding the Everett build targets to the registry" src="http://www.jinxbot.net/pub/safeImportsVS8.png"&gt;&lt;/P&gt;
&lt;P&gt;Building ASP.NET support with this is somewhat more challenging.&amp;nbsp; You should be comfortable with using the ASP.NET markup syntax, because you probably don't want to try to incorporate the designer changes in ASP.NET 2.0.&lt;/P&gt;
&lt;P&gt;Having said so, there are some other things you need to do.&amp;nbsp; The Everett projects by default build to a subfolder of \bin; you'll want to have them output to \bin by default.&amp;nbsp; ASP.NET 1.1's code model is significantly different than 2.0: with 1.1: there is quite a bit less dynamic compilation done with codebehind projects in 1.1 than there is in 2.0.&lt;/P&gt;
&lt;P&gt;For projects that I built up, instead of trying to open the original project (which you probably don't want to do), I copied and pasted the files into new projects in a different subtree of the directory structure, and set up that directory as the web site in IIS 7.&amp;nbsp; Be sure to check out &lt;A href="http://mythoughtsaboutcode.blogspot.com/2007/03/vista-iis-7-and-aspnet-11-playing-nice.html"&gt;Justin Copeland's blog entry&lt;/A&gt; about setting up ASP.NET 1.1 with IIS 7 to avoid, you know, continually crashing IIS.&amp;nbsp; :)&lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=110013"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=110013" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/robp/aggbug/110013.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Robert Paveza</dc:creator>
            <guid>http://geekswithblogs.net/robp/archive/2007/03/27/110013.aspx</guid>
            <pubDate>Tue, 27 Mar 2007 16:59:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/robp/comments/110013.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/robp/archive/2007/03/27/110013.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/robp/comments/commentRss/110013.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/robp/services/trackbacks/110013.aspx</trackback:ping>
        </item>
        <item>
            <title>Outlook 2007 and the Battle for Backgrounds, Part 1</title>
            <link>http://geekswithblogs.net/robp/archive/2007/03/22/109538.aspx</link>
            <description>&lt;p&gt;&lt;font face="Tahoma"&gt;As a web marketing firm, my company manages to generate quite a bit of e-mail for our clients (all opt-in, of course), and one of the ways that we do that is by templating out the entire HTML e-mail into a user control.&amp;nbsp; The nice advantage to this is, of course, that we're able to pull in whatever kind of data we need and basically treat the e-mail like a page.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;Our production team can generate some really great artwork and layout, and up until this point it's worked great.&amp;nbsp; They've been doing extensive testing to make sure that our generated e-mails work in Outlook/Outlook Express/Thunderbird/Gmail/Hotmail/etc., and generally things have worked great.&amp;nbsp; It wasn't until we started using Outlook 2007 that things were mucked up.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;For those who don't know, Outlook 2007 no longer uses the Internet Explorer HTML rendering engine, which is probably a positive thing from a security standpoint.&amp;nbsp; It uses the Word 2007 rendering engine, which &lt;a href="http://msdn2.microsoft.com/en-us/library/aa338201.aspx"&gt;severely cuts back its HTML and CSS rendering capabilities&lt;/a&gt;.&amp;nbsp; Among the problematic rendering logic is Outlook's inability to render background images, something that has been crucial to our placing of dynamically-generated text into e-mails (for instance, a "Send to Friend" feature might include a note to the recipient).&amp;nbsp; Static text would be no problem - our graphic artists would simply include the copy in the final image.&amp;nbsp; But for dynamic text, we were left with a question of functionality - do we simply not include dynamic text, or do we put it over a solid background?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;Dynamically generating images with ASP.NET has been common since it was first released, and for a short time (through Beta 1), ASP.NET 2.0 was going to handle it natively with a new file type, *.asix (it was removed due to architectural difficulties).&amp;nbsp; Especially for low-volume e-mails (such as one that wasn't likely to generate tens of thousands of simultaneous hits to the web server), this seemed like an elegant solution, and it would work in all e-mail clients equally-well.&amp;nbsp; The only real question was how to get the data to the server efficiently.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;I opted out of storing the text in the database in this instance because, well, the dynamic text was an afterthought and I didn't really want to go back and modify the db schema (nor did I think that the text was worth storing).&amp;nbsp; Rather, I came up with a slightly roundabout way of having the client specify the message itself: since dynamic images are generally .aspx pages that send image data over the wire instead of markup, I simply include a query string as part of the image's URL (if we want to be even more creative and SEO-compliant, we can use PathInfo instead of QueryString).&amp;nbsp; The last question is how to get such data to the image without it looking funny (for instance, by having %20 encoded for spaces), and that is answered with &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;Base64&lt;/a&gt; encoding.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;Base64 encoding uses six bits to represent byte values, and so for every three bytes there are four Base64 characters.&amp;nbsp; Base64 is never garbled by browsers because it uses the 26 uppercase and lowercase characters and two standard characters + and / (note that if we used PathInfo instead of QueryString, we should replace the / character with something else such as - or _ so that we don't run into our web application believing we're running another page, in the event we're using PathInfo for URL rewriting techniques).&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Tahoma"&gt;I've created a new control that can be used in our e-mail templates.&amp;nbsp; It's entirely code, and very brief:&lt;/font&gt;&lt;/p&gt;&lt;pre&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DynamicTextImage : System.Web.UI.WebControls.Image
    {
        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; m_msg;
        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Message
        {
            &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;
            {
                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; m_msg;
            }
            &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;
            {
                m_msg = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;
            }
        }
 
        &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; OnPreRender(EventArgs e)
        {
            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Message != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Message.Length &amp;gt; 0)
            {
                &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] msgBytes = Encoding.ASCII.GetBytes(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Message);
                &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; message64 = Convert.ToBase64String(msgBytes);
                &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ImageUrl = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format("&lt;span style="color: #8b0000"&gt;{0}?t={1}&lt;/span&gt;", &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ImageUrl, message64);
            }
 
            &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.OnPreRender(e);
        }
    }&lt;/pre&gt;
&lt;p&gt;&lt;font face="Tahoma"&gt;This allows the image to be inserted in the same way a standard &lt;font face="Courier New" size="2"&gt;&amp;lt;asp:Image&amp;gt;&lt;/font&gt; control is, with no additional markup required by our production team and very little code by the developer working on it (&lt;font face="Courier New" size="2"&gt;&lt;font color="#0000ff"&gt;this&lt;/font&gt;.dynamicImage1.Message = &lt;font color="#0000ff"&gt;this&lt;/font&gt;.txtMessage.Text;&lt;/font&gt;).&amp;nbsp; &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma"&gt;Part 2 of this article will discuss the code behind generating the dynamic image and sending it to the viewer.&amp;nbsp; I'm sure for those of you who have used dynamic images in the past, the wheels are already spinning as to how you can adapt this to be effective at your organization.&amp;nbsp; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=109538"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=109538" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/robp/aggbug/109538.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Robert Paveza</dc:creator>
            <guid>http://geekswithblogs.net/robp/archive/2007/03/22/109538.aspx</guid>
            <pubDate>Thu, 22 Mar 2007 17:51:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/robp/comments/109538.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/robp/archive/2007/03/22/109538.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/robp/comments/commentRss/109538.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/robp/services/trackbacks/109538.aspx</trackback:ping>
        </item>
    </channel>
</rss>