/*
* Stall Shutdown ver 1.0 - Shutdown any windows computer after a user
* specified amount of time, coded so I could watch
* family guy in bed and not have to get out again to
* turn my computer off. Should compile first time in
* Bloodshed Dev-C++ 4.9.9.2
*
* Feel free to use this code for anything you want, just don't pass it off as your own.
*
* If you have any questions/comments, drop me a line,
* Cheers
*
* Author: Matt. "Dirty Monkey" Stevens
* Circa: 15/08/08 16:34
* Contact: matt@DirtyMonkey.co.uk
* Website: www.DirtyMonkey.co.uk
*/
#include <windows.h>
#include <time.h>
#include "resource.h"
#define ID_EDIT_SECS 1 /* seconds input */
#define ID_EDIT_MINS 2 /* minutes input */
#define ID_EDIT_LEFT 3 /* time left display */
#define ID_EDIT_TIME 4 /* current status display */
#define ID_EDIT_STATUS 5 /* current time display */
#define ID_BUTTON 6 /* Start!/Abort! button */
#define ID_RAD_BUTTON_1 7 /* seconds radio button */
#define ID_RAD_BUTTON_2 8 /* minutes radio button */
/* prototypes */
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
int CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
/* Make the class name into a global variable */
char szClassName[] = "WindowsApp";
HINSTANCE global_instance;
NOTIFYICONDATA structNID;
HICON hMainIcon;
HMENU hPopMenu;
HWND hwndEdit1, hwndEdit2, hwndEdit3,
hwndEdit4, hwndEdit5, hwndButton,
hwndRad1, hwndRad2, hwndForce;
int WINAPI WinMain(HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
global_instance = hThisInstance; /* now we can use this everywhere */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.hIcon = LoadIcon(hThisInstance, MAKEINTRESOURCE(ID_MYICON));
wincl.hIconSm = LoadIcon(hThisInstance, MAKEINTRESOURCE(ID_MYICON));
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = MAKEINTRESOURCE(ID_MYMENU);
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) (COLOR_3DFACE+1);
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx(&wincl)) return(0);
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx(
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Stall Shutdown ver 1.0", /* Title Text */
WS_MINIMIZEBOX | WS_SYSMENU, /* a standard window with no maximize button */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
304, /* The programs width */
235, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
hMainIcon = LoadIcon(hThisInstance,(LPCTSTR) MAKEINTRESOURCE(ID_MYICON));
structNID.cbSize = sizeof(NOTIFYICONDATA);
structNID.hWnd = (HWND) hwnd;
structNID.uID = ID_MYICON;
structNID.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
strcpy(structNID.szTip, "Stall Shutdown - by Matt. Stevens");
structNID.hIcon = hMainIcon;
structNID.uCallbackMessage = WM_USER_SHELLICON;
/* put icon into the systray */
Shell_NotifyIcon(NIM_ADD, &structNID);
/* Make the window visible on the screen */
ShowWindow(hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage(&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return(messages.wParam);
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int flag = 0; /* the current state of the button */
static int seconds; /* time used in the 'Time left' edit control */
char countdown_buffer[10]; /* holds the string to send to countdown */
POINT lpClickPoint; /* location of mouse over systray icon */
HFONT font, font2; /* fonts for the controls */
time_t lt = time(NULL); /* stores the value returned by time() */
struct tm *ptr = localtime(<); /* stores data and time information */
char ascii_time[28];
switch (message)
{
/* deals with messages from the icon in the systray */
case WM_USER_SHELLICON:
switch(LOWORD(lParam))
{
case WM_LBUTTONDBLCLK: /* open the window */
ShowWindow(hwnd, SW_NORMAL);
return(1);
case WM_RBUTTONDOWN: /* open the menu */
GetCursorPos(&lpClickPoint);
/* place the window/menu there if needed */
hPopMenu = CreatePopupMenu();
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, ID_EXIT, "&Exit");
SetForegroundWindow(hwnd);
TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN,
lpClickPoint.x, lpClickPoint.y, 0, hwnd, NULL);
SendMessage(hwnd, WM_NULL, 0, 0);
return(1);
}
break;
case WM_CREATE:
{
/* set timer up for the time control */
SetTimer(hwnd, 1, 1000, NULL);
CreateWindow("BUTTON", "Shutdown in...", WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
5, /* X Position */
5, /* Y Position */
165, /* X Width */
70, /* Y Height */
hwnd, (HMENU) 200, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
CreateWindow("BUTTON", "Time left", WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
175, /* X Position */
5, /* Y Position */
115, /* X Width */
70, /* Y Height */
hwnd, (HMENU) 201, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
CreateWindow("BUTTON", "Status", WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
5, /* X Position */
80, /* Y Position */
165, /* X Width */
45, /* Y Height */
hwnd, (HMENU) 202, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
CreateWindow("BUTTON", "Current Time", WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
5, /* X Position */
130, /* Y Position */
165, /* X Width */
45, /* Y Height */
hwnd, (HMENU) 203, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndEdit1 = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | ES_NUMBER,
15, /* X Position */
25, /* Y Position */
60, /* X Width */
20, /* Y Height */
hwnd, (HMENU) ID_EDIT_SECS, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndEdit2 = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | ES_NUMBER,
100, /* X Position */
25, /* Y Position */
60, /* X Width */
20, /* Y Height */
hwnd, (HMENU) ID_EDIT_MINS, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndEdit3 = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_CENTER | ES_AUTOHSCROLL | WS_TABSTOP,
185, /* X Position */
25, /* Y Position */
95, /* X Width */
20, /* Y Height */
hwnd, (HMENU) ID_EDIT_LEFT, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndEdit4 = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP,
15, /* X Position */
98, /* Y Position */
145, /* X Width */
20, /* Y Height */
hwnd, (HMENU) ID_EDIT_STATUS, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndEdit5 = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP,
15, /* X Position */
148, /* Y Position */
145, /* X Width */
20, /* Y Height */
hwnd, (HMENU) ID_EDIT_TIME, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndForce = CreateWindow("BUTTON", "Force Shutdown",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
180, /* X Position */
90, /* Y Position */
105, /* X Width */
15, /* Y Height */
hwnd, (HMENU) 204, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndButton = CreateWindow("BUTTON", "Start!", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
180, /* X Position */
120, /* Y Position */
100, /* X Width */
50, /* Y Height */
hwnd, (HMENU) ID_BUTTON, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
CreateWindow("STATIC", "seconds", WS_CHILD | WS_VISIBLE,
215, /* X Position */
50, /* Y Position */
60, /* X Width */
20, /* Y Height */
hwnd, (HMENU) 205, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndRad1 = CreateWindow("BUTTON", "seconds", WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
15, /* X Position */
50, /* Y Position */
60, /* X Width */
18, /* Y Height */
hwnd, (HMENU) ID_RAD_BUTTON_1, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
hwndRad2 = CreateWindow("BUTTON", "minutes", WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
100, /* X Position */
50, /* Y Position */
60, /* X Width */
18, /* Y Height */
hwnd, (HMENU) ID_RAD_BUTTON_2, ((LPCREATESTRUCT) lParam)->hInstance, NULL);
/* disable edit boxes that don't require user input */
EnableWindow(hwndEdit3, FALSE);
EnableWindow(hwndEdit4, FALSE);
EnableWindow(hwndEdit5, FALSE);
/* create a custom font for our controls */
font = CreateFont(15, 0, 0, 0, 550, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
font2 = CreateFont(13, 0, 0, 0, 550, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
/* set the fonts for the controls */
SendDlgItemMessage(hwnd, ID_RAD_BUTTON_1, WM_SETFONT, (WPARAM)font2, TRUE);
SendDlgItemMessage(hwnd, ID_RAD_BUTTON_2, WM_SETFONT, (WPARAM)font2, TRUE);
SendDlgItemMessage(hwnd, ID_EDIT_SECS, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, ID_EDIT_MINS, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, ID_EDIT_LEFT, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, ID_EDIT_TIME, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, ID_EDIT_STATUS, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, 200, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, 201, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, 202, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, 203, WM_SETFONT, (WPARAM)font, TRUE);
SendDlgItemMessage(hwnd, 204, WM_SETFONT, (WPARAM)font2, TRUE);
SendDlgItemMessage(hwnd, 205, WM_SETFONT, (WPARAM)font2, TRUE);
/* formats time into a string */
strftime(ascii_time, 28, "%c", ptr);
/* control settings on startup */
SetWindowText(hwndEdit5, ascii_time);
SetWindowText(hwndEdit4, "Halted...");
SetWindowText(hwndEdit1, "60");
SetWindowText(hwndEdit2, "60");
SetWindowText(hwndEdit3, "60");
SendMessage(hwndRad1, BM_SETCHECK, TRUE, 0);
EnableWindow(hwndEdit2, FALSE);
break;
}
/* we use two timers, one for the clock and one for the countdown */
case WM_TIMER:
{
switch (wParam)
{
/* for updating the time edit control */
case 1:
{
lt = time(NULL);
ptr = localtime(<);
/* formats time into a string */
strftime(ascii_time, 28, "%c", ptr);
/* change the current time text */
SetWindowText(hwndEdit5, ascii_time);
break;
}
/* for the countdown */
case 2:
{
/* start button has been pressed so countdown commences */
if (flag == 1) {
seconds = GetDlgItemInt(hwnd, ID_EDIT_LEFT, 0, FALSE);
/* sound effects for the last 5 seconds */
if (seconds <= 6 && seconds != 0) {
PlaySound(MAKEINTRESOURCE(ID_BEEP), global_instance, SND_RESOURCE | SND_ASYNC);
}
switch (seconds)
{
case 11: /* fall through */
case 10: /* fall through */
case 9: /* fall through */
case 8: /* fall through */
case 7: /* fall through */
SetWindowText(hwndEdit4, "Shutdown Soon!");
break;
case 6:
SetWindowText(hwndEdit4, "Five!");
break;
case 5:
SetWindowText(hwndEdit4, "Four!");
break;
case 4:
SetWindowText(hwndEdit4, "Three!");
break;
case 3:
SetWindowText(hwndEdit4, "Two!");
break;
case 2:
SetWindowText(hwndEdit4, "One!");
break;
case 1:
SetWindowText(hwndEdit4, "Shutdown Now!");
break;
default:
break;
}
if (seconds == 0) {
/* stops the shutdown code from being executed more than once */
KillTimer(hwnd, 2);
/* begin: shutdown code */
TOKEN_PRIVILEGES tkp;
HANDLE hToken;
/* get the token for this process */
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
/* set this privilege to enabled. otherwise it would disable it */
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
/* force shutdown button checked? */
if (SendMessage(hwndForce, BM_GETCHECK, 0, 0) == BST_CHECKED) {
ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0);
/* normal shutdown */
} else {
ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF | EWX_FORCE, 0);
}
/* end: shutdown code */
}
/* stops the counter from going below zero */
if (seconds != 0) seconds--;
sprintf(countdown_buffer, "%i", seconds);
SetWindowText(hwndEdit3, countdown_buffer);
}
break;
}
}
break;
}
case WM_COMMAND:
switch (LOWORD (wParam)) {
case ID_RAD_BUTTON_1:
{
EnableWindow(hwndEdit2, FALSE);
EnableWindow(hwndEdit1, TRUE);
break;
}
case ID_RAD_BUTTON_2:
{
EnableWindow(hwndEdit1, FALSE);
EnableWindow(hwndEdit2, TRUE);
break;
}
/* when the 'Start!' button is pressed a lot of controls */
/* are disabled and changed, this code deals with that */
case ID_BUTTON:
{
/* changes the flag state */
flag ^= 1;
/* 'Start!' has been pressed */
if (flag) {
SetTimer(hwnd, 2, 1000, NULL);
SetWindowText(hwndButton, "Abort!");
SetWindowText(hwndEdit4, "Counting Down...");
EnableWindow(hwndEdit1, FALSE);
EnableWindow(hwndEdit2, FALSE);
EnableWindow(hwndRad1, FALSE);
EnableWindow(hwndRad2, FALSE);
EnableWindow(hwndForce, FALSE);
/* sets the countdown edit control to the right time */
/* the first radio button is checked, so it's seconds */
if (SendMessage(hwndRad1, BM_GETCHECK, 0, 0) == BST_CHECKED) {
seconds = GetDlgItemInt(hwnd, ID_EDIT_SECS, 0, FALSE);
sprintf(countdown_buffer, "%i", seconds);
SetWindowText(hwndEdit3, countdown_buffer);
/* the second radio button is checked, so convert the */
/* minutes into seconds and put result in countdown */
} else {
seconds = GetDlgItemInt(hwnd, ID_EDIT_MINS, 0, FALSE);
sprintf(countdown_buffer, "%i", seconds*60);
SetWindowText(hwndEdit3, countdown_buffer);
}
/* 'Abort!' has been pressed */
} else {
KillTimer(hwnd, 2);
SetWindowText(hwndButton, "Start!");
SetWindowText(hwndEdit4, "Halted...");
EnableWindow(hwndRad1, TRUE);
EnableWindow(hwndRad2, TRUE);
EnableWindow(hwndForce, TRUE);
/* stops both time entry fields from being activated */
if (SendMessage(hwndRad1, BM_GETCHECK, 0, 0) == BST_CHECKED) {
EnableWindow(hwndEdit1, TRUE);
} else {
EnableWindow(hwndEdit2, TRUE);
}
}
break;
}
case ID_EXIT:
/* send a quit message to close the program */
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_ABOUT:
/* launch the about dialog box */
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(ABOUT_DIALOG), hwnd, DlgProc);
break;
}
break;
/* hide window on minimize */
case WM_SYSCOMMAND:
if (SC_MINIMIZE == wParam) {
ShowWindow(hwnd, SW_HIDE);
return(1);
}
break;
case WM_CLOSE:
/* remove the icon from system tray */
Shell_NotifyIcon(NIM_DELETE, &structNID);
DestroyWindow(hwnd);
PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/* handles messages from the 'About' dialog box */
int CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
return(TRUE);
case WM_COMMAND:
switch(LOWORD(wParam))
{
case WM_DESTROY:
case ID_ABOUT_OK:
EndDialog(hwnd, ID_ABOUT_OK);
break;
}
break;
default:
return(FALSE);
}
return(TRUE);
}