In Files

Parent

Methods

Win32::API

Constants

VERSION

The version of the win32-api library

Attributes

dll_name[R]

The name of the DLL that exports the API function

function_name[R]

The name of the function passed to the constructor

effective_function_name[R]

The name of the actual function that is returned by the constructor.

   For example, if you passed 'GetUserName' to the constructor, then the
   effective function name would be either 'GetUserNameA' or 'GetUserNameW'.
   
prototype[R]

The prototype, returned as an array of characters

return_type[R]

The return type, returned as a single character, S, P, L, I, V or B

Public Class Methods

new(function, prototype='V', return='L', dll='kernel32') click to toggle source

Creates and returns a new Win32::API object. The function is the name of the Windows function.

The prototype is the function prototype for function. This can be a string or an array of characters. The possible valid characters are ‘I’ (integer), ‘L’ (long), ‘V’ (void), ‘P’ (pointer), ‘K’ (callback) or ‘S’ (string).

The default is void (‘V’).

Constant (const char*) strings should use ‘S’. Pass by reference string buffers should use ‘P’. The former is faster, but cannot be modified.

The return argument is the return type for the function. The valid characters are the same as for the prototype. The default is ‘L’ (long).

The dll is the name of the DLL file that the function is exported from. The default is ‘kernel32’.

If the function cannot be found then an API::Error is raised (a subclass of RuntimeError).

Example:

   require 'win32/api'
   include Win32

   buf = 0.chr * 260
   len = [buf.length].pack('L')

   GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
   GetUserName.call(buf, len)

   puts buf.strip
static VALUE api_init(int argc, VALUE* argv, VALUE self)
{
   HMODULE hLibrary;
   FARPROC fProc;
   Win32API* ptr;
   int i;
   const char* first  = "A";
   const char* second = "W";
   VALUE v_proc, v_proto, v_return, v_dll;

   rb_scan_args(argc, argv, "13", &v_proc, &v_proto, &v_return, &v_dll);

   Data_Get_Struct(self, Win32API, ptr);

   // Convert a string prototype to an array of characters
   if(rb_respond_to(v_proto, rb_intern("split")))
      v_proto = rb_str_split(v_proto, "");

   // Convert a nil or empty prototype to 'V' (void) automatically
   if(NIL_P(v_proto) || RARRAY_LEN(v_proto) == 0){
      v_proto = rb_ary_new();
      rb_ary_push(v_proto, rb_str_new2("V"));
   }

   // Set an arbitrary limit of 20 parameters
   if(20 < RARRAY_LEN(v_proto))
      rb_raise(rb_eArgError, "too many parameters: %d", RARRAY_LEN(v_proto));

   // Set the default dll to 'kernel32'
   if(NIL_P(v_dll))
      v_dll = rb_str_new2("kernel32");

   // Set the default return type to 'L' (DWORD)
   if(NIL_P(v_return))
      v_return = rb_str_new2("L");

   SafeStringValue(v_dll);
   SafeStringValue(v_proc);

   hLibrary = LoadLibrary(TEXT(RSTRING_PTR(v_dll)));

   // The most likely cause of failure is a bad DLL load path
   if(!hLibrary){
      rb_raise(cAPILoadError, "LoadLibrary() function failed for '%s': %s",
         RSTRING_PTR(v_dll),
         StringError(GetLastError())
      );
   }

   ptr->library = hLibrary;

   /* Attempt to get the function.  If it fails, try again with an 'A'
    * appended.  If that fails, try again with a 'W' appended. If that
    * still fails, raise an API::LoadLibraryError.
    */

   fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_proc)));

   // Skip the ANSI and Wide function checks for MSVCRT functions.
   if(!fProc){
      if(strstr(RSTRING_PTR(v_dll), "msvcr")){
         rb_raise(
            cAPILoadError,
            "Unable to load function '%s'",
            RSTRING_PTR(v_proc)
         );
      }
      else{
         VALUE v_ascii = rb_str_new3(v_proc);
         v_ascii = rb_str_cat(v_ascii, first, 1);
         fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_ascii)));

         if(!fProc){
            VALUE v_unicode = rb_str_new3(v_proc);
            v_unicode = rb_str_cat(v_unicode, second, 1);
            fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_unicode)));

            if(!fProc){
               rb_raise(
                  cAPILoadError,
                  "Unable to load function '%s', '%s', or '%s'",
                  RSTRING_PTR(v_proc),
                  RSTRING_PTR(v_ascii),
                  RSTRING_PTR(v_unicode)
               );
            }
            else{
               rb_iv_set(self, "@effective_function_name", v_unicode);
            }
         }
         else{
            rb_iv_set(self, "@effective_function_name", v_ascii);
         }
      }
   }
   else{
      rb_iv_set(self, "@effective_function_name", v_proc);
   }

   ptr->function = fProc;

   // Push the numeric prototypes onto our int array for later use.

   for(i = 0; i < RARRAY_LEN(v_proto); i++){
      SafeStringValue(RARRAY_PTR(v_proto)[i]);
      switch(*(char*)StringValuePtr(RARRAY_PTR(v_proto)[i])){
         case 'L':
            ptr->prototype[i] = _T_LONG;
            break;
         case 'P':
            ptr->prototype[i] = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->prototype[i] = _T_INTEGER;
            break;
         case 'V':
            ptr->prototype[i] = _T_VOID;
            break;
         case 'K':
            ptr->prototype[i] = _T_CALLBACK;
            break;
         case 'S':
            ptr->prototype[i] = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal prototype '%s'",
               StringValuePtr(RARRAY_PTR(v_proto)[i])
            );
      }
   }

   // Store the return type for later use.

   // Automatically convert empty strings or nil to type void.
   if(NIL_P(v_return) || RSTRING_LEN(v_return) == 0){
      v_return = rb_str_new2("V");
      ptr->return_type = _T_VOID;
   }
   else{
      SafeStringValue(v_return);
      switch(*RSTRING_PTR(v_return)){
         case 'L':
            ptr->return_type = _T_LONG;
            break;
         case 'P':
            ptr->return_type = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->return_type = _T_INTEGER;
            break;
         case 'V':
            ptr->return_type = _T_VOID;
            break;
         case 'S':
            ptr->return_type = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal return type '%s'",
               RSTRING_PTR(v_return)
            );
      }
   }

   rb_iv_set(self, "@dll_name", v_dll);
   rb_iv_set(self, "@function_name", v_proc);
   rb_iv_set(self, "@prototype", v_proto);
   rb_iv_set(self, "@return_type", v_return);

   return self;
}

Public Instance Methods

) click to toggle source

Calls the function pointer with the given arguments (if any). Note that, while this method will catch some prototype mismatches (raising a TypeError in the process), it is not fulproof. It is ultimately your job to make sure the arguments match the prototype specified in the constructor.

For convenience, nil is converted to NULL, true is converted to TRUE (1) and false is converted to FALSE (0).

static VALUE api_call(int argc, VALUE* argv, VALUE self){

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.