Initial commit — FuckCapsLock v1
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.sln.docstates
|
||||||
|
.vs/
|
||||||
|
*.csproj.user
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal 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
115
Program.cs
Normal 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
62
README.md
Normal 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
1887
dotnet-install.sh
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
fuckcapslock.csproj
Normal file
12
fuckcapslock.csproj
Normal 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
BIN
out/D3DCompiler_47_cor3.dll
Normal file
Binary file not shown.
BIN
out/PenImc_cor3.dll
Normal file
BIN
out/PenImc_cor3.dll
Normal file
Binary file not shown.
BIN
out/PresentationNative_cor3.dll
Normal file
BIN
out/PresentationNative_cor3.dll
Normal file
Binary file not shown.
BIN
out/fuckcapslock.exe
Normal file
BIN
out/fuckcapslock.exe
Normal file
Binary file not shown.
BIN
out/fuckcapslock.pdb
Normal file
BIN
out/fuckcapslock.pdb
Normal file
Binary file not shown.
BIN
out/vcruntime140_cor3.dll
Normal file
BIN
out/vcruntime140_cor3.dll
Normal file
Binary file not shown.
BIN
out/wpfgfx_cor3.dll
Normal file
BIN
out/wpfgfx_cor3.dll
Normal file
Binary file not shown.
Reference in New Issue
Block a user