What Each ROM Has
A selection of functions people reach for, checked against the export lists in exports/. A blank cell means the ROM doesn't export it, so a program that calls it won't compile for that version.
| Function | CE 1.0 | CE 2.0 |
|---|---|---|
| Text | ||
wsprintfW | Yes | Yes |
wcslen | Yes | Yes |
wcscpy | Yes | Yes |
wcscmp | Yes | Yes |
_wcsicmp | Yes | Yes |
lstrcmpW | Yes | |
lstrcmpiW | Yes | |
CharUpperW | Yes | |
CharLowerW | Yes | |
towlower | Yes | |
MultiByteToWideChar | Yes | |
WideCharToMultiByte | Yes | |
FormatMessageW | Yes | |
| Dialogs | ||
DialogBoxIndirectParamW | Yes | Yes |
CreateDialogIndirectParamW | Yes | Yes |
GetDlgItem | Yes | Yes |
SetDlgItemTextW | Yes | |
GetDlgItemTextW | Yes | |
SendDlgItemMessageW | Yes | |
SetDlgItemInt | Yes | Yes |
CheckRadioButton | Yes | Yes |
GetOpenFileNameW | Yes | Yes |
GetSaveFileNameW | Yes | Yes |
| Drawing | ||
CreatePen | Yes | |
CreatePenIndirect | Yes | Yes |
CreateSolidBrush | Yes | Yes |
CreatePatternBrush | Yes | |
CreateDIBSection | Yes | Yes |
StretchBlt | Yes | Yes |
TransparentImage | Yes | |
DrawFrameControl | Yes | |
CreateRectRgn | Yes | |
SetROP2 | Yes | |
| Windows and input | ||
LoadCursorW | Yes | |
SetCursor | Yes | Yes |
RegisterWindowMessageW | Yes | |
GetClassLongW | Yes | |
DrawMenuBar | Yes | |
PlaySoundW | Yes | |
sndPlaySoundW | Yes | Yes |
MessageBeep | Yes | Yes |
| Files and system | ||
GetModuleFileNameW | Yes | |
GetTempPathW | Yes | |
GetDiskFreeSpaceExW | Yes | |
GetStoreInformation | Yes | Yes |
CopyFileW | Yes | Yes |
SHCreateShortcut | Yes | Yes |
ShellExecuteEx | Yes | Yes |
GetVersionEx | Yes | Yes |
GetSystemPowerStatusEx | Yes | Yes |
QueryPerformanceCounter | Yes | |
| Processes and threads | ||
CreateProcessW | Yes | Yes |
OpenProcess | Yes | |
GetExitCodeProcess | Yes | |
CreateMutexW | Yes | |
CreateEventW | Yes | Yes |
CreateThread | Yes | Yes |
TerminateThread | Yes | |
| Scheduling and databases | ||
CeRunAppAtTime | Yes | |
PegRunAppAtTime | Yes | Yes |
CeRunAppAtEvent | Yes | |
CeCreateDatabase | Yes | |
CeOpenDatabase | Yes | |
PegCreateDatabase | Yes | Yes |
PegOpenDatabase | Yes | Yes |
Peg where CE 2.0 says Ce: PegOpenDatabase, PegRunAppAtTime. CE 2.0 has both.Microsoft's SDK headers covered some gaps with macros: DialogBoxParamW, and on CE 1.0 SetDlgItemTextW, GetDlgItemTextW and SendDlgItemMessageW, are built from the functions that are exported. Some functions are exported without the W, such as GetVersionEx and FindResource, though they take wide strings. The toolchain's headers accept either name.
What the headers declare
The toolchain's headers are CeGCC's w32api, patched so constants, structures and signatures match Microsoft's CE 1.0 and 2.0 SDKs. windows.h gives the API as the target version has it, with the C runtime's wide string functions and the object store databases. commctrl.h, commdlg.h, winsock.h and the others add their parts. A function the target ROM doesn't export is marked unavailable, so using it is a compile error that names the version.
Not covered: COM and OLE, telephony, drivers and kernel internals, the address book and mail APIs, and ANSI (A) structures. The toolchain's README.md has the full list. For those, check the export list and declare what you need yourself, with WINAPI.
Gotchas
Everything in this book that's different from what you'd expect, in one place.
| Symptom | Cause | Fix |
|---|---|---|
| Greys come out black on CE 1.0 | CE 1.0 uses the low two bits of the red value as the grey | Use RGB(0,0,0), RGB(85,85,85), RGB(170,170,170), RGB(255,255,255) or system colours |
| Controls inside a group box or tab control are invisible | Siblings stack in creation order, first on top, and these paint their insides | Create the group box or tab control after its contents |
| "'Function' is unavailable: not in Windows CE 1.0" | That ROM doesn't export it | Use an alternative, or put it behind #if _WIN32_WCE >= 200 |
| Program crashes reading a struct from a buffer | Unaligned access on MIPS | Copy with memcpy or read bytes |
| Program can't find its files | No current directory, and no GetModuleFileNameW on CE 1.0 | Full paths, a known install folder, or the folder on the command line |
LoadLibraryW(L"mine.dll") fails | Neither version searches the program's folder | Put DLLs in \Windows or use a full path |
| The interface freezes during a download | Blocking socket calls on the interface thread | A worker thread, results by PostMessageW |
| Tap coordinates are huge numbers | LOWORD of a negative coordinate | Cast through short |
Nothing happens after LB_SETCURSEL or similar | Notifications only follow what the user does | Update dependent state yourself |
| Waiting for a started program returns at once on CE 1.0 | A new process's handle reports finished there | Poll for its window instead |
| Italic text looks broken on CE 1.0 | The CE 1.0 ROM's fonts | Use bold and size for emphasis |
| HTTPS fails | No modern TLS on the Velo | Plain HTTP through a proxy |
SetEvent doesn't link | CE has no such export: it's an inline function over EventModify | Use the toolchain's windows.h |
SetWindowLongW(window, GWL_USERDATA, ...) fails on CE 1.0 | CE 1.0 doesn't support GWL_USERDATA | Extra window memory: cbWndExtra and offset 0 |
MultiByteToWideChar(CP_UTF8, ...) fails | CE has no UTF-8 code page | Convert UTF-8 yourself (chapter 5) |
BitBlt fails on CE 1.0 | CE 1.0 only does SRCCOPY, SRCPAINT, SRCAND and SRCINVERT | Stick to those four |
| Dividing by zero gives a strange number | Integer division doesn't trap | Check divisors |
| Program closes silently | It crashed | Run it under GDB, or with --debug-output and velo-symbolize |
Notification Codes
How each control tells its parent something happened.
| Control | Message | Codes |
|---|---|---|
| Button, check box, radio button | WM_COMMAND | BN_CLICKED. Read a check with BM_GETCHECK. |
| Edit | WM_COMMAND | EN_CHANGE after each edit |
| List box | WM_COMMAND | LBN_SELCHANGE, LBN_DBLCLK, both only with LBS_NOTIFY |
| Combo box | WM_COMMAND | CBN_SELCHANGE |
| Menu, accelerator, command bar button | WM_COMMAND | The command ID in LOWORD(wParam) |
| List view | WM_NOTIFY | LVN_ITEMCHANGED, NM_CLICK, NM_DBLCLK, and LVN_ITEMACTIVATE on CE 2.0 |
| Tree view | WM_NOTIFY | TVN_SELCHANGEDW |
| Tab control | WM_NOTIFY | TCN_SELCHANGE |
| Trackbar | WM_HSCROLL | Its handle in lParam |
| Scroll bar on a window | WM_VSCROLL, WM_HSCROLL | SB_LINEUP, SB_PAGEDOWN, SB_THUMBTRACK and the rest in LOWORD(wParam) |
Glossary
- Accelerator
- A shortcut key, mapped to a command ID by an
ACCELERATORSresource. - Command bar
- CE's combined menu bar, toolbar and title bar, at the top of a program's window.
- Common controls
- The controls in
commctrl.dll: list view, tree view, tabs, progress bar, trackbar, up-down, toolbar, status bar. CallInitCommonControlsbefore using them. - Device context (DC)
- A drawing surface with its current font, pen, brush and colours.
HDC. - Dialog units
- The coordinates in dialog resources, which scale with the dialog's font.
- GDI
- The drawing part of Windows: device contexts, fonts, pens, brushes and bitmaps.
- Handle
- An opaque value naming something the system owns:
HWND,HFONT,HANDLE. - Instance
- A loaded program or DLL,
HINSTANCE. Needed to load its resources and register its window classes. - Object store
- CE's storage in battery-backed RAM: the file system, the registry and databases.
- Resource
- Data built into the program from a
.rcfile: menus, dialogs, icons, bitmaps, strings, accelerators. - Window class
- A name plus a window procedure and defaults, registered with
RegisterClassW, that windows are created from. - Window procedure
- The function that handles a window's messages.
_WIN32_WCE- 100 when building for CE 1.0, 200 for CE 2.0.
Further Reading
- Douglas Boling, Programming Microsoft Windows CE (Microsoft Press, 1998). The book on CE programming, written for CE 2.0.
- Microsoft Windows CE Programmer's Guide (Microsoft Press, 1998). Microsoft's reference, with a note on each function about how CE differs from desktop Windows.
- Charles Petzold, Programming Windows, fifth edition (Microsoft Press, 1998). Win32 in depth: messages, GDI, controls and dialogs.
- The toolchain's
README.md, anddebugmgr/PROTOCOL.mdfor the debug manager. - velo-emu's
README.md: the emulator, its proxy, headless options, GDB and the host mailbox. - velo-bluesky's source, for everything in chapters 6 and 7 at full size.
- velo-apps'
installer/library.c, for chapter 8 at full size. - The AT Protocol at atproto.com and Bluesky's API reference at docs.bsky.app.