Scheduled Windows Hibernating
A. First Edition
This is almost a trivial practice of win32 api. However, I spent a whole night, literally, to implement it.
I listen mp3 player and want to shut down my PC at a setup moment. What's more, I want my PC to hibernate instead of shutting down. Simple? A sort of, but the "privilege" in windows is a bit tricky and the timer is not so easy to use. (Actually there is a "windows" timer which doesn't work properly.)
The only thing I must remember is that the "PHANDLE" or HANDLE* cannot be passed as parameter to "OpenProcessToken". Instead you have to pass &HANDLE. This is really strange thing and drives me crazy for whole night.
E.Further improvement
F.File listing
1. winshut.cpp
file name: winshut.cpp
#include <iostream>
#include <windows.h>
#include <mmsystem.h>
#include <process.h>
//#include <PowrProf.h>
//
using namespace std;
#pragma comment (lib, "winmm.lib")
typedef BOOL (*SetSuspendState_Type)(
BOOL Hibernate,
BOOL ForceCritical,
BOOL DisableWakeEvent
);
void hibernate()
{
HANDLE handle=NULL;
HMODULE hmodule;
TOKEN_PRIVILEGES tp;
//DWORD length;
LUID luid;
SetSuspendState_Type proc;
if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luid))
{
printf("lookup fails\n");
exit(23);
}
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &handle)==0)
{
printf("open process token fails and error code is %d\n", GetLastError());
exit(2);
}
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(handle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)==0)
{
printf("adjust token privileges fails error=%d \n", GetLastError());
exit(5);
}
/*
if (ExitWindowsEx(EWX_POWEROFF, 0)==0)
{
printf("failed and error code is %d\n", GetLastError());
}
*/
if ((hmodule=LoadLibrary("powrprof.dll"))==NULL)
{
printf("load library fails\n");
exit(12);
}
proc=(SetSuspendState_Type)GetProcAddress(hmodule, "SetSuspendState");
proc(TRUE, FALSE, TRUE);
}
void CALLBACK timerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
printf("prepare to hibernating...\n");
//hibernate();
}
LPTIMECALLBACK pTimerProc=timerProc;
int main(int argc, char** argv)
{
UINT delay;
char* myArgs[2];
STARTUPINFO startInfo;
PROCESS_INFORMATION pi;
int hour, minute, second;
if (argc==1)
{
hour=0;
minute=0;
second=3;
}
if (argc>2)
{
sscanf(argv[1], "%d:%d:%d", &hour, &minute, &second);
}
if (argc==3)
{
myArgs[0]=argv[2];
myArgs[1]=NULL;
////////////////////////////
memset(&startInfo, 0, sizeof(STARTUPINFO));
memset(&pi, 0, sizeof(STARTUPINFO));
startInfo.cb=sizeof(STARTUPINFO);
if (CreateProcess(argv[2], NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL,
&startInfo, &pi)==0)
{
printf("create process fails and error=%d\n", GetLastError());
exit(9);
}
}
delay=(hour*3600+minute*60+second)*1000;
if (!timeSetEvent(delay, 0, pTimerProc, 45, TIME_ONESHOT))
{
printf("failed \n");
}
else
{
printf("successful\n");
}
Sleep(delay+5000);
return 0;
}