Enumerate Top Level Windows

This example shows how to use a native function that takes a callback specifying simple input parameters. The callback itself calls a native function which returns a string via its pointer to a character buffer parameter.

The Windows API Unicode function version (MessageBoxW) is explicitly specified to FFI’s attach_function.

Rather than using :string parameter types (as would normally be used with the MessageBoxAASCII version) :buffer_in parameter types are used for Unicode strings. In Ruby-FFI:string means “null terminated C string” where UTF-16 is closer to a binary blob of data that can contain NULL bytes. NOTE: currently Ruby-FFI checks for NULL chars in :string parameters to help avoid NULL byte poisoning attacks from outside string sources.

The Ruby string needs to be encoded to UTF-16LE and have a Unicode string terminator (double NULL)

Move the Mouse

This example shows how to interface with a native function that takes a pointer to a struct which contains an embedded union, both of which are populated before being provided to the native function.

The above FFI code takes a shortcut in the name of saving wiki page space. The actual Windows INPUT struct contains an anonymous union member with MOUSEINPUT, KEYBDINPUT, and HARDWAREINPUT members. As the MOUSEINPUT struct is the largest of these members, we can get away with the hacky InputEventFFI union definition for example purposes.

TODO explain FFI syntax for embedded struct members which is opposite of typical C usage.

Advanced

Bringing windows to the foreground is tricky, since no single call seems to always force it to the foreground.
http://betterlogic.com/roger/?p=2950 describes how.

Note that for windows’ core working you use a @ ffi_convention :stdcall@ but with normal DLL’s it appears you do not see here

Gotcha’s

For all functions that take string arguments, the Windows API provides “short name” macros that expand to function names with a suffix indicating ASCII or Unicode. ASCII versions are suffixed with a “A”, and Unicode versions are suffixed with a “W”. For example, the Windows APIFindWindow function gets defined as either FindWindowA (ASCII) or FindWindowW (Unicode).

Types

DWORD appears to be an :uint (32 bits that is, so :int should work well - NB that MSDN says it is a long-but for MS, long is 32 bits, even in 64 bit architecture)

HWND appears to be a :pointer see this thread for why you should not actually read from the value it points to. You may as well just use a :long or :ulong.