Showing posts with label debugging. Show all posts
Showing posts with label debugging. Show all posts

What to do when CryptAcquireContext() fails

I’m using CryptoAPI to do encryption and encountering an error on Win2008 Terminal Server which enforces Mandatory Profiles. CryptAcquireContext() fails with a message of either “keyset not found” or “The profile for the user is a temporary profile”.

I’ve tried the same test on WinXP using a guest account and got the same thing.

So, what gives?

Well, this blog post (RSACryptoServiceProvider fails when used with mandatory profiles) way back in 2007 by @alejacma explains:

CryptAcquireContext will fail with NTE_TEMPORARY_PROFILE error when called from a mandatory profile.

Mandatory profiles are read-only user profiles. Since changes to the mandatory profile cannot be saved, PKI design doesn't allow this operation, and CryptAcquireContext prevents this scenario by failing.

The moral of this story is: RSA sucks, and I am now Rijndael’s new biggest fan.

By the way, troubleshooting this problem had given me the chance to learn a few more WinDbg commands:

.sympath srv*http://msdl.microsoft.com/downloads/symbols
.sympath+ c:\localsymbols
.reload –f
bm /a advapi32!CryptAcquireContext*

XmlSerializer and the "Specified" suffix

It took me 3 hours to figure out why XmlSerializer wasn’t writing out a particular class property. This is why:

…if a serializable Field/Property has a corresponding field of type Boolean having as a name the Field/Property name with "Specified" suffix, the XmlSerializer conditionally exclude that Field/Property from the serialization process.

Debugging hybrid VB6/C/C# app crashes with WinDbg

I was troubleshooting one of two (2) different app crashes this past week in which the app simply dies without any prior warning.  At first I thought: crappy VB6! But then, after looking in the Event Log, I found out this was not Visual Basic 6.0 Runtime’s fault, but rather it’s the .NET Runtime version 2.0 Fatal Execution Engine that erred fatally. Below is how I went about debugging the crash.

First of all, two sets of tools are needed:

  1. Debugging Tools for Windows (WinDbg)
  2. Debugging symbol (.pdb) files. These are useful but not essential.   PDB files are generated automatically in Visual Studio .NET, and can be turned on in VB6 IDE via the project properties under the Compile tab.

In using WinDbg to troubleshoot app crashes, I found this blog post Using WinDbg - Hunting Exceptions  by Johan Straarup to be tremendously helpful.

As anyone who’s ever involved in troubleshooting any software bug would know, the hardest part is to reproduce it in a consistent manner, and an app crash is (or should be) the rarest (and most feared by programmers) of bugs. Yet, an app crash is nothing more than an exception that has gone uncaught by the application.

In WinDbg, I used the Attach to a Process menu option to connect to the running app. Then, I issued the gn command (Go [until] Unhandled Exception) command, and let the app run its course.  Eventually, it came a stop with this message:

(4a4.1e4): CLR exception - code e0434f4d (!!! second chance !!!)
eax=0129ecfc ebx=0017d328 ecx=00000000 edx=00000025 esi=0129ed88 edi=e0434f4d
eip=7c812afb esp=0129ecf8 ebp=0129ed4c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
…

I then used “!analyze –v” and subsequently “!pe”, which gave me this:

0:002> !PrintException
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll -
PDB symbol for mscorwks.dll not loaded
Exception object: 019138a0
Exception type: System.IO.FileLoadException
Message: Could not load file or assembly 'Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
InnerException: <none>
StackTrace (generated):
    SP       IP       Function
    00000000 00000001 MyAssembly1.MyClass1.Finalize()

So, this crash was the result of a referenced assembly version mismatch in one of the plugin components. That's one easy problem solved.

The other crash is a bit more elusive, which, after two weeks, I'm still in the process of trying to reproduce.