[SJF Logo]
Steve Friedl's Weblog

December 27, 2003
Tech Tip: Reading C Type Declarations

Almost all C programmers can decode the declaration int *foo[5];, but as the types get more complicated, it gets much harder to just "wing it" when trying to read a type declaration. Just try to decode this one on sight:

char *(*(**foo[8][])())[];
Back in college I started to write a program to parse a declaration and describe it in English, but during the process the "rules" clicked, so I could read them by sight (and never needed to finish the parser).

Every time I teach a C class I have a lesson on how to read arbitrary C type declarations ("How to impress your friends"), and I've finally written it up in a Tech Tip.

Unixwiz.net Tech Tip: Reading C Type Declarations

Posted by Steve at 03:17 PM
December 12, 2003
"Explicit Lyrics"

As I've previously written, I love the MusicMatch RadioMX streaming music service, and as I sit at my chair for at least 12 hours a day, I get more value out of it than most.

Recently they added a $.99 download service, so I've been busily buying up individual tracks right and left. It's a wonderful service.

I checked for my favorite artist, Lao Tizer, and found that his work was available, but all marked with the "[Explicit]" tag. Now I understand that this can be subjectively applied, but in Lao's case, he is an instrumental artist (and a very good one). How does this work?

explicit Lao Tizer

I think a database needs to be updated.

Posted by Steve at 10:57 PM
More fun with OutputDebugString()

Those who haven't nodded off yet might find this an amusing use of a deep knowledge of OutputDebugString(). This is a Win32 interface to a message stream that a program can use to send information to a debugger ("can't open file", "connected to printer", etc.), and it's used by developers to see what's going on in software that's not easy to attach to a debugger.

When running a debug-message receiver, it's common to get bits of random chitchat from unrelated software - it's not uncommon that software is shipped without all the debugging stuff removed - but most of this time this is pretty limited, so it doesn't get in the way.

Enter "Microsoft Digital Rights Management" - when using the MusicMatch Jukebox to play (purchased!) downloaded music, it apparently uses some Microsoft DLLs to make sure that this content doesn't find its way out and about, and it's taken some steps to forestall running a debugger on them. This manifests itself with an absolute deluge of these messages streaming across the debugging monitor, many of them every second:


159c:**********************************************************************************************
159c:This breakpoint is By Design.  You are accessing protected content while running the debugger.
159c:This only occurs in Free builds - either use Checked builds or stop playing protected content.
159c:Hint: turn off protection of CD copied content in Windows Media Player by going to {Tools}{Options...},
159c:clicking the CD Audio tab, and unchecking Enable Personal Rights Management.
159c:**********************************************************************************************
I've found several Microsoft DLLs (including BLACKBOX.DLL) that do this, and it renders the debugging monitor positively useless. The annoying part is that running a debug-message receiver is not the same thing as a debugger, so it's really just entirely spurious.

I have to get my work done, so I am faced with either excluding a dozen pieces of music from my playlist, or Fixing The Problem. I chose the latter, and I was surprised that it took less than an hour to protoype a solution.

As asute readers of my Tech Tip on OutputDebugString may remember, this API function uses a Mutex to gain access to the debugging channel, and if there were some way to NULL that handle out, it might suppress the messages.

It works.

By disassembling KERNEL32.DLL, it was straightforward to find the offset of the Mutex HANDLE (plus a helper variable that said "we couldn't open the mutex, so don't try again"). Using this knowledge, it's possible to OpenProcess() on the MusicMatch process, then write updated values to these variables (NULL for the mutex handle, TRUE for the don't-try-again variable).

These offsets depend precisely on the version of KERNEL32.DLL being used, and even minor variations of this file have substantially different values - it requires reverse engineering on a case-by-case basis.

So now I have a tool that can disable OutputDebugString() for any process, and it's made life much easier. I'm going to release this tool once I have a bit more miles on it, and this includes testing with KERNEL32.DLL version other than 5.0.2195.6794 (the latest in Win2000).

Those who (a) understand this, and (b) could use its functionality should contact me offline to make arrangements for some testing.

Now: it's back to listening to Stevie Nicks and Gypsy - best 99 cents I ever spent.

Posted by Steve at 09:03 PM
December 10, 2003
Tracking down a subtle Win32 bug

On and off for several years, I've run into all kinds of problems with the Win32 function OutputDebugString(), which lets an application send a printable string to a debugger for display. This is a great way for "inaccessible" software - such as those running in a system service - to send debugging messages.

But there has been a long-running, sporadic problem (going back to NT 3.51) where these messages simply get lost, and now that I'm doing my software development under Windows as a non-admin user, it got worse, and it was crippling me on a project. Debugging is hard enough with debugging messages. So I figured it out, and I consider this to be a bug in Windows.

The results of several days of work are two things:

Tech Tip: Understanding Win32 "OutputDebugString"

This gives the background on how OutputDebugString() works, how to use it, and the subtle permissions issues that has been so troubling for so long. It includes a pseudocode for the function reverse engineered from KERNEL32.DLL.

Tool: dbmutex

This is a very small Win32 system service that launches at system boot time, fixes the permissions problem, and goes to sleep until shutdown. During this process it's holding onto a HANDLE to the troublesome Mutex object so the permissions are right every time.

This shouldn't have taken this much work, but at least it's now mainly behind me - now back to real work.

Posted by Steve at 11:21 PM