We are going through test passes on some new functionality for our patch build system and ran into a bug in a service I wrote to handle post-reboot commands without requiring an interactive login. The documentation for the SERVICE_STATUS structure for NT Services (a.k.a. Windows Services) states that the SERVICE_ACCEPT_STOP (0x40) is not supported under Windows NT (i.e., Windows NT 4.0).
Typically in Win32 unsupported flags are passively ignored. They are masked out by the bitwise check for the flags of interest with statements like the example below:
if (SERVICE_ACCEPT_STOP != (SERVICE_ACCEPT_STOP & status.dwControlsAccepted)) { return ERROR_INVALID_SERVICE_CONTROL; }
As I found out today, however, the service control codes supported by HandlerEx like SERVICE_ACCEPT_POWEREVENT are indeed not supported. For an NT Service that supports NT4 and newer NT platforms this flag must be set conditionally so that it is only specified for Windows 2000 and newer NT platforms. A check against the current OS version using a backward-compatible API provide the information needed to conditionally set the newer service control codes that are accepted like in the following example:
BOOL IsGteWin2K() { OSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) }; if (GetVersionEx(&osvi)) { return VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && 0x0500 <= (osvi.dwMajorVersion << 8 | osvi.dwMinorVersion); } return FALSE; } // ... SERVICE_STATUS status = { 0 }; status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; if (IsGteWin2K()) { status.dwControlsAccepted |= SERVICE_ACCEPT_POWEREVENT; }
0 comments