At work the other day we had a report from a client that the latest version of our software was not working on new Vista machines. Ingeniously, the customer managed to discover that if they initially launched the program with elevated (administrator) access then subsequent executions of  the program would work un-elevated.

Just yestarday I managed to duplicate these symptoms in my development environment and discovered that the problem was being triggered in the InitSetEventOffset ROUTINE of the Debuger class we are using.

You can download the class over at Radfusion Free Downloads.

The helpful folk over at the clarion skype chat were able to narrow this down to a problem with the length of the CSTRING used in the call to DebugerNameMessage.

Further analysis shows that this only manifests as an issue under very specific circumstances:

  • The class instance is created using New().
  • The application is compiled with debug mode set to “off” (or in other words, in “release” mode).
  • The application is run “asInvoker” on a system with UAC tuned ON.
  • There is no “EventOffset” entry already in the WIN.INI file*.

* That last point will depend on the version of the debuger class you are using. The one we have here is “6.0.2” but there are others around that no longer use WIN.INI and they might work OK. Note though that when I say “OK” the problem hasn’t gone away and you will still see the APPCRASH error the first time your program is run but subsequent executions will be able to read the offset from the INI file and this bypasses this bug.

Changing the variable from CSTRING(20) to CSTRING(128) fixed the problem (Thanks Larry!) but I was still curious to find out what the cause was.

First lets look at the prototype forDebugerNameMessage :

And it’s usage:

(I have removed all the other code from the above method just for clarity in this example)

The call to DebugerNameMessage crashed just after giving this result:

When the LOC:RetVal is changed to CSTRING(128) we see that the next call is this:

The reason for the crash I guess is Len(WM_OTHERWINDOWDESTROY) > 20

There are 2 questions remaining and I think I have the answer for one:

Why does it only crash when the class is instantiated with New()?

I am pretty sure this simply because when using New() the “EventOffset” is different and so the InitSetEventOffset routine attempts to find the correct offset and thus triggering the problem with our too small variable.

Why does it only happen when the program is compile with debugging turned OFF?

I guess in debug mode the code it is not so sensitive about the buffer overrun it still seems kind of strange that it should work at all.

Hopefully someone reading this will be able to give a hint as to a possible reason?