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