Thanks for the responses, and sorry for the late reply (real life has been limiting my hacking time...)
glXMakeCurrent(default_display, None, NULL)
If you could do a non-wine test case for that and see if it's just a buggy driver, that'd be good.
It turns out not to be as simple as that. I did a +opengl trace and the game makes the same call without any problem several times before the crash. So it must be something to do with the context whether it crashes or not.
Good catch! I have not seen any references to this flag in my voyages over the code, so it's possible we are indeed clobbering this flag somewhere - it may even be implicit via gcc. If you can trace the point at which it's being reset we might be able to special case this.
It's difficult to trace properly as PECrypt has debugger detection and behaves oddly if it detects breakpoints or whatever. But I narrowed it down to 3 Wine calls in the critical loop: SetEvent, WaitForSingleObject and ResetEvent. I tried wrapping each of these functions with __asm__("pushfl\n"); at the start and __asm__("popfl\n"); at the end to preserve the flags - with this, PECrypt works fine and the game gets as far as trying to initialise DirectX. Not exactly a neat fix though.
I never did trace exactly where the flag was getting clobbered, but I disassembled some basic libc functions and found that memcpy and memset both clear the direction flag. So it could be happening almost anywhere - looks like it is standard practise in UNIX to clobber this flag.
Cheers, James