<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Decrypt my World</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/alejacma/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/alejacma/feed.xml</link>
    <description>Cryptography, Security, Debugging and more!</description>
    <lastBuildDate>Wed, 04 Nov 2015 06:12:37 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Good bye Escalation Engineer, Hello Developer Evangelist</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/good-bye-escalation-engineer-hello-developer-evangelist</link>
      <pubDate>Wed, 18 Jul 2012 00:16:33 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/07/18/good-bye-escalation-engineer-hello-developer-evangelist/</guid>
      <description><![CDATA[Hello all,

&nbsp;

I recently changed to another department within Microsoft. I am not an...]]></description>
      <content:encoded><![CDATA[Hello all,

&nbsp;

I recently changed to another department within Microsoft. <strong>I am not</strong> an <strong>Escalation Engineer</strong> working with Windows SDK in general and Crypto in particular anymore. No.&nbsp;<strong>Now</strong> I am a <strong>Developer Evangelist</strong> fully dedicated to <strong>Windows 8 and Windows Phone</strong> development in Spain.

<strong>So what does this mean to this blog?</strong> Well, I don't think I will be able to post any more content on CryptoAPI or related from now on. I am&nbsp;basically discontinuing this blog until further notice. If I have time to post something now,&nbsp;it will be related to development of Metro style applications on Windows 8 and Windows Phone 7.5/8, and preferably in Spanish for our Spanish audience. For the moment, consider this to be <strong>my last post on this blog</strong>.

<strong>What will happen with all the posts I've written so far?</strong> Nothing, I won't delete them or anything. I will leave the blog as is for your reference.

<strong>And what if you need help?</strong> I will still try to answer your questions, but my suggestion if you need urgent help is that you create a Technical Support case so my colleagues can assist you appropriately.

&nbsp;

It's been a great pleasure writing this blog, and I<strong> THANK YOU</strong> all for your questions,&nbsp;comments, suggestions and thank-you's during the live of this blog.

Cheers!

&nbsp;

<p>Alex (Alejandro Campos Magencio)</p><div class="fb_reset" id="fb-root">  <div style="top: -10000px; width: 0px; height: 0px; position: absolute;">  <div></div>  </div>  </div>]]></content:encoded>
    </item>
    <item>
      <title>.NET and the XAdES standard</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/net-and-the-xades-standard</link>
      <pubDate>Fri, 25 May 2012 01:57:45 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/05/25/net-and-the-xades-standard/</guid>
      <description><![CDATA[Hi all,

&nbsp;

You may know already that SignedXml class in .NET doesn't support the XML Advanced...]]></description>
      <content:encoded><![CDATA[Hi all,

&nbsp;

You may know already that <strong>SignedXml</strong> class in<strong> .NET doesn't support</strong> the <strong>XML Advanced Electronic Signatures (XAdES) </strong><strong></strong>standard (more info&nbsp;here: <a href="http://blogs.msdn.com/b/alejacma/archive/2010/08/18/which-standards-does-signedxml-support.aspx">Which standards does SignedXml support?</a>)

Fortunatelly my colleagues in Microsoft France developed a&nbsp;<strong>XAdES library&nbsp;for .NET</strong>&nbsp;<strong>(Microsoft.Xades.dll)</strong> that they published on this French site: <a href="http://www.microsoft.com/france/interop/ressources/xades.aspx">Kit de d&eacute;marrage &laquo; Signature avanc&eacute;e (XAdES) pour Microsoft .NET Framework v3.5 (et ult&eacute;rieur)</a>

Disclaimer: I don't speak French, so I don't understand the license for this library and cannot tell if any restrictions come with it.

&nbsp;

I hope this helps.

Regards,

&nbsp;

Alex (Alejandro Campos Magencio)

&nbsp;

<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>How to remove a certificate from a certificate store programmatically (PowerShell)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-remove-a-certificate-from-a-certificate-store-programmatically-powershell</link>
      <pubDate>Fri, 27 Apr 2012 05:37:23 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/27/how-to-remove-a-certificate-from-a-certificate-store-programmatically-powershell/</guid>
      <description><![CDATA[Hi all,

The following sample will remove a certificate from MY certificate store of the local...]]></description>
      <content:encoded><![CDATA[Hi all,

The following sample will <strong>remove</strong> a <strong>certificate</strong> from <strong>MY</strong> certificate store of the <strong>local machine</strong> after locating it by <strong>serial number</strong>:

<code><br> # Pass Serial Number of the cert you want to remove<br> param ($serialNumber = $(throw "Please pass a certificate's serial number to the script"))<br> <br> # Access MY store of Local Machine profile <br> $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")<br> $store.Open("ReadWrite")<br> <br> # Find the cert we want to delete<br> $cert = $store.Certificates.Find("FindBySerialNumber",$serialNumber,$FALSE)[0]<br> <br> if ($cert -ne $null)<br> {<br> # Found the cert. Delete it (need admin permissions to do this)<br> $store.Remove($cert)<br> <br> Write-Host "Certificate with Serial Number" $serialNumber "has been deleted"<br> }<br> else<br> {<br> # Didn't find the cert. Exit<br> Write-Host "Certificate with Serial Number" $serialNumber "could not be found"<br> }<br> <br> # We are done<br> $store.Close()</code>

&nbsp;

Note: this sample attacks the local machine profile, so by default you will need admin permissions to remove certs from its MY store.

I hope this helps.

Regards,

&nbsp;

<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to get all certificates in the Server Certificates section of IIS Manager programmatically (PowerShell)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-get-all-certificates-in-the-server-certificates-section-of-iis-manager-programmatically-powershell</link>
      <pubDate>Fri, 27 Apr 2012 05:28:00 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/27/how-to-get-all-certificates-in-the-server-certificates-section-of-iis-manager-programmatically-powershell/</guid>
      <description><![CDATA[Hi all,
The certificates in the Server Certificates section of IIS Manager (inetmgr.exe) are...]]></description>
      <content:encoded><![CDATA[<p>Hi all,</p>
<p>The certificates in the <strong>Server Certificates</strong> section of <strong>IIS Manager</strong> (inetmgr.exe) are certificates located in <strong>MY</strong> certificate store of the <strong>local machine</strong>, and their <strong>Enhanced Key Usage</strong> is <strong>Server Authentication</strong>. The following sample gets those certs:</p>
<pre class="scroll"><code class="css"># Get all certs in MY store of Local Machine profile<br /> $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")<br /> $store.Open("ReadOnly")<br /> $store.Certificates | <br /> % { <br /> # Get all extensions for one cert<br /> $cert = $_<br /> $cert.Extensions | <br /> % { <br /> # Find "Enhanced Key Usage" extension<br /> $extension = $_<br /> If ($extension.Oid.FriendlyName -eq "Enhanced Key Usage")<br /> {<br /> # Get all enhanced key usages for the cert<br /> $enhancedKeyUsageExtension = [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]$extension<br /> $enhancedKeyUsageExtension.EnhancedKeyUsages | <br /> % { <br /> # Find "Server Authentication" enhanced key usage<br /> $enhancedKeyUsage = $_<br /> If ($enhancedKeyUsage.FriendlyName -eq "Server Authentication") <br /> {<br /> # We found a cert that will get listed in Server Certificates list in IIS Manager. Show its info <br /> $cert | Select Subject, Issuer, NotBefore, NotAfter, Thumbprint, SerialNumber<br /> } <br /> }<br /> } <br /> }<br /> }<br /> $store.Close()</code></pre>
<p>&nbsp;</p>
<p>I hope this helps.</p>
<p>Regards,</p>
<p>&nbsp;</p>
<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to install the response from a CA programmatically (PowerShell)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-install-the-response-from-a-ca-programmatically-powershell</link>
      <pubDate>Fri, 27 Apr 2012 05:19:36 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/27/how-to-install-the-response-from-a-ca-programmatically-powershell/</guid>
      <description><![CDATA[Hi all,
&nbsp;
The other day a customer of mine was creating a SSL certificate request with IIS...]]></description>
      <content:encoded><![CDATA[<p>Hi all,</p>
<p>&nbsp;</p>
<p>The other day a customer of mine was creating a <strong>SSL certificate request</strong> with <strong>IIS Manager</strong> (inetmgr.exe) with <strong>"Create Certificate Request..." </strong>action in the <strong>Server Certificates</strong> section. He was sending that request to a Certificate Authority, and he wanted to programmatically <strong>install</strong> the .cer file with the <strong>response</strong> from the CA the same way you do it manually with <strong>"Complete Certificate Request&hellip;"</strong> action in the Server Certificates section.</p>
<p>The following <strong>Powershell sample</strong> does that:</p>
<pre class="scroll"><code class="csharp">$strBase64Response = get-content "C:\Test\Base64.cer"<br /> $objEnroll = New-Object -ComObject X509Enrollment.CX509enrollment<br /> $objEnroll.Initialize(0x2);<br /> $objEnroll.InstallResponse(0x4, $strBase64Response, 0, $null)</code></pre>
<p>&nbsp;</p>
<p>Note: the 0x2 value in Initialize call means ContextMachine, and the 0x4 value in InstallResponse call means AllowUntrustedRoot.</p>
<p>Note: you need to run this with an administrator, as the cert will go to the MY certificate store of the local machine, and only admin users have access to write in there by default.</p>
<p>I hope this helps.</p>
<p>Regards,</p>
<p>&nbsp;</p>
<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to export issued certificates from a CA programatically (PowerShell)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-export-issued-certificates-from-a-ca-programatically-powershell</link>
      <pubDate>Fri, 13 Apr 2012 05:56:38 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/13/how-to-export-issued-certificates-from-a-ca-programatically-powershell/</guid>
      <description><![CDATA[Hi all,
&nbsp;
The following sample is a conversion of How to export issued certificates from a CA...]]></description>
      <content:encoded><![CDATA[<p>Hi all,</p>
<p>&nbsp;</p>
<p>The following sample is a conversion of <a href="http://blogs.msdn.com/b/alejacma/archive/2012/04/04/how-to-export-issued-certificates-from-a-ca-programatically-c.aspx">How to export issued certificates from a CA programatically (C#)</a>&nbsp;sample to <strong>PowerShell</strong>. It will get all the <strong>issued certs</strong> in the <strong>CA database</strong> and copy them to a folder:</p>
<p>&nbsp;</p>
<pre class="scroll"><code class="csharp">#Params <br /> $strServer = "myserver"; <br /> $strCAName = "myserver-CA"; <br /> $strPathForCerts = "c:\test\"; <br /> <br /> # Constants <br /> $CV_OUT_BASE64HEADER = 0; <br /> $CV_OUT_BINARY = 2; <br /> <br /> # Connecting to the Certificate Authority <br /> $objCertView = New-Object -ComObject CertificateAuthority.View<br /> $objCertView.OpenConnection($strServer + "\" + $strCAName)<br /> <br /> # Get a column count and place columns into the view <br /> $iColumnCount = $objCertView.GetColumnCount(0)<br /> $objCertView.SetResultColumnCount($iColumnCount)<br /> <br /> # Place each column in the view<br /> for ($x=0; $x -lt $iColumnCount; $x++)<br /> {<br /> $objCertView.SetResultColumn($x)<br /> } <br /> <br /> # Open the View and reset the row position <br /> $objCertViewRow = $objCertView.OpenView(); <br /> $objCertViewRow.Reset(); <br /> <br /> # Enumerate Row and Column Information <br /> # Rows (one per cert) <br /> for ($x = 0; $objCertViewRow.Next() -ne -1; $x++) <br /> { <br /> # Columns with the info we need <br /> $objCertViewColumn = $objCertViewRow.EnumCertViewColumn() <br /> while ($objCertViewColumn.Next() -ne -1) <br /> { <br /> switch ($objCertViewColumn.GetDisplayName()) <br /> { <br /> "Request ID"<br /> {<br /> #Request ID <br /> $objValue = $objCertViewColumn.GetValue($CV_OUT_BINARY)<br /> if ($objValue -ne $null) { <br /> $strID = "Request ID " + $objValue<br /> }<br /> break<br /> } <br /> <br /> "Binary Certificate"<br /> {<br /> # Binary Certificate <br /> $objValue = $objCertViewColumn.GetValue($CV_OUT_BASE64HEADER); <br /> if ($objValue -ne $null) { <br /> # Write certificate to file <br /> $strPath = $strPathForCerts + $strID + ".cer"<br /> Set-Content $strPath $objValue<br /> } <br /> break<br /> }<br /> default <br /> {<br /> }<br /> } <br /> } <br /> } <br /> <br /> Write-Host "We are done!`nCerts have been copied to " + $strPathForCerts</code></pre>
<p>&nbsp;</p>
<p>I hope it helps.</p>
<p>Regards,</p>
<p>&nbsp;</p>
<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to export issued certificates from a CA programatically (C#)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-export-issued-certificates-from-a-ca-programatically-c</link>
      <pubDate>Wed, 04 Apr 2012 07:29:46 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/04/how-to-export-issued-certificates-from-a-ca-programatically-c/</guid>
      <description><![CDATA[Hi all,
&nbsp;
The following sample is a simplification of How to get info from client...]]></description>
      <content:encoded><![CDATA[<p>Hi all,</p>
<p>&nbsp;</p>
<p>The following <strong>sample</strong> is a simplification of <a href="http://blogs.msdn.com/b/alejacma/archive/2010/05/10/how-to-get-info-from-client-certificates-issued-by-a-ca-c.aspx">How to get info from client certificates issued by a CA (C#)</a>, and gets all the <strong>issued certs</strong> in the <strong>CA database</strong> and copies them to a folder:</p>
<p>&nbsp;</p>
<pre class="scroll"><code class="csharp">using System;<br /> using System.Windows.Forms;<br /> using System.IO;<br /> using CERTADMINLib;<br /> <br /> &hellip;<br /> <br /> // Parameters<br /> string strServer = "myserver";<br /> string strCAName = "myserver-CA";<br /> string strPathForCerts = "c:\\test\\";<br /> <br /> // Constants<br /> const int CV_OUT_BASE64HEADER = 0;<br /> const int CV_OUT_BINARY = 2;<br /> <br /> // Variables<br /> CERTADMINLib.CCertView certView = null;<br /> CERTADMINLib.IEnumCERTVIEWROW certViewRow = null;<br /> CERTADMINLib.IEnumCERTVIEWCOLUMN certViewColumn = null;<br /> int iColumnCount = 0;<br /> object objValue = null;<br /> string strID = "";<br /> StreamWriter objFile = null;<br /> <br /> // Connecting to the Certificate Authority<br /> certView = new CERTADMINLib.CCertView();<br /> certView.OpenConnection(strServer + "\\" + strCAName);<br /> <br /> // Get a column count and place columns into the view<br /> iColumnCount = certView.GetColumnCount(0);<br /> certView.SetResultColumnCount(iColumnCount);<br /> <br /> // Place each column in the view.<br /> for (int x = 0; x &lt; iColumnCount; x++)<br /> {<br /> certView.SetResultColumn(x);<br /> }<br /> <br /> // Open the View and reset the row position<br /> certViewRow = certView.OpenView();<br /> certViewRow.Reset();<br /> <br /> // Enumerate Row and Column Information<br /> <br /> // Rows (one per cert) <br /> for (int x = 0; certViewRow.Next() != -1; x++)<br /> {<br /> // Columns with the info we need<br /> certViewColumn = certViewRow.EnumCertViewColumn();<br /> while (certViewColumn.Next() != -1)<br /> {<br /> switch (certViewColumn.GetDisplayName())<br /> {<br /> // Request ID<br /> case "Request ID":<br /> objValue = certViewColumn.GetValue(CV_OUT_BINARY);<br /> if (objValue != null)<br /> {<br /> strID = "Request ID " + objValue.ToString();<br /> }<br /> break;<br /> <br /> // Binary Certificate<br /> case "Binary Certificate":<br /> objValue = certViewColumn.GetValue(CV_OUT_BASE64HEADER);<br /> if (objValue != null)<br /> {<br /> // Write certificate to file<br /> objFile = File.CreateText(strPathForCerts + strID + ".cer");<br /> objFile.Write(objValue.ToString());<br /> objFile.Close(); <br /> }<br /> break;<br /> <br /> default:<br /> break;<br /> }<br /> }<br /> }<br /> <br /> MessageBox.Show("We are done!\nCerts have been copied to " + strPathForCerts);</code></pre>
<p>&nbsp;</p>
<p>I hope this helps.</p>
<p>Regards,</p>
<p>&nbsp;</p>
<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>How to get info from client certificates issued by a CA (C#, VS 2010)</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/how-to-get-info-from-client-certificates-issued-by-a-ca-c-vs-2010</link>
      <pubDate>Wed, 04 Apr 2012 07:24:26 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/04/04/how-to-get-info-from-client-certificates-issued-by-a-ca-c-vs-2010/</guid>
      <description><![CDATA[Hi all,

&nbsp;

I developed this sample some time ago: How to get info from client certificates...]]></description>
      <content:encoded><![CDATA[Hi all,

&nbsp;

I developed this sample some time ago: <a href="http://blogs.msdn.com/b/alejacma/archive/2010/05/10/how-to-get-info-from-client-certificates-issued-by-a-ca-c.aspx">How to get info from client certificates issued by a CA (C#)</a>. The other day I tried it on a new machine with <strong>Windows 7</strong>, <strong>Visual Studio 2010</strong> and <strong>.NET Framework 4.0</strong>, and it didn't even compile. I had to do the following to make it work:

1) Install this&nbsp;to be able to use<strong>&nbsp;certadmin.dll</strong> in a client machine:

<a href="http://www.microsoft.com/download/en/details.aspx?id=7887">Remote Server Administration Tools for Windows 7 with Service Pack 1 (SP1)<br></a>

Or this depending on your OS version:

<a href="http://www.microsoft.com/download/en/details.aspx?id=21090">Microsoft Remote Server Administration Tools for Windows Vista<br></a>

And turn the feature on from "Control Panel" &gt; "Programs and Features" &gt; "Turn Windows features on or off".

2) Generate <strong>certadminlib.dll</strong> with "<em>tlbimp certadm.dll</em>" and add it as a reference to the project.

3) Change this<br>&ldquo;<br><em>CERTADMINLib.CCertViewClass</em><br>&ldquo;<br>to this:<br>&ldquo;<br><em>CERTADMINLib.CCertView</em><br>&ldquo;

4) Add <strong>Microsoft.CSharp </strong>reference.

&nbsp;

I hope this helps.

Regards,

&nbsp;

<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>Why is my process in a Job if I didn't put it there?</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/why-is-my-process-in-a-job-if-i-didnt-put-it-there</link>
      <pubDate>Fri, 09 Mar 2012 06:06:00 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/03/09/why-is-my-process-in-a-job-if-i-didnt-put-it-there/</guid>
      <description><![CDATA[Hi all,

The other day a customer of mine was having this issue on Windows 7: CreateProcessAsUser...]]></description>
      <content:encoded><![CDATA[Hi all,

The other day a customer of mine was having this issue on <strong>Windows 7</strong>: <a class="internal-link view-post" href="http://blogs.msdn.com/b/alejacma/archive/2012/03/09/createprocessasuser-fails-with-error-5-access-denied-when-using-jobs.aspx">CreateProcessAsUser fails with error 5 (Access Denied) when using Jobs</a>. So he had a Windows service running as System in Session 0, that service created a process running as System in Session 0 too, and this process tried to create a new process in logged-on user's session but failed with <strong>Access Denied</strong>. The process that the service created as System in Session 0 was member of a Job and that was the cause of the issue as my other post explains.

Now, my customer confirmed me that he wasn't explicitly adding the process to a Job. Actually, he wasn't using Jobs at all in his app. <strong>Why was the process a member of a Job</strong> then?

According to the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx">Job Objects</a>&nbsp;documentation, a process is associated to a Job either <strong>explicitly</strong> via <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681949(v=vs.85).aspx">AssignProcessToJobObject</a> API or <strong>by default</strong> if your parent process is part of a Job already. In my customer's scenario, his Windows service was not part of a Job, and he wasn't calling any Job API in his code.

&nbsp;

I did some kernel debugging to figure out who was assigning that process to a Job, and I found it. Our <strong>Program Compatibility Assistant Service</strong> (<strong>PcaSvc</strong>) was the process calling <strong>AssignProcessToJobObject</strong>&nbsp;to do the task.

Our Program Compatibility Assistant (<strong>PCA</strong>) service got the details of customer's app and the Job from an LRPC (Local Remote Procedure Call) call made from customer's Windows Service. But customer's code was not doing this directly. This was something that was happening behind the scenes when the service was creating the problematic process.

What is PCA?

<a href="http://windows.microsoft.com/en-US/windows-vista/Program-Compatibility-Assistant-frequently-asked-questions">Program Compatibility Assistant: frequently asked questions<br></a>"<br><em>What is the Program Compatibility Assistant? </em><br><em>The Program Compatibility Assistant detects known compatibility issues in older programs.</em>

<em>What changes does it make? </em><br><em>It depends on the problem, but any changes made are related to how Windows runs the program. No changes are made to the program itself. For example, the Program Compatibility Assistant can resolve conflicts with User Account Control, a new security feature in this version of Windows that can help make your computer safer. Or, it can run the program in a mode that simulates earlier versions of Windows. The changes that Program Compatibility Assistant makes are done automatically, so you don't need to make them.</em>

<em>How do I turn it off or turn it back on? </em><br><em>Adjustments to the Program Compatibility Wizard can be made by using Group Policy. For more information on how to use Group Policy, go to the Microsoft website for IT professionals.</em><br><em>The Program Compatibility Assistant is an automatic feature of Windows that runs when it detects an older program has a compatibility problem.</em><br>"

Doing some research I found out that, by design, <strong>PCA uses Job objects to perform its tasks</strong>. So PCA is clearly interfering with the problematic process. It detected some sort of compatibility problem with it, run it in compatibility mode and assigned it to a&nbsp;Job to handle it.

&nbsp;

There are several ways to <strong>exclude programs from the PCA</strong>:

<a href="http://msdn.microsoft.com/en-us/library/bb756937.aspx">Program Compatibility Assistant (PCA) in Windows Vista</a><br>"<br><em>Excluding Programs from PCA</em>

<em>PCA is intended to detect issues with older programs and not intended to monitor programs developed for Windows Vista and Windows Server 2008. The best option to exclude a program from PCA is to include, with the program, an application manifest with run level (either Administrator or as limited users) marking for UAC. This marking means the program is tested to work under UAC (and Windows Vista and Windows Server 2008). PCA checks for this manifest and will exclude the program. This process applies for both installer and regular programs.</em>

<em>Another option to exclude applications from PCA is to add the list of executable files with full path under the following registry key: HKEY_LOCAL_MACHINE\ Software\Microsoft\Windows NT\CurrentVersion\Compatibility Assistant. The value name is ExecutablesToExclude, which is type REG_MULTI_SZ.</em>

<em>PCA automatically excludes programs running from network locations and programs containing fixes applied to them in the application compatibility databases.</em>

<em>A group policy setting is provided to disable PCA for all programs if desired. The name of the policy is Turn Off Program Compatibility Assistant. It can be found under Administrative Templates\Windows Components\Application Compatibility in the group policy editor (gpedit.msc).</em>

<em>There are also individual policies to turn off specific scenarios. These policies are available under Administrative Templates\System\Troubleshooting and Diagnostics\Application Compatibility Diagnostics in the group policy editor.</em> <br>"

So just to test my findings were correct, I did a quick test: I added the path to the problematic EXE to the REG_MULTI_SZ value ExecutablesToExclude I created under HKEY_LOCAL_MACHINE\ Software\Microsoft\Windows NT\CurrentVersion\Compatibility Assistant, and it worked! The problematic process was not assigned to a Job anymore, and I didn't get the Access Denied error.

&nbsp;

Summing up, there are <strong>several ways to solve this issue</strong>:<br>1)&nbsp;Problematic process creates its child processes with <strong>CREATE_BREAKAWAY_FROM_JOB</strong>, so we don&rsquo;t care if it is within a Job or not.<br>2)&nbsp;We exclude the problematic process from PCA via <strong>registry or GPO</strong>.<br>3)&nbsp;We add a <strong>UAC manifest</strong> to problematic process. (For example: <a href="http://msdn.microsoft.com/en-us/library/bb756929.aspx">Step 6: Create and Embed an Application Manifest (UAC)</a>).

&nbsp;

My customer already had a <strong>manifest</strong> in his problematic process, but he had to add a <strong>Compatibility section</strong> (see <a href="http://msdn.microsoft.com/en-us/library/dd371711(v=vs.85).aspx">Application Manifest</a> for details) to make things work on Windows 7:

"

&nbsp;<span style="color: blue;">&lt;?</span><span style="color: #a31515;">xml</span> <span style="color: red;">version</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">1.0</span><span style="color: black;">"</span> <span style="color: red;">encoding</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">UTF-8</span><span style="color: black;">"</span> <span style="color: red;">standalone</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">yes</span><span style="color: black;">"</span><span style="color: blue;">?&gt;</span> <br>&nbsp; <span style="color: blue;">&lt;</span><span style="color: #a31515;">assembly</span> <span style="color: red;">xmlns</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">urn:schemas-microsoft-com:asm.v1</span><span style="color: black;">"</span> <span style="color: red;">manifestVersion</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">1.0</span><span style="color: black;">"</span><span style="color: blue;">&gt;</span> <br>&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;</span><span style="color: #a31515;">compatibility</span> <span style="color: red;">xmlns</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">urn:schemas-microsoft-com:compatibility.v1</span><span style="color: black;">"</span><span style="color: blue;">&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;</span><span style="color: #a31515;">application</span><span style="color: blue;">&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: green;">&lt;!--The ID below indicates application support for Windows Vista --&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;</span><span style="color: #a31515;">supportedOS</span> <span style="color: red;">Id</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">{e2011457-1546-43c5-a5fe-008deee3d3f0}</span><span style="color: black;">"</span><span style="color: blue;">/&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: green;">&lt;!--The ID below indicates application support for Windows 7 --&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;</span><span style="color: #a31515;">supportedOS</span> <span style="color: red;">Id</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">{35138b9a-5d96-4fbd-8e2d-a2440225f93a}</span><span style="color: black;">"</span><span style="color: blue;">/&gt;</span> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;/</span><span style="color: #a31515;">application</span><span style="color: blue;">&gt;</span> <br>&nbsp;&nbsp;&nbsp; <span style="color: blue;">&lt;/</span><span style="color: #a31515;">compatibility</span><span style="color: blue;">&gt;</span><br>&nbsp; <span style="color: blue;">&lt;/</span><span style="color: #a31515;">assembly</span><span style="color: blue;">&gt;</span><br>"

I hope this helps.

Regards,

&nbsp;

<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
    <item>
      <title>CreateProcessAsUser fails with error 5 (Access Denied) when using Jobs</title>
      <link>https://docs.microsoft.com/archive/blogs/alejacma/createprocessasuser-fails-with-error-5-access-denied-when-using-jobs</link>
      <pubDate>Fri, 09 Mar 2012 02:03:54 GMT</pubDate>
      <dc:creator><![CDATA[Alejandro Campos Magencio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/alejacma/2012/03/09/createprocessasuser-fails-with-error-5-access-denied-when-using-jobs/</guid>
      <description><![CDATA[Hi all,

The other day I worked on a support case where a Windows service running as System in...]]></description>
      <content:encoded><![CDATA[Hi all,

The other day I worked on a support case where a <strong>Windows service</strong> running as <strong>System</strong> in <strong>Session 0</strong> was creating a <strong>process&nbsp;</strong>also running as <strong>System</strong> in <strong>Session 0</strong>, and this new process failed to create another <strong>process</strong> in the <strong>logged-on user's session</strong> (Session 2 in this particular case). And it failed because <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx">CreateProcessAsUser </a>API didn't work and returned <strong>error 5</strong> (<strong>Access Denied</strong>).

Note the issue happened on <strong>Windows 7</strong>, and because of <a href="http://msdn.microsoft.com/en-us/library/bb756986.aspx">Session 0 Isolation</a> the logged-on user and the service (and its child process running as System) were running in different sessions.

&nbsp;

To understand what was going on exactly, I did some kernel debugging of the issue and saw that the <strong>error</strong> in CreateProcessAsUser happened when trying to <strong>bind</strong> the <strong>process</strong> we were trying to spawn <strong>to its parent's Job</strong> (the Job that the process that the service spawned as System was a member of).

Indeed, I could verify with <a href="http://technet.microsoft.com/en-us/sysinternals/bb896653">Process Explorer</a>&nbsp;that the process running as System in Session 0 was member of a Job, by checking the properties of the process and going to the <strong>Job tab</strong> (note: when there is no Job, there is no Job tab).

After a process is associated with a job, by default any child processes it creates are also associated with the job (see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx">Job Objects</a> for more details on this)<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx)"></a>.

But the following is also documented:

<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681949(v=vs.85).aspx">AssignProcessToJobObject function<br></a>"<br><em>Terminal Services: All processes within a job must run within the same session as the job.</em><br>"

Which means that, as the new process we are trying to create is in a different session than its parent, we will fail to bind it to its parent's Job.

&nbsp;

The only way to work around this, would be to <strong>create the process</strong> in the different session by <strong>passing this flag</strong> to the CreateProcessAsUser API:

<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx">Process Creation Flags</a><br>&ldquo;<br><strong><em>CREATE_BREAKAWAY_FROM_JOB</em></strong><br><em></em>

<em>0x01000000&nbsp;The child processes of a process associated with a job are not associated with the job. </em><br><em>If the calling process is not associated with a job, this constant has no effect. If the calling process is associated with a job, the job must set the JOB_OBJECT_LIMIT_BREAKAWAY_OK limit.</em>

&ldquo;

I hope this helps.

Regards,

&nbsp;

<p>Alex (Alejandro Campos Magencio)</p>]]></content:encoded>
    </item>
  </channel>
</rss>