A tiny Windows 9x–style desktop that runs real Win32 C applications compiled to WebAssembly — by its own small lcc-wasm toolchain, with no Emscripten. The window manager is DOM-based, GDI is a <canvas> facade, and you can edit, compile and run C apps from inside the browser.
winweb.webm
Opening Minesweeper, then opening a program's source, compiling a hello-world and running it — all in the browser.
Every program is real Win32 C (written with WinMain / RegisterClass / a message loop / GDI), compiled to standalone wasm:
- Minesweeper — the classic, on
WM_PAINT/BitBlt/DrawEdge - Notepad — edits files on the virtual
C: - Command Prompt (
cmd) —cd/dir/type, runs programs by name - cc / msbuild — the C compiler & project builder… in the browser
- IconsDemo, greet (a console app), Hello
System libraries are real files too: C:\Windows\System32\{user32,gdi32,kernel32}.wasm. Apps import Win32 functions from them; those wasm "DLLs" forward to the JS facade. The call chain is honest: app.wasm → user32.wasm → JS.
Requires Node 18+ and Yarn.
yarn install
yarn dev # dev server at http://localhost:5050 (uses the committed pre-built wasm)
yarn build # production build -> dist/Recompile the bundled C apps to wasm (needs clang, used only as the C preprocessor):
yarn build:wasm # compiles src/cdrive/Projects/*.vcxproj via lcc-wasm -> public/cdrive/...Deploy under a sub-path (e.g. a blog at /demo/winweb/):
WINWEB_BASE=/demo/winweb/ yarn buildCreate a project under src/cdrive/Projects/<App>/:
<App>.c— standard Win32 C (WinMainfor a GUI app,mainfor a console one)<App>.vcxproj— a minimal MSBuild-style descriptor (name, console/GUI subsystem, optional icon)
then yarn build:wasm — or build it from inside the running desktop with msbuild <App> in cmd.
- Compiler. lcc-wasm — the LCC C compiler retargeted to WebAssembly and then compiled to wasm itself (
rcc.wasm, ~280 KB). It compiles C89 straight to wasm, both under Node (the build) and in the browser (cc/msbuild). No Emscripten, no LLVM. See the companion write-up. - Standalone modules. Each app exports its own memory + function table, so two instances run fully independently.
- Windowing. A DOM window manager (each window is a
<div>with a title bar, menu and taskbar button).CreateWindowEx/RegisterClass/GetMessage/DispatchMessagedrive real messages (WM_PAINT,WM_COMMAND,WM_TIMER,WM_SIZE). - GDI.
Rectangle,TextOut,CreateFontW,BitBlt, … rendered onto<canvas>. - Filesystem. A virtual
C:on IndexedDB, seeded from a generated manifest; case-insensitive; persists your edits and in-browser builds.
TypeScript · Vite · WebAssembly · LCC (via lcc-wasm)