Initial commit — FuckCapsLock v1

This commit is contained in:
2026-06-30 16:58:13 -07:00
commit b6cb6e0969
13 changed files with 2104 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
bin/
obj/
*.user
*.suo
*.sln.docstates
.vs/
*.csproj.user

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Llama Chile Shop
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

115
Program.cs Normal file
View File

@@ -0,0 +1,115 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32;
static class Program
{
const int WH_KEYBOARD_LL = 13;
const int VK_CAPITAL = 0x14;
delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[StructLayout(LayoutKind.Sequential)]
struct KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
static LowLevelKeyboardProc _proc = HookCallback;
static IntPtr _hookId = IntPtr.Zero;
static NotifyIcon? _trayIcon;
[STAThread]
static void Main()
{
RegisterStartup();
using var mutex = new Mutex(true, @"Global\FuckCapsLock", out var createdNew);
if (!createdNew)
return;
_hookId = SetHook(_proc);
if (_hookId == IntPtr.Zero)
return;
ApplicationConfiguration.Initialize();
using var form = new Form();
form.WindowState = FormWindowState.Minimized;
form.ShowInTaskbar = false;
form.Load += (_, _) => form.Hide();
_trayIcon = new NotifyIcon
{
Icon = SystemIcons.Application,
Text = "FuckCapsLock",
ContextMenuStrip = new ContextMenuStrip()
};
_trayIcon.ContextMenuStrip.Items.Add("Exit", null, (_, _) =>
{
_trayIcon.Visible = false;
Application.Exit();
});
_trayIcon.Visible = true;
Application.Run(form);
UnhookWindowsHookEx(_hookId);
}
static void RegisterStartup()
{
try
{
using var key = Registry.CurrentUser.OpenSubKey(
@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (key is null) return;
var path = Environment.ProcessPath;
if (path is null) return;
var value = path.Contains(' ') ? $"\"{path}\"" : path;
var existing = key.GetValue("FuckCapsLock") as string;
if (!string.Equals(existing, value, StringComparison.OrdinalIgnoreCase))
key.SetValue("FuckCapsLock", value);
}
catch { }
}
static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using var curProcess = Process.GetCurrentProcess();
using var curModule = curProcess.MainModule;
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule!.ModuleName), 0);
}
static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
var hookStruct = Marshal.PtrToStructure<KBDLLHOOKSTRUCT>(lParam);
if (hookStruct.vkCode == VK_CAPITAL)
return (IntPtr)1;
}
return CallNextHookEx(_hookId, nCode, wParam, lParam);
}
}

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
# FuckCapsLock
**Caps Lock is a vestigial organ — this app permanently disables it until you terminate the app.**
A lightweight Windows background utility that hooks the keyboard at the system level and swallows the Caps Lock keypress before it reaches any window. Runs silently in the system tray, auto-starts with Windows, and only stops blocking Caps Lock when you explicitly exit via the tray menu.
## How It Works
FuckCapsLock installs a low-level Windows keyboard hook (`WH_KEYBOARD_LL``SetWindowsHookEx`). Every keypress passes through this hook before any application sees it. The hook inspects the virtual-key code and, if it matches `VK_CAPITAL` (0x14), **returns 1** (blocked) without calling `CallNextHookEx`. All other keys pass through normally.
No driver, no service, no admin rights required. It's a single-user-mode userland hook that runs in your session's context.
## Usage
1. Run `fuckcapslock.exe` — it minimizes to the system tray immediately
2. Caps Lock is now permanently disabled — pressing it does nothing
3. To restore Caps Lock, right-click the tray icon and select **Exit**
4. The app registers itself in `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` for auto-start on next boot
## Build
```bash
dotnet publish -c Release -r win-x64 --self-contained
```
Output: `bin/Release/net10.0/win-x64/publish/fuckcapslock.exe`
A pre-built self-contained exe is also available in the `out/` directory.
## Requirements
- Windows x64 (x86-64 processor)
- No .NET runtime required for the self-contained build
Tested on Windows 11. Should work on Windows 10 and 8 as well.
## System Calls Reference
Every Win32 API and registry call the application makes, for auditability:
| API / Call | Module | Purpose | Risk |
|---|---|---|---|
| `SetWindowsHookEx(WH_KEYBOARD_LL, ...)` | user32.dll | Install low-level keyboard hook | **Blocks only VK_CAPITAL** |
| `UnhookWindowsHookEx(...)` | user32.dll | Remove hook on exit | Cleanup — no data sent |
| `CallNextHookEx(...)` | user32.dll | Pass unchecked keys to next hook | Normal keyboard passthrough |
| `GetModuleHandle(...)` | kernel32.dll | Get module handle for hook install | Standard hook setup |
| `Registry.CurrentUser\...\Run` | Microsoft.Win32 | Register for auto-start on boot | **Writes only its own exe path** |
| `NotifyIcon` | System.Windows.Forms | System tray icon | Visual indicator only — no data |
| `Application.Run(...)` | System.Windows.Forms | Message loop | Keeps process alive |
| `Mutex("Global\FuckCapsLock")` | System.Threading | Prevent duplicate instances | Singleton pattern |
**No network calls, no filesystem reads/writes (beyond registry auto-start), no process injection, no DLL sideloading, no keylogging.** The only key intercepted is Caps Lock (0x14), which is swallowed and never forwarded.
## Background
Caps Lock was designed for typewriters where holding Shift was physically strenuous. On modern keyboards it serves no purpose — it toggles a mode that accidentally inverts case for entire sentences. Every major OS has considered removing it (Apple briefly experimented, Chromebooks replaced it with Search, IBM's Model M had a removable keycap). This utility exists so you don't have to rip the keycap off your laptop.
## License
MIT License — see [LICENSE](LICENSE).
Copyright (c) 2026 Llama Chile Shop

1887
dotnet-install.sh vendored Normal file

File diff suppressed because it is too large Load Diff

12
fuckcapslock.csproj Normal file
View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableWindowsTargeting>True</EnableWindowsTargeting>
</PropertyGroup>
</Project>

BIN
out/D3DCompiler_47_cor3.dll Normal file

Binary file not shown.

BIN
out/PenImc_cor3.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
out/fuckcapslock.exe Normal file

Binary file not shown.

BIN
out/fuckcapslock.pdb Normal file

Binary file not shown.

BIN
out/vcruntime140_cor3.dll Normal file

Binary file not shown.

BIN
out/wpfgfx_cor3.dll Normal file

Binary file not shown.