One of the first things I do when I get a new desktop machine or install a new build of Windows is to map the Sleep button on my keyboard to hibernate instead of suspend. Hibernate makes more sense for these machines because they will never run on batteries and I want them to be truly off ;). This worked out great because I have a bunch of first generation Microsft USB keyboards (they are off white with a row of blue buttons across the top and a normal extended key layout). I got really, really used to this. I would just hit the sleep key, the machine would hibernate and I could walk away. No start menu, no mouse, just a simple key press.

Well, my keyboard at home broke and I bought a Microsoft Natural Ergonomic Keyboard 4000 to replace it. Works great...but there is no Sleep key on the keyboard! Ergh. So, instead I figured I would map one of the five customizable keys (which meant I had to run IntelliType as well...<sigh>) to an application which would hibernate the machine for me. I thought it would be obvious, but it wasn't.

In the end, the program is quite short, but figuring out the magic user mode incantations was hard for a kernel curmudgeon like me. Anyways, here is the app I wrote to get a machine to hibernate and return my ability to put hibernate machine with a single keypress. All it does is adjust the process's token to enable SE_SHUTDOWN_NAME and then call SetSystemPowerState(). Simple as it is, I am proud of it ;).

    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif //  WIN32_LEAN_AND_MEAN

    #include <windows.h>
    #include <stdio.h>

    BOOL
    SetPrivilege(
        HANDLE hToken,          // access token handle
        LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
        BOOL bEnablePrivilege   // to enable or disable privilege
        )
    {
        TOKEN_PRIVILEGES tp;
        LUID luid;

        if (!LookupPrivilegeValue(NULL,            // lookup privilege on local system
                                  lpszPrivilege,   // privilege to lookup
                                  &luid)) {        // receives LUID of privilege
            printf("LookupPrivilegeValue error: %u\n", GetLastError() );
            return FALSE;
        }

        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        if (bEnablePrivilege) {
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        }
        else {
            tp.Privileges[0].Attributes = 0;
        }

        //
        // Enable the privilege or disable all privileges.
        //
        if (!AdjustTokenPrivileges(hToken,
                                   FALSE,
                                   &tp,
                                   sizeof(TOKEN_PRIVILEGES),
                                   (PTOKEN_PRIVILEGES) NULL,
                                   (PDWORD) NULL)) {
            printf("AdjustTokenPrivileges error: %d / 0x%x\n",
                   GetLastError(), GetLastError() );
            return FALSE;
        }

        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
            printf("The token does not have the specified privilege.\n");
            return FALSE;
        }

        return TRUE;
    }

    int __cdecl main()
    {
        HANDLE hToken;

        if (!OpenProcessToken(GetCurrentProcess(),
                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                              &hToken))  {
            printf("open failed %d / 0x%x\n", GetLastError(), GetLastError());
            return FALSE;
        }

        if (SetPrivilege(hToken,
                         SE_SHUTDOWN_NAME,
                         TRUE)) {
            if (SetSystemPowerState(FALSE, TRUE) == FALSE) {
                printf("failed %d / 0x%x\n", GetLastError(), GetLastError());
            }
        }
        else {
            printf("set failed %d / 0x%x\n", GetLastError(), GetLastError());
        }

        return 0;
    }