windows provides thin Win32 bindings on top of Magnolia's sys wrappers.
It is intended for:
- resolving and calling
kernel32.dll/ntdll.dll/psapi.dllexports - resolving and calling GUI/system DLL exports like
user32.dll/gdi32.dll - querying process and module handles
- basic virtual memory and remote process memory APIs
All public calls are OS-gated and return structured error objects on non-Windows hosts.
The windows facade is composed of these focused modules:
- windows-constants
- windows-flags
- windows-core
- windows-loader
- windows-kernel
- windows-gdi
- windows-windowing
- windows-net
- windows-registry
windows := import('windows')
Kernel32NtdllPsapiUser32Gdi32Advapi32Shell32Ole32Ws2_32Comctl32WininetD3d9DdrawVulkan1MsvcrtUcrtbaseVcruntime140ActionCenterAclui,AcleditAcppage,AcproxyAdproviderAeinv,AepicAmstreamAdsldp,AdsntAdtschema,Adsldpc,AdsmsextAdhsvcAdvapi32res,AdvpackAeevtsApdsWinhttp,UrlmonCrypt32,Bcrypt,Secur32Comdlg32,Oleaut32Imm32Shlwapi,ShcoreUxTheme,DwmapiVersion,Setupapi,Netapi32Winmm,Avrt,Mmdevapi,DsoundMfplat,Mfreadwrite,MfuuidTaskschd,WevtapiWlanapi,Mpr,Spoolss,Wtsapi32,Rasapi32Msi,Wimgapi,Cabinet,ApphelpWer,Faultrep,Dbghelp,DbgengPdh,Iphlpapi,Wscapi,SensapiNcrypt,Cryptui,Wintrust,SamlibNetshell,Fwpuclnt,Dnsapi,Nlaapi,HttpapiRpcrt4,Srpapi,SxsMsvcirtApiSetPrefix(prefix for ApiSet compatibility stubs likeapi-ms-win-*.dll)D3dx9Prefix(prefix for legacyd3dx9_*.dllhelper DLL family)MsvcpPrefix,VcruntimePrefix,AtlPrefix,MfcPrefix,VcompPrefix
PROCESS_TERMINATEPROCESS_VM_READPROCESS_VM_WRITEPROCESS_VM_OPERATIONPROCESS_QUERY_INFORMATIONPROCESS_QUERY_LIMITED_INFORMATIONPROCESS_ALL_ACCESS
MEM_COMMITMEM_RESERVEMEM_DECOMMITMEM_RELEASE
PAGE_NOACCESSPAGE_READONLYPAGE_READWRITEPAGE_EXECUTEPAGE_EXECUTE_READPAGE_EXECUTE_READWRITE
FORMAT_MESSAGE_IGNORE_INSERTSFORMAT_MESSAGE_FROM_SYSTEMERROR_SUCCESS
AF_INETSOCK_STREAM,SOCK_DGRAMIPPROTO_TCP,IPPROTO_UDPSOCKET_ERROR,INVALID_SOCKETSD_RECEIVE,SD_SEND,SD_BOTH
INTERNET_OPEN_TYPE_PRECONFIGINTERNET_OPEN_TYPE_DIRECTINTERNET_OPEN_TYPE_PROXYINTERNET_DEFAULT_HTTP_PORTINTERNET_DEFAULT_HTTPS_PORTINTERNET_SERVICE_HTTP
HKEY_CLASSES_ROOTHKEY_CURRENT_USERHKEY_LOCAL_MACHINEHKEY_USERSHKEY_CURRENT_CONFIGKEY_QUERY_VALUE,KEY_SET_VALUE,KEY_CREATE_SUB_KEY,KEY_ENUMERATE_SUB_KEYS,KEY_READKEY_WRITEREG_SZ,REG_DWORD,REG_QWORD
CS_VREDRAW,CS_HREDRAWWS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAMEWS_MINIMIZEBOX,WS_MAXIMIZEBOX,WS_VISIBLE,WS_CLIPSIBLINGS,WS_CLIPCHILDREN,WS_OVERLAPPEDWINDOWCW_USEDEFAULTWM_CREATE,WM_DESTROY,WM_PAINT,WM_CLOSE,WM_QUIT,WM_COMMANDSW_HIDE,SW_SHOWPM_NOREMOVE,PM_REMOVEMB_OK,MB_ICONERROR,MB_ICONWARNING,MB_ICONINFORMATIONIDC_ARROW,IDI_APPLICATION
Returns true when the host OS is Windows.
Converts a string to UTF-16 bytes with trailing null terminator (for *W APIs).
Converts a string to ANSI bytes with trailing null terminator.
Builds a 16-bit value commonly used for Winsock version negotiation. Example:
makeWord(2, 2) for Winsock 2.2.
Resolves symbol from kernel32.dll.
Resolves symbol from a specific library.
Calls a resolved proc or address through sys.call.
Resolve + call convenience wrappers for each library.
Loads a DLL by name/path using LoadLibraryW and memoizes the module handle.
Returns:
{type: :ok, handle: <int>, library: <string>}on success{type: :error, ...}on failure
Ensures a DLL is loaded, then resolves a symbol via GetProcAddress.
Returns:
{type: :ok, proc: <int>, handle: <int>, library: <string>, symbol: <string>}{type: :error, ...}
Load + resolve + call helper for arbitrary DLLs.
Dynamic helpers for runtime library families such as msvcp*.dll,
vcruntime*.dll, atl*.dll, mfc*.dll, and vcomp*.dll.
- pass a numeric/variant suffix like
'140'or'140_1'to build names - pass a full filename ending in
.dllto use it directly
Convenience wrappers that route through callIn(...).
This section focuses on practical usage for the expanded Windows surface.
Some DLLs are optional by Windows edition, installed feature, or runtime package. Probe first, then call APIs only when loaded.
windows := import('windows')
probe := windows.loadDll(windows.Taskschd)
if probe.type = :ok {
true -> {
println('taskschd loaded: ' + string(probe.handle))
}
_ -> {
# Commonly 126 when the module is unavailable on this machine.
println('taskschd unavailable: ' + string(probe))
}
}
Use callIn(dll, symbol, args...) for quick one-off calls without creating a
new wrapper.
windows := import('windows')
if windows.isWindows?() {
true -> {
# Beep(DWORD freq, DWORD duration)
beep := windows.callIn(windows.Kernel32, 'Beep', 880, 120)
println(string(beep))
}
}
Use *Dll(suffix) to build a DLL name and *Family(suffix, symbol, args...)
to dispatch through that generated filename.
windows := import('windows')
if windows.isWindows?() {
true -> {
println(windows.msvcpDll('140')) # msvcp140.dll
println(windows.vcruntimeDll('140')) # vcruntime140.dll
println(windows.atlDll('100')) # atl100.dll
println(windows.mfcDll('140')) # mfc140.dll
println(windows.vcompDll('140')) # vcomp140.dll
# Example: ask any runtime family DLL for DllCanUnloadNow when available.
unload := windows.msvcpFamily('140', 'DllCanUnloadNow')
println(string(unload))
}
}
You can also pass a full filename (ending in .dll) as the suffix argument.
Use apiSetDll(contract) for contract name generation and apiSet(...) for
direct call attempts.
windows := import('windows')
name := windows.apiSetDll('file-l1-1-0')
println(name) # api-ms-win-core-file-l1-1-0.dll
probe := windows.loadDll(name)
println(string(probe))
Use d3dx9Dll(suffix) for d3dx9_*.dll names and d3dx9(...) for dispatch.
windows := import('windows')
println(windows.d3dx9Dll('43'))
attempt := windows.d3dx9('43', 'D3DXCheckVersion', 32, 43)
println(string(attempt))
Use sockaddrIn(ip, port) to build a compatible sockaddr_in byte buffer for
connectSocket and bindSocket.
windows := import('windows')
if windows.isWindows?() {
true -> {
wsaData := bits([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
startup := windows.wsaStartup(windows.makeWord(2, 2), addr(wsaData))
if windows.callOk?(startup) {
true -> {
sock := windows.socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP)
sa := windows.sockaddrIn('93.184.216.34', 80)
if sa.type = :ok {
true -> {
conn := windows.connectSocket(sock.r1, sa.ptr, sa.len)
println(string(conn))
}
}
windows.closeSocket(sock.r1)
windows.wsaCleanup()
}
}
}
}
Use internetSimpleGet(url, agent?, chunkSize?) for quick text fetches.
windows := import('windows')
result := windows.internetSimpleGet('https://example.com', 'Magnolia', 4096)
println(string(result))
Use regReadString / regReadDword for reads and regWriteString /
regWriteDword for writes.
windows := import('windows')
if windows.isWindows?() {
true -> {
keyPath := 'Software\\MagnoliaDemo'
writeN := windows.regWriteDword(windows.HKEY_CURRENT_USER, keyPath, 'Counter', 7)
writeS := windows.regWriteString(windows.HKEY_CURRENT_USER, keyPath, 'Label', 'hello')
println(string(writeN))
println(string(writeS))
readN := windows.regReadDword(windows.HKEY_CURRENT_USER, keyPath, 'Counter')
readS := windows.regReadString(windows.HKEY_CURRENT_USER, keyPath, 'Label')
println(string(readN))
println(string(readS))
}
}
For explicitly wrapped libraries (imm32, msvcirt, dnsapi, httpapi,
netapi32, mmdevapi, dbghelp, and many others), usage is always the same:
windows := import('windows')
# ImmGetContext(HWND)
imm := windows.imm32('ImmGetContext', 0)
println(string(imm))
# Example no-arg call through another wrapper
dbg := windows.dbghelp('SymCleanup', 0)
println(string(dbg))
Use this pattern to keep module-specific code small:
- Probe with
loadDll(...)when availability may vary. - Call through the specific wrapper (
dnsapi,taskschd,wlanapi, etc.). - Handle both syscall transport success and API-level result codes.
Core Winsock lifecycle helpers.
Thin socket wrappers over WinSock calls.
Network byte-order and IPv4 conversion helpers.
sockaddrIn returns {type: :ok, buffer, ptr, len} for passing to
connectSocket/bindSocket.
Thin wrappers for high-level HTTP/FTP style network handles.
Returns true when a syscall result is successful and has ERROR_SUCCESS status
(r1 = 0), which is common for Win32 registry functions.
regCreateKeyEx(rootKey, subKey, reserved, className, options, samDesired, securityAttributesPtr, outKeyPtr, dispositionOutPtr)
Thin registry wrappers for opening, creating, querying, setting, and deleting registry values.
Calls RegisterClassExW.
createWindowEx(exStyle, className, windowName, style, x, y, width, height, parent, menu, instance, param)
Calls CreateWindowExW with UTF-16 conversion for class and window names.
Core window lifecycle helpers.
Message-loop helpers. msgPtr should point to a MSG-compatible buffer.
Returns true for a successful syscall result, and also treats some Win32
interop cases with r1 > 0 as truthy.
Returns true when a peek/get call produced no queued message.
Returns true when IsWindow(hwnd) indicates the handle is still valid.
Returns platform-correct MSG struct byte size (48 on 64-bit, 28 on
32-bit targets).
Allocates and returns a zero-initialized MSG-compatible byte buffer.
Runs one non-blocking PeekMessageW loop iteration and returns one of:
{type: :dispatch, detail: ...}when a message was dispatched{type: :idle, detail: ...}when no message was pending{type: :closed}when the window is no longer valid{type: :error, ...}on unexpected call failure
Runs a close-aware PeekMessageW + WaitMessage loop until hwnd closes.
Returns 0 when the window closes, or an error object.
Registers a default top-level WNDCLASSEXW using DefWindowProcW.
This is a convenience helper for Magnolia samples where no custom Oak WNDPROC callback is available.
Convenience helper that creates a visible overlapped top-level window using
CreateWindowExW.
Runs the native win_msg_loop builtin for hwnd on the current thread.
For Win32 UI code, pair this with lock_thread() / unlock_thread() so
window creation and message dispatch stay on the same OS thread.
Common Win32 UI helper calls.
Painting and DC access helpers.
Thin wrappers for common drawing primitives.
Returns Win32 GetLastError() value (or -1 on non-Windows).
Best-effort user-readable message for a Win32 error code via FormatMessageW.
Returns a string on success and ? on failure/non-Windows hosts.
Convenience helper for formatMessage(getLastError()).
Returns GetCurrentProcessId() (or -1 on non-Windows).
Returns GetCurrentProcess() pseudo-handle (or 0 on non-Windows).
Calls GetModuleHandleW.
- pass
?to get the current executable module handle - pass a DLL/module name string to resolve that module
Convenience helper for current executable image base (moduleHandle(?)).
Calls LoadLibraryW.
Calls FreeLibrary.
Calls GetProcAddress.
Wrap OpenProcess and CloseHandle.
Wrap virtual memory management APIs.
Remote-process variants of virtual memory management/query APIs.
Wrap process memory and memory region query APIs.
Little-endian typed integer helpers built on top of memread/memwrite.
windows := import('windows')
if windows.isWindows?() {
true -> {
pid := windows.currentProcessId()
base := windows.imageBase()
println('PID: ' + string(pid))
println('Image base: ' + string(base))
println('Error 2 text: ' + string(windows.formatMessage(2)))
}
_ -> println('windows library is inactive on this host')
}
See samples/windows-window.oak for a runnable window sample.
windows := import('windows')
if windows.isWindows?() {
true -> {
lock_thread()
className := 'MagnoliaWindowClass'
windows.registerDefaultWindowClass(className)
hwnd := windows.createTopLevelWindow(className, 'Magnolia Win32 Window', 800, 480)
if hwnd.type = :ok & hwnd.r1 > 0 {
true -> {
windows.showWindow(hwnd.r1, windows.SW_SHOW)
windows.updateWindow(hwnd.r1)
msgBuf := windows.createMsgBuffer()
windows.runWindowLoopPeek(hwnd.r1, addr(msgBuf))
}
}
unlock_thread()
}
}
See samples/windows-draw.oak for a runnable example that:
- creates a visible top-level window
- draws text + simple shapes using
getDC,textOut,rectangle, andellipse - enters a close-aware
PeekMessage/DispatchMessageloop
See samples/windows-network.oak for a runnable network sample that:
- initializes Winsock with
wsaStartup(makeWord(2, 2), ...) - builds a
sockaddr_instruct viasockaddrIn(ip, port) - performs a simple HTTP GET via
internetSimpleGet(...)
windows := import('windows')
if windows.isWindows?() {
true -> {
wsaData := bits([...])
startup := windows.wsaStartup(windows.makeWord(2, 2), addr(wsaData))
if windows.callOk?(startup) {
true -> {
response := windows.internetSimpleGet('https://example.com', 'Magnolia', 2048)
println(string(response))
windows.wsaCleanup()
}
}
}
}
See samples/windows-registry.oak for a runnable registry sample that:
- reads a known system value with
regReadString(...) - writes and reads back
REG_DWORDandREG_SZvalues underHKEY_CURRENT_USER
windows := import('windows')
if windows.isWindows?() {
true -> {
product := windows.regReadString(
windows.HKEY_LOCAL_MACHINE
'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
'ProductName'
)
println(string(product))
}
}
See samples/windows-dll-bindings.oak for a runnable sample that:
- probes the full explicitly requested DLL set using
loadDll(...) - prints counts of loaded vs failed modules
- classifies
errno = 126as unavailable modules (often SKU/feature-dependent) - prints detailed failures only for non-126 hard errors
See samples/windows-dll-families.oak for a runnable sample that:
- generates
api-ms-win-*.dllnames throughapiSetDll(...) - generates
d3dx9_*.dllnames throughd3dx9Dll(...) - probes those generated names with
loadDll(...)
See samples/windows-d3d9.oak for a runnable D3D9 bootstrap sample that:
- calls
Direct3DCreate9(D3D_SDK_VERSION)throughd3d9(...) - invokes
IDirect3D9COM methods via vtable pointer dispatch - prints adapter count and releases the D3D object
Note: Release can report errno = 31 in this runtime bridge even when the
call path is otherwise valid; the sample reports this as a benign runtime quirk.
registerClassEx(...) is available, but Magnolia currently does not expose a
native callback bridge for passing an Oak function as WNDPROC.
That means custom message handling (for example explicit WM_PAINT handlers)
still requires runtime support beyond the current sysproc/syscall surface.
Use this sequence for stable Win32 window behavior in Magnolia:
- Gate execution with
windows.isWindows?(). - Call
lock_thread()before creating any UI objects. - Register a class (
registerDefaultWindowClass(...)or custom class setup). - Create the window (
createTopLevelWindow(...)orcreateWindowEx(...)). - Show and update the window (
showWindow, thenupdateWindow). - Allocate a
MSGbuffer withcreateMsgBuffer(). - Run a message loop on the same locked thread:
runWindowLoopPeek(hwnd, addr(msgBuf))for close-aware peek/wait flow, orrunWindowLoop(hwnd)for native built-in loop flow.
- Exit loop when closed (
0result for helper loops). - Call
unlock_thread()when UI work is complete.
Common symptoms when steps are skipped:
- Missing
lock_thread(): window can freeze or become non-responsive. - No running message loop: window appears but does not process input/close.
- Loop on a different thread than creation: undefined behavior and stale handles.
- Interop calls are unsafe by nature; validate pointers and sizes.
- A successful syscall-like response can be
:okor:success. - Prefer building higher-level wrappers for application logic.
- On Windows UI code, lock to a single OS thread during create/show/loop flow.