M-A's

technology blog

Sunday 13 January 2008

The undocumented frustration

I had some frustration when updating WINVER and _WIN32_WINNT from 0x501 to 0600 (okay we're late but better be late than sorry). I came across two things I'd like to document.

---

First I need to reference Nicolas Sylvain post about GENERIC_MAPPING changes to give some background. Then all I have to say is that there are other access masks that changed, but explicitly. The ones we hit were PROCESS_ALL_ACCESS and THREAD_ALL_ACCESS. They have a new bitmask. Here are the definition:
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
#else
#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
#endif

#if (NTDDI_VERSION >= NTDDI_LONGHORN)
#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
#else
#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
#endif
The nice thing is that the new bitmasks are refused by Windows XP. So you need to use different flags depending on the OS, which you need to define yourself. Not great! The easiest work around is to use MAXIMUM_ALLOWED but this is not always what you want.

---

The second one is nasty. The NONCLIENTMETRICS structure's size silently changed between XP and Vista. Here is the definition:
typedef struct tagNONCLIENTMETRICSW
{
UINT cbSize;
int iBorderWidth;
int iScrollWidth;
int iScrollHeight;
int iCaptionWidth;
int iCaptionHeight;
LOGFONTW lfCaptionFont;
int iSmCaptionWidth;
int iSmCaptionHeight;
LOGFONTW lfSmCaptionFont;
int iMenuWidth;
int iMenuHeight;
LOGFONTW lfMenuFont;
LOGFONTW lfStatusFont;
LOGFONTW lfMessageFont;
#if(WINVER >= 0x0600)
int iPaddedBorderWidth;
#endif /* WINVER >= 0x0600 */
} NONCLIENTMETRICSW, *PNONCLIENTMETRICSW, FAR* LPNONCLIENTMETRICSW;

WTL 8.0 has a workaround for this
but let's face it, it looks more as a hack than anything else. It looks like the guy at Microsoft that changed the structure should have wrote a unit test...
Anything that is written that looks like this is bound to fail:
NONCLIENTMETRICS cm = { sizeof(NONCLIENTMETRICS) };
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &cm, 0);
I don't blame Microsoft for doing small errors like this. Managing an operating system is a tremendous task and we all know errors can slip through. The real problem I see is that even one year after the release, it's still not documented. Let's hope the Vista SP1 SDK will define PROCESS_ALL_ACCESS_XP, THREAD_ALL_ACCESS_XP and NONCLIENTMETRICS_v1.

No comments: