Skip to content
Hiroshi Hatake edited this page Aug 25, 2016 · 3 revisions

Require the gem

To use the win32-api gem in your code you must first require it like so:

require 'win32/api'

A simple example

To create a Win32::API object, you'll need the name of the function you want to wrap, its prototype, its return type, and the library that exports the function. Let's start with the GetUserName function, which retrieves the name of the user associated with the current Ruby process. First, let's look at the C function declaration:

BOOL WINAPI GetUserName(
  __out    LPTSTR lpBuffer,
  __inout  LPDWORD lpnSize
);

Based on the function declaration above we know that it takes two arguments, a string buffer and a pointer to a DWORD, which we happen to know is an unsigned long. We also happen to know that this function comes from the advapi32 library. Armed with this knowledge, here's how we would wrap that function:

GetUserName = Win32::API.new('GetUserName', 'PP', 'I', 'advapi32')

The first argument to the constructor is a string with the name of the function that you want to wrap. The second argument is a string containing characters that match the function's prototype. Use "P" for pointers (including output buffers), "L" for long data types, "I" for integer data types and "V" for void data types. The third argument is a string that matches the function's return type. It is always a single character. In this case we use "I" (integer) to represent a BOOL since it's either 1 or 0. The final argument is a string with the name of the library that exports the function.

Preparing the input variables

For out GetUserName function we need to create a couple of variables before we call the function. We'll need a string buffer and a long pointer. A string buffer is just what it sounds like, a empty string, filled with "\000", long enough to hold the results. The second is a pointer to a long.

buffer = 0.chr * 32           # A string of "\000" chars
dwptr  = [buffer.size].pack('L') # This effectively gives us a pointer address

Calling the function

To call any Win32::API function use the call method. With our input variables prepared we can call the function:

bool = GetUserName.call(buffer, dwptr)

if bool == 1
  puts "The user's name is: " << buffer.strip # Remove trailing "\000" characters
else
  raise "Oops, the GetUser function failed for some reason."
end

Although it's not really necessary here, we could dereference the dwptr variable as well to get its result, keeping in mind that it will be 1 more than the strength you see because it counts a terminating null character.

puts "Number of chars copied to buffer: " << dwptr.unpack('L').first.to_s
Clone this wiki locally