We're maintaining an old video game that uses a full-screen 256-color graphics mode with DirectDraw. The problem is, some applications running in the background sometimes try to change the system palette while the game is running, which results in corrupted graphics.
We can (sometimes) detect when this happens by processing the WM_PALETTECHANGED message. A few update versions ago we added logging (just log the window title/class/process name), which helped users identify offending applications and close them. MSN Live Messenger was a common culprit.
The problem got worse when we found out that Windows Vista (and 7) does it "by itself". The WM_PALETTECHANGED parameters point towards CSRSS and the desktop window. In Vista, a workaround that often worked was to open any folder (Computer, Documents, etc.) and leave it open while running the game. Sounds ridiculous, but it worked - in most cases. In Windows 7, not even this workaround worked any more. Users found that stopping some services (Windows Update and the indexing service) also resolved the problem on some configurations.
Some time ago I just started trying random things in hope of finding a solution. I found that setting the GDI palette (using Create/SelectPalette) before setting the DirectDraw palette (using IDirectDrawPalette::SetEntries) would restore the palette after it became corrupted (WM_PALETTECHANGED handler). SetSystemPaletteUse and calling SetPalette on the primary surface helped some more. However, there is still perceivable flickering when an application tries to steal the palette, which is especially prominent during fades.
Question: is there a way to get a "real" exclusive palette, which completely disallows other applications changing the Windows palette as long as our game retains focus?
Someone actually found a registry entry fix for this, here:
Look for "scrambled colours" on that page and you'll get to the part with the fix you need.
Since online resources are fleeting, though, here's the full explanation:
Make a new key under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility\" for the program.
If the program you're applying the compatibility for is a 32-bit program, and you're on a 64-bit system (either applying it manually or through a 64-bit program), don't forget to add the "Wow6432Node" between "Software" and "DirectDraw" to compensate for that.
In that key, set these values:
To get the required DirectDraw ID, run the program and then check this registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\MostRecentApplication
Again, if you're on a 64 bit system and the program you're doing this for is a 32-bit one, add the "Wow6432Node" after "Software".
The ID in that key is four bytes. Reverse their order to get the bytes to put in the ID value. 32dd83d5 becomes d5,83,dd,32.