-
Notifications
You must be signed in to change notification settings - Fork 10
Getting Started
To use the win32-api gem in your code you must first require it like so:
require 'win32/api'
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.
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
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