I've hit this issue too.
My embedded USB read-only mass-storage project watches the SCSI commands from the host. With Mac OS X (10.5): on plug-in the OS X driver tells the device, quite nicely, to prevent removal of the media (SCSI command PREVENT/ALLOW MEDIUM REMOVAL). My device accepts this command. Later, when the user signals that the device should be ejected, OS X, again quite nicely, sends PREVENT/ALLOW REMOVAL again with the ALLOW flag, then sends SCSI START/STOP indicating stop (or eject, can't remember). Beautiful.
Windows XP, however, appears simply to stop sending the SCSI command TEST UNIT READY. I've watched; "safely remove hardware" sends no SCSI signal whatsoever, it just causes the TEST UNIT READY signal to stop coming, which it had been doing every second or so. Basically Windows just clams up.
A TEST UNIT READY timeout could work with Windows but it is a lousy way to detect a device stop condition. Plus it won't work with OS X since OS X is not pinging my device every second like Windows is; I'd get a false positive.
UPDATE 15 NOVEMBER 2009
Sondergaard here reporting back.
A great deal depends on whether the device response to the USB Mass-Storage-Class SCSI "Inquiry" command self identifies as "removable" or "fixed".
If the flag says removable, the only way I could tell if the Windows XP user has "stopped" my device is that the test-unit-ready commands quit coming every second. If the flag doesn't say removable, there is no regular stream of test-unit-ready commands. USB suspend could not be counted on either, in about 1/4 of my tests "safely remove" did NOT send USB suspend. No idea why it wasn't consistent. So if you want to be sure, best recommendation I can make for compatibility with WINDOWS XP ONLY is to respond to INQUIRY as "removable", look for regular TEST UNIT READY commands, and then when they cease consider yourself safely removed.
OS X (10.6) is a different story. As I wrote above, it is much more polite. It sends SCSI START/STOP to spin up or spin down the device, sometimes all on its own with no user input. But that means if you interpret STOP as saying the user is through, and disconnect in any sort of ugly way internal to your device, OS X can get very confused when it tries to spin the disk up again. If your device is marked as removable, OS X will send an ALLOW REMOVAL command before the STOP (or was it EJECT in this case?), that would be a pretty good sign that it's through.
I didn't exhaustively try different configurations. My application is read-only with two partitions, and has to identify as NON removable because Windows XP refuses to acknowledge more than one partition for removable USB drives (OS X has no problem either way). So most of my testing was in this configuration.
Hope this helps.