win32-api 1.2.0-x86-mswin32-60 → 1.2.1-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +7 -0
- data/README +1 -1
- data/ext/win32/api.c +209 -95
- data/lib/win32/api.so +0 -0
- data/test/test_win32_api.rb +36 -24
- metadata +2 -2
    
        data/CHANGES
    CHANGED
    
    | @@ -1,3 +1,10 @@ | |
| 1 | 
            +
            = 1.2.1 - 14-Nov-2008
         | 
| 2 | 
            +
            * Fixed and updated callback handling.
         | 
| 3 | 
            +
            * Fixed wide string return handling for pointers and strings.
         | 
| 4 | 
            +
            * Added the Win32::API::Callback#address instance method.
         | 
| 5 | 
            +
            * All errors are now in English instead of your native language, because
         | 
| 6 | 
            +
              that's what Ruby itself does.
         | 
| 7 | 
            +
             | 
| 1 8 | 
             
            = 1.2.0 - 22-Jul-2008
         | 
| 2 9 | 
             
            * Added support for the 'S' (string) prototype and return type. It can be
         | 
| 3 10 | 
             
              used instead of 'P' (pointer) for const char*.
         | 
    
        data/README
    CHANGED
    
    | @@ -70,7 +70,7 @@ | |
| 70 70 | 
             
               instance variable names with proper accessors, removing support for lower
         | 
| 71 71 | 
             
               case prototype and return value characters that no one used in practice,
         | 
| 72 72 | 
             
               better naming conventions, the addition of RDoc ready comments and,
         | 
| 73 | 
            -
               especially, callback support.
         | 
| 73 | 
            +
               especially, callback and raw function pointer support.
         | 
| 74 74 |  | 
| 75 75 | 
             
               Most importantly, we can now add, modify and fix any features that we feel
         | 
| 76 76 | 
             
               best benefit our end users.
         | 
    
        data/ext/win32/api.c
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            #include <windows.h>
         | 
| 3 3 |  | 
| 4 4 | 
             
            #define MAX_BUF 1024
         | 
| 5 | 
            -
            #define WINDOWS_API_VERSION "1.2. | 
| 5 | 
            +
            #define WINDOWS_API_VERSION "1.2.1"
         | 
| 6 6 |  | 
| 7 7 | 
             
            #define _T_VOID     0
         | 
| 8 8 | 
             
            #define _T_LONG     1
         | 
| @@ -12,6 +12,7 @@ | |
| 12 12 | 
             
            #define _T_STRING   5
         | 
| 13 13 |  | 
| 14 14 | 
             
            VALUE cAPIError, cCallbackError;
         | 
| 15 | 
            +
            static VALUE ActiveCallback = Qnil;
         | 
| 15 16 |  | 
| 16 17 | 
             
            typedef struct {
         | 
| 17 18 | 
             
                HANDLE library;
         | 
| @@ -34,7 +35,10 @@ static VALUE api_allocate(VALUE klass){ | |
| 34 35 | 
             
            }
         | 
| 35 36 |  | 
| 36 37 | 
             
            /* Helper function that converts the error number returned by GetLastError()
         | 
| 37 | 
            -
             * into a human readable string.  | 
| 38 | 
            +
             * into a human readable string. Note that we always use English for error
         | 
| 39 | 
            +
             * output because that's what Ruby itself does.
         | 
| 40 | 
            +
             *
         | 
| 41 | 
            +
             * Internal use only.
         | 
| 38 42 | 
             
             */
         | 
| 39 43 | 
             
            char* StringError(DWORD dwError){
         | 
| 40 44 | 
             
               LPVOID lpMsgBuf;
         | 
| @@ -48,7 +52,7 @@ char* StringError(DWORD dwError){ | |
| 48 52 | 
             
                  FORMAT_MESSAGE_IGNORE_INSERTS,
         | 
| 49 53 | 
             
                  NULL,
         | 
| 50 54 | 
             
                  dwError,
         | 
| 51 | 
            -
                  MAKELANGID( | 
| 55 | 
            +
                  MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
         | 
| 52 56 | 
             
                  (LPSTR)&lpMsgBuf,
         | 
| 53 57 | 
             
                  0,
         | 
| 54 58 | 
             
                  NULL
         | 
| @@ -74,43 +78,44 @@ char* StringError(DWORD dwError){ | |
| 74 78 | 
             
            /*
         | 
| 75 79 | 
             
             * call-seq:
         | 
| 76 80 | 
             
             *    Win32::API::Callback.new(prototype, return='L'){ |proto| ... }
         | 
| 77 | 
            -
             * | 
| 81 | 
            +
             *
         | 
| 78 82 | 
             
             * Creates and returns a new Win32::API::Callback object. The prototype
         | 
| 79 83 | 
             
             * arguments are yielded back to the block in the same order they were
         | 
| 80 84 | 
             
             * declared.
         | 
| 81 | 
            -
             * | 
| 85 | 
            +
             *
         | 
| 82 86 | 
             
             * The +prototype+ is the function prototype for the callback function. This
         | 
| 83 87 | 
             
             * is a string. The possible valid characters are 'I' (integer), 'L' (long),
         | 
| 84 88 | 
             
             * 'V' (void), 'P' (pointer) or 'S' (string). Unlike API objects, API::Callback
         | 
| 85 89 | 
             
             * objects do not have a default prototype.
         | 
| 86 | 
            -
             * | 
| 90 | 
            +
             *
         | 
| 87 91 | 
             
             * The +return+ argument is the return type for the callback function. The
         | 
| 88 92 | 
             
             * valid characters are the same as for the +prototype+. The default is
         | 
| 89 93 | 
             
             * 'L' (long).
         | 
| 90 | 
            -
             * | 
| 94 | 
            +
             *
         | 
| 91 95 | 
             
             * Example:
         | 
| 92 96 | 
             
             *    require 'win32/api'
         | 
| 93 97 | 
             
             *    include Win32
         | 
| 94 | 
            -
             * | 
| 98 | 
            +
             *
         | 
| 95 99 | 
             
             *    EnumWindows = API.new('EnumWindows', 'KP', 'L', 'user32')
         | 
| 96 100 | 
             
             *    GetWindowText = API.new('GetWindowText', 'LPI', 'I', 'user32')
         | 
| 97 | 
            -
             * | 
| 101 | 
            +
             *
         | 
| 98 102 | 
             
             *    EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
         | 
| 99 103 | 
             
             *       buf = "\0" * 200
         | 
| 100 104 | 
             
             *       GetWindowText.call(handle, buf, 200);
         | 
| 101 105 | 
             
             *       puts buf.strip unless buf.strip.empty?
         | 
| 102 106 | 
             
             *       buf.index(param).nil? ? true : false
         | 
| 103 107 | 
             
             *    }
         | 
| 104 | 
            -
             * | 
| 108 | 
            +
             *
         | 
| 105 109 | 
             
             *    EnumWindows.call(EnumWindowsProc, 'UEDIT32')
         | 
| 106 110 | 
             
             */
         | 
| 107 111 | 
             
            static VALUE callback_init(int argc, VALUE* argv, VALUE self)
         | 
| 108 112 | 
             
            {
         | 
| 113 | 
            +
               extern void *CallbackTable[];
         | 
| 109 114 | 
             
               VALUE v_proto, v_return, v_proc;
         | 
| 110 115 | 
             
               int i;
         | 
| 111 | 
            -
             | 
| 116 | 
            +
             | 
| 112 117 | 
             
               rb_scan_args(argc, argv, "11&", &v_proto, &v_return, &v_proc);
         | 
| 113 | 
            -
             | 
| 118 | 
            +
             | 
| 114 119 | 
             
               /* Validate prototype characters */
         | 
| 115 120 | 
             
               for(i = 0; i < RSTRING(v_proto)->len; i++){
         | 
| 116 121 | 
             
                  switch(RSTRING(v_proto)->ptr[i]){
         | 
| @@ -128,17 +133,19 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self) | |
| 128 133 | 
             
               rb_iv_set(self, "@function", v_proc);
         | 
| 129 134 | 
             
               rb_iv_set(self, "@prototype", v_proto);
         | 
| 130 135 | 
             
               rb_iv_set(self, "@return_type", v_return);
         | 
| 131 | 
            -
             | 
| 136 | 
            +
               rb_iv_set(self, "@address", ULONG2NUM((LPARAM)CallbackTable[RSTRING(v_proto)->len]));
         | 
| 137 | 
            +
               ActiveCallback = self;
         | 
| 138 | 
            +
             | 
| 132 139 | 
             
               return self;
         | 
| 133 140 | 
             
            }
         | 
| 134 141 |  | 
| 135 142 | 
             
            /*
         | 
| 136 143 | 
             
             * call-seq:
         | 
| 137 144 | 
             
             *    Win32::API.new(function, prototype='V', return='L', dll='kernel32')
         | 
| 138 | 
            -
             * | 
| 145 | 
            +
             *
         | 
| 139 146 | 
             
             * Creates and returns a new Win32::API object. The +function+ is the name
         | 
| 140 147 | 
             
             * of the Windows function.
         | 
| 141 | 
            -
             * | 
| 148 | 
            +
             *
         | 
| 142 149 | 
             
             * The +prototype+ is the function prototype for +function+. This can be a
         | 
| 143 150 | 
             
             * string or an array of characters.  The possible valid characters are 'I'
         | 
| 144 151 | 
             
             * (integer), 'L' (long), 'V' (void), 'P' (pointer), 'K' (callback) or 'S'
         | 
| @@ -148,27 +155,27 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self) | |
| 148 155 | 
             
             *
         | 
| 149 156 | 
             
             * Constant (const char*) strings should use 'S'. Pass by reference string
         | 
| 150 157 | 
             
             * buffers should use 'P'. The former is faster, but cannot be modified.
         | 
| 151 | 
            -
             * | 
| 158 | 
            +
             *
         | 
| 152 159 | 
             
             * The +return+ argument is the return type for the function.  The valid
         | 
| 153 160 | 
             
             * characters are the same as for the +prototype+.  The default is 'L' (long).
         | 
| 154 | 
            -
             * | 
| 161 | 
            +
             *
         | 
| 155 162 | 
             
             * The +dll+ is the name of the DLL file that the function is exported from.
         | 
| 156 163 | 
             
             * The default is 'kernel32'.
         | 
| 157 | 
            -
             * | 
| 164 | 
            +
             *
         | 
| 158 165 | 
             
             * If the function cannot be found then an API::Error is raised (a subclass
         | 
| 159 166 | 
             
             * of RuntimeError).
         | 
| 160 | 
            -
             * | 
| 167 | 
            +
             *
         | 
| 161 168 | 
             
             * Example:
         | 
| 162 | 
            -
             * | 
| 169 | 
            +
             *
         | 
| 163 170 | 
             
             *    require 'win32/api'
         | 
| 164 171 | 
             
             *    include Win32
         | 
| 165 | 
            -
             * | 
| 172 | 
            +
             *
         | 
| 166 173 | 
             
             *    buf = 0.chr * 260
         | 
| 167 174 | 
             
             *    len = [buf.length].pack('L')
         | 
| 168 | 
            -
             * | 
| 175 | 
            +
             *
         | 
| 169 176 | 
             
             *    GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
         | 
| 170 177 | 
             
             *    GetUserName.call(buf, len)
         | 
| 171 | 
            -
             * | 
| 178 | 
            +
             *
         | 
| 172 179 | 
             
             *    puts buf.strip
         | 
| 173 180 | 
             
             */
         | 
| 174 181 | 
             
            static VALUE api_init(int argc, VALUE* argv, VALUE self)
         | 
| @@ -180,9 +187,9 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 180 187 | 
             
               char* first  = "A";
         | 
| 181 188 | 
             
               char* second = "W";
         | 
| 182 189 | 
             
               VALUE v_proc, v_proto, v_return, v_dll;
         | 
| 183 | 
            -
             | 
| 190 | 
            +
             | 
| 184 191 | 
             
               rb_scan_args(argc, argv, "13", &v_proc, &v_proto, &v_return, &v_dll);
         | 
| 185 | 
            -
             | 
| 192 | 
            +
             | 
| 186 193 | 
             
               Data_Get_Struct(self, Win32API, ptr);
         | 
| 187 194 |  | 
| 188 195 | 
             
               // Convert a string prototype to an array of characters
         | 
| @@ -198,14 +205,14 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 198 205 | 
             
               // Set an arbitrary limit of 16 parameters
         | 
| 199 206 | 
             
               if(16 < RARRAY(v_proto)->len)
         | 
| 200 207 | 
             
                  rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
         | 
| 201 | 
            -
             | 
| 208 | 
            +
             | 
| 202 209 | 
             
               // Set the default dll to 'kernel32'
         | 
| 203 210 | 
             
               if(NIL_P(v_dll))
         | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 211 | 
            +
                  v_dll = rb_str_new2("kernel32");
         | 
| 212 | 
            +
             | 
| 206 213 | 
             
               // Set the default return type to 'L' (DWORD)
         | 
| 207 214 | 
             
               if(NIL_P(v_return))
         | 
| 208 | 
            -
             | 
| 215 | 
            +
                  v_return = rb_str_new2("L");
         | 
| 209 216 |  | 
| 210 217 | 
             
               SafeStringValue(v_dll);
         | 
| 211 218 | 
             
               SafeStringValue(v_proc);
         | 
| @@ -397,7 +404,7 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){ | |
| 397 404 |  | 
| 398 405 | 
             
               // Set the default return type to 'L' (DWORD)
         | 
| 399 406 | 
             
               if(NIL_P(v_return))
         | 
| 400 | 
            -
             | 
| 407 | 
            +
                  v_return = rb_str_new2("L");
         | 
| 401 408 |  | 
| 402 409 | 
             
               ptr->function = (FARPROC)NUM2LONG(v_address);
         | 
| 403 410 |  | 
| @@ -467,95 +474,174 @@ static VALUE func_init(int argc, VALUE* argv, VALUE self){ | |
| 467 474 | 
             
            }
         | 
| 468 475 |  | 
| 469 476 | 
             
            typedef struct {
         | 
| 470 | 
            -
               DWORD params[ | 
| 471 | 
            -
            }  | 
| 477 | 
            +
               DWORD params[16];
         | 
| 478 | 
            +
            } CALLPARAM;
         | 
| 472 479 |  | 
| 473 | 
            -
            static VALUE ActiveCallback; 
         | 
| 474 480 |  | 
| 475 | 
            -
            DWORD CallbackFunction( | 
| 481 | 
            +
            DWORD CallbackFunction(CALLPARAM param)
         | 
| 476 482 | 
             
            {
         | 
| 477 483 | 
             
                VALUE v_proto, v_return, v_proc, v_retval;
         | 
| 478 484 | 
             
                VALUE argv[16];
         | 
| 479 485 | 
             
                int i, argc;
         | 
| 480 486 | 
             
                char *a_proto;
         | 
| 481 487 | 
             
                char *a_return;
         | 
| 482 | 
            -
             | 
| 488 | 
            +
             | 
| 483 489 | 
             
                if(!NIL_P(ActiveCallback)){
         | 
| 484 490 | 
             
                    v_proto = rb_iv_get(ActiveCallback, "@prototype");
         | 
| 485 491 | 
             
                    a_proto = RSTRING(v_proto)->ptr;
         | 
| 486 | 
            -
             | 
| 492 | 
            +
             | 
| 487 493 | 
             
                    v_return = rb_iv_get(ActiveCallback, "@return_type");
         | 
| 488 494 | 
             
                    a_return = RSTRING(v_return)->ptr;
         | 
| 489 | 
            -
             | 
| 495 | 
            +
             | 
| 490 496 | 
             
                    v_proc = rb_iv_get(ActiveCallback, "@function");
         | 
| 491 497 | 
             
                    argc = RSTRING(v_proto)->len;
         | 
| 492 | 
            -
             | 
| 498 | 
            +
             | 
| 493 499 | 
             
                    for(i=0; i < RSTRING(v_proto)->len; i++){
         | 
| 494 500 | 
             
                       argv[i] = Qnil;
         | 
| 495 501 | 
             
                       switch(a_proto[i]){
         | 
| 496 | 
            -
             | 
| 497 | 
            -
             | 
| 498 | 
            -
             | 
| 499 | 
            -
             | 
| 500 | 
            -
             | 
| 501 | 
            -
             | 
| 502 | 
            -
             | 
| 503 | 
            -
             | 
| 504 | 
            -
             | 
| 505 | 
            -
             | 
| 506 | 
            -
             | 
| 507 | 
            -
             | 
| 502 | 
            +
                          case 'L':
         | 
| 503 | 
            +
                             argv[i] = ULONG2NUM(param.params[i]);
         | 
| 504 | 
            +
                             break;
         | 
| 505 | 
            +
                          case 'P':
         | 
| 506 | 
            +
                             if(param.params[i])
         | 
| 507 | 
            +
                                argv[i] = rb_str_new2((char *)param.params[i]);
         | 
| 508 | 
            +
                             break;
         | 
| 509 | 
            +
                          case 'I':
         | 
| 510 | 
            +
                             argv[i] = INT2NUM(param.params[i]);
         | 
| 511 | 
            +
                             break;
         | 
| 512 | 
            +
                          default:
         | 
| 513 | 
            +
                             rb_raise(cCallbackError, "Illegal prototype '%c'", a_proto[i]);
         | 
| 508 514 | 
             
                        }
         | 
| 509 515 | 
             
                    }
         | 
| 510 | 
            -
             | 
| 516 | 
            +
             | 
| 511 517 | 
             
                    v_retval = rb_funcall2(v_proc, rb_intern("call"), argc, argv);
         | 
| 512 | 
            -
             | 
| 518 | 
            +
             | 
| 513 519 | 
             
                    /* Handle true and false explicitly, as some CALLBACK functions
         | 
| 514 520 | 
             
                     * require TRUE or FALSE to break out of loops, etc.
         | 
| 515 521 | 
             
                     */
         | 
| 516 | 
            -
                    if(v_retval == Qtrue) | 
| 522 | 
            +
                    if(v_retval == Qtrue)
         | 
| 517 523 | 
             
                       return TRUE;
         | 
| 518 | 
            -
                    else if(v_retval == Qfalse) | 
| 524 | 
            +
                    else if(v_retval == Qfalse)
         | 
| 519 525 | 
             
                       return FALSE;
         | 
| 520 | 
            -
             | 
| 526 | 
            +
             | 
| 521 527 | 
             
                    switch (*a_return) {
         | 
| 522 528 | 
             
                       case 'I':
         | 
| 523 529 | 
             
                          return NUM2INT(v_retval);
         | 
| 524 530 | 
             
                          break;
         | 
| 525 531 | 
             
                       case 'L':
         | 
| 526 | 
            -
                          return NUM2ULONG(v_retval); | 
| 532 | 
            +
                          return NUM2ULONG(v_retval);
         | 
| 527 533 | 
             
                          break;
         | 
| 528 534 | 
             
                       case 'S':
         | 
| 529 535 | 
             
                          return (unsigned long)RSTRING(v_retval)->ptr;
         | 
| 530 536 | 
             
                          break;
         | 
| 531 537 | 
             
                       case 'P':
         | 
| 532 | 
            -
             | 
| 533 | 
            -
             | 
| 534 | 
            -
             | 
| 535 | 
            -
             | 
| 536 | 
            -
             | 
| 537 | 
            -
             | 
| 538 | 
            -
             | 
| 539 | 
            -
             | 
| 540 | 
            -
             | 
| 541 | 
            -
             | 
| 542 | 
            -
             | 
| 543 | 
            -
             | 
| 544 | 
            -
                    } | 
| 538 | 
            +
                          if(NIL_P(v_retval)){
         | 
| 539 | 
            +
                             return 0;
         | 
| 540 | 
            +
                          }
         | 
| 541 | 
            +
                          else if(FIXNUM_P(v_retval)){
         | 
| 542 | 
            +
                             return NUM2ULONG(v_retval);
         | 
| 543 | 
            +
                          }
         | 
| 544 | 
            +
                          else{
         | 
| 545 | 
            +
                             StringValue(v_retval);
         | 
| 546 | 
            +
                             rb_str_modify(v_retval);
         | 
| 547 | 
            +
                             return (unsigned long)StringValuePtr(v_retval);
         | 
| 548 | 
            +
                          }
         | 
| 549 | 
            +
                          break;
         | 
| 550 | 
            +
                    }
         | 
| 545 551 | 
             
                }
         | 
| 546 | 
            -
             | 
| 552 | 
            +
             | 
| 547 553 | 
             
                return 0;
         | 
| 548 554 | 
             
            }
         | 
| 549 555 |  | 
| 556 | 
            +
            DWORD CALLBACK CallbackFunction0() {
         | 
| 557 | 
            +
               CALLPARAM param = {0};
         | 
| 558 | 
            +
               param.params[0] = 0;
         | 
| 559 | 
            +
               return CallbackFunction(param);
         | 
| 560 | 
            +
            }
         | 
| 561 | 
            +
             | 
| 562 | 
            +
            DWORD CALLBACK CallbackFunction1(DWORD p1) {
         | 
| 563 | 
            +
               CALLPARAM param = {p1};
         | 
| 564 | 
            +
               return CallbackFunction(param);
         | 
| 565 | 
            +
            }
         | 
| 566 | 
            +
             | 
| 567 | 
            +
            DWORD CALLBACK CallbackFunction2(DWORD p1, DWORD p2){
         | 
| 568 | 
            +
               CALLPARAM param = {p1,p2};
         | 
| 569 | 
            +
               return CallbackFunction(param);
         | 
| 570 | 
            +
            }
         | 
| 571 | 
            +
             | 
| 572 | 
            +
            DWORD CALLBACK CallbackFunction3(DWORD p1, DWORD p2, DWORD p3){
         | 
| 573 | 
            +
               CALLPARAM param = {p1,p2,p3};
         | 
| 574 | 
            +
               return CallbackFunction(param);
         | 
| 575 | 
            +
            }
         | 
| 576 | 
            +
             | 
| 577 | 
            +
            DWORD CALLBACK CallbackFunction4(DWORD p1, DWORD p2, DWORD p3, DWORD p4){
         | 
| 578 | 
            +
               CALLPARAM param = {p1,p2,p3,p4};
         | 
| 579 | 
            +
               return CallbackFunction(param);
         | 
| 580 | 
            +
            }
         | 
| 581 | 
            +
             | 
| 582 | 
            +
            DWORD CALLBACK CallbackFunction5(
         | 
| 583 | 
            +
               DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5
         | 
| 584 | 
            +
            )
         | 
| 585 | 
            +
            {
         | 
| 586 | 
            +
               CALLPARAM param = {p1,p2,p3,p4,p5};
         | 
| 587 | 
            +
               return CallbackFunction(param);
         | 
| 588 | 
            +
            }
         | 
| 589 | 
            +
             | 
| 590 | 
            +
            DWORD CALLBACK CallbackFunction6(
         | 
| 591 | 
            +
               DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5, DWORD p6
         | 
| 592 | 
            +
            )
         | 
| 593 | 
            +
            {
         | 
| 594 | 
            +
               CALLPARAM param = {p1,p2,p3,p4,p5,p6};
         | 
| 595 | 
            +
               return CallbackFunction(param);
         | 
| 596 | 
            +
            }
         | 
| 597 | 
            +
             | 
| 598 | 
            +
            DWORD CALLBACK CallbackFunction7(
         | 
| 599 | 
            +
               DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5, DWORD p6, DWORD p7)
         | 
| 600 | 
            +
            {
         | 
| 601 | 
            +
               CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7};
         | 
| 602 | 
            +
               return CallbackFunction(param);
         | 
| 603 | 
            +
            }
         | 
| 604 | 
            +
             | 
| 605 | 
            +
            DWORD CALLBACK CallbackFunction8(
         | 
| 606 | 
            +
               DWORD p1, DWORD p2, DWORD p3, DWORD p4,
         | 
| 607 | 
            +
               DWORD p5, DWORD p6, DWORD p7, DWORD p8
         | 
| 608 | 
            +
            )
         | 
| 609 | 
            +
            {
         | 
| 610 | 
            +
               CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7,p8};
         | 
| 611 | 
            +
               return CallbackFunction(param);
         | 
| 612 | 
            +
            }
         | 
| 613 | 
            +
             | 
| 614 | 
            +
            DWORD CALLBACK CallbackFunction9(
         | 
| 615 | 
            +
               DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5,
         | 
| 616 | 
            +
               DWORD p6, DWORD p7, DWORD p8, DWORD p9
         | 
| 617 | 
            +
            )
         | 
| 618 | 
            +
            {
         | 
| 619 | 
            +
               CALLPARAM param = {p1,p2,p3,p4,p5,p6,p7,p8,p9};
         | 
| 620 | 
            +
               return CallbackFunction(param);
         | 
| 621 | 
            +
            }
         | 
| 622 | 
            +
             | 
| 623 | 
            +
            void *CallbackTable[] = {
         | 
| 624 | 
            +
               CallbackFunction0,
         | 
| 625 | 
            +
               CallbackFunction1,
         | 
| 626 | 
            +
               CallbackFunction2,
         | 
| 627 | 
            +
               CallbackFunction3,
         | 
| 628 | 
            +
               CallbackFunction4,
         | 
| 629 | 
            +
               CallbackFunction5,
         | 
| 630 | 
            +
               CallbackFunction6,
         | 
| 631 | 
            +
               CallbackFunction7,
         | 
| 632 | 
            +
               CallbackFunction8,
         | 
| 633 | 
            +
               CallbackFunction9
         | 
| 634 | 
            +
            };
         | 
| 635 | 
            +
             | 
| 550 636 | 
             
            /*
         | 
| 551 637 | 
             
             * call-seq:
         | 
| 552 638 | 
             
             *    Win32::API#call(arg1, arg2, ...)
         | 
| 553 | 
            -
             * | 
| 639 | 
            +
             *
         | 
| 554 640 | 
             
             * Calls the function pointer with the given arguments (if any). Note that,
         | 
| 555 641 | 
             
             * while this method will catch some prototype mismatches (raising a TypeError
         | 
| 556 642 | 
             
             * in the process), it is not fulproof.  It is ultimately your job to make
         | 
| 557 643 | 
             
             * sure the arguments match the +prototype+ specified in the constructor.
         | 
| 558 | 
            -
             * | 
| 644 | 
            +
             *
         | 
| 559 645 | 
             
             * For convenience, nil is converted to NULL, true is converted to TRUE (1)
         | 
| 560 646 | 
             
             * and false is converted to FALSE (0).
         | 
| 561 647 | 
             
             */
         | 
| @@ -619,7 +705,8 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){ | |
| 619 705 | 
             
                           break;
         | 
| 620 706 | 
             
                        case _T_CALLBACK:
         | 
| 621 707 | 
             
                           ActiveCallback = v_arg;
         | 
| 622 | 
            -
                            | 
| 708 | 
            +
                           v_proto = rb_iv_get(ActiveCallback, "@prototype");
         | 
| 709 | 
            +
                           param.params[i] = (LPARAM)CallbackTable[RSTRING(v_proto)->len];
         | 
| 623 710 | 
             
                           break;
         | 
| 624 711 | 
             
                        case _T_STRING:
         | 
| 625 712 | 
             
                           param.params[i] = (unsigned long)RSTRING(v_arg)->ptr;
         | 
| @@ -632,6 +719,7 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){ | |
| 632 719 | 
             
               /* Call the function, get the return value */
         | 
| 633 720 | 
             
               return_value = ptr->function(param);
         | 
| 634 721 |  | 
| 722 | 
            +
             | 
| 635 723 | 
             
               /* Return the appropriate type based on the return type specified
         | 
| 636 724 | 
             
                * in the constructor.
         | 
| 637 725 | 
             
                */
         | 
| @@ -646,13 +734,38 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){ | |
| 646 734 | 
             
                     v_return = Qnil;
         | 
| 647 735 | 
             
                     break;
         | 
| 648 736 | 
             
                  case _T_POINTER:
         | 
| 649 | 
            -
                     if(!return_value)
         | 
| 737 | 
            +
                     if(!return_value){
         | 
| 650 738 | 
             
                        v_return = Qnil;
         | 
| 651 | 
            -
                      | 
| 652 | 
            -
             | 
| 739 | 
            +
                     }
         | 
| 740 | 
            +
                     else{
         | 
| 741 | 
            +
                        VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
         | 
| 742 | 
            +
                        char* efunc = RSTRING(v_efunc)->ptr;
         | 
| 743 | 
            +
                        if(efunc[strlen(efunc)-1] == 'W'){
         | 
| 744 | 
            +
                           v_return = rb_str_new(
         | 
| 745 | 
            +
                              (TCHAR*)return_value,
         | 
| 746 | 
            +
                              wcslen((wchar_t*)return_value)*2
         | 
| 747 | 
            +
                           );
         | 
| 748 | 
            +
                        }
         | 
| 749 | 
            +
                        else{
         | 
| 750 | 
            +
                           v_return = rb_str_new2((TCHAR*)return_value);
         | 
| 751 | 
            +
                        }
         | 
| 752 | 
            +
                     }
         | 
| 653 753 | 
             
                     break;
         | 
| 654 754 | 
             
                  case _T_STRING:
         | 
| 655 | 
            -
                      | 
| 755 | 
            +
                     {
         | 
| 756 | 
            +
                        VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
         | 
| 757 | 
            +
                        char* efunc = RSTRING(v_efunc)->ptr;
         | 
| 758 | 
            +
             | 
| 759 | 
            +
                        if(efunc[strlen(efunc)-1] == 'W'){
         | 
| 760 | 
            +
                           v_return = rb_str_new(
         | 
| 761 | 
            +
                              (TCHAR*)return_value,
         | 
| 762 | 
            +
                              wcslen((wchar_t*)return_value)*2
         | 
| 763 | 
            +
                           );
         | 
| 764 | 
            +
                        }
         | 
| 765 | 
            +
                        else{
         | 
| 766 | 
            +
                           v_return = rb_str_new2((TCHAR*)return_value);
         | 
| 767 | 
            +
                        }
         | 
| 768 | 
            +
                     }
         | 
| 656 769 | 
             
                     break;
         | 
| 657 770 | 
             
                  default:
         | 
| 658 771 | 
             
                     v_return = INT2NUM(0);
         | 
| @@ -661,26 +774,26 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){ | |
| 661 774 | 
             
               return v_return;
         | 
| 662 775 | 
             
            }
         | 
| 663 776 |  | 
| 664 | 
            -
            /* | 
| 777 | 
            +
            /*
         | 
| 665 778 | 
             
             * Wraps the Windows API functions in a Ruby interface.
         | 
| 666 779 | 
             
             */
         | 
| 667 780 | 
             
            void Init_api(){
         | 
| 668 781 | 
             
               VALUE mWin32, cAPI, cCallback, cFunction;
         | 
| 669 | 
            -
             | 
| 782 | 
            +
             | 
| 670 783 | 
             
               /* Modules and Classes */
         | 
| 671 | 
            -
             | 
| 784 | 
            +
             | 
| 672 785 | 
             
               /* The Win32 module serves as a namespace only */
         | 
| 673 786 | 
             
               mWin32 = rb_define_module("Win32");
         | 
| 674 | 
            -
             | 
| 787 | 
            +
             | 
| 675 788 | 
             
               /* The API class encapsulates a function pointer to Windows API function */
         | 
| 676 789 | 
             
               cAPI = rb_define_class_under(mWin32, "API", rb_cObject);
         | 
| 677 | 
            -
             | 
| 678 | 
            -
               /* The API::Callback class encapsulates a Windows CALLBACK function */ | 
| 790 | 
            +
             | 
| 791 | 
            +
               /* The API::Callback class encapsulates a Windows CALLBACK function */
         | 
| 679 792 | 
             
               cCallback = rb_define_class_under(cAPI, "Callback", rb_cObject);
         | 
| 680 793 |  | 
| 681 794 | 
             
               /* The API::Function class encapsulates a raw function pointer */
         | 
| 682 795 | 
             
               cFunction = rb_define_class_under(cAPI, "Function", cAPI);
         | 
| 683 | 
            -
             | 
| 796 | 
            +
             | 
| 684 797 | 
             
               /* The API::Error class is raised if the constructor fails */
         | 
| 685 798 | 
             
               cAPIError = rb_define_class_under(cAPI, "Error", rb_eRuntimeError);
         | 
| 686 799 |  | 
| @@ -689,7 +802,7 @@ void Init_api(){ | |
| 689 802 |  | 
| 690 803 | 
             
               /* Miscellaneous */
         | 
| 691 804 | 
             
               rb_define_alloc_func(cAPI, api_allocate);
         | 
| 692 | 
            -
             | 
| 805 | 
            +
             | 
| 693 806 | 
             
               /* Win32::API Instance Methods */
         | 
| 694 807 | 
             
               rb_define_method(cAPI, "initialize", api_init, -1);
         | 
| 695 808 | 
             
               rb_define_method(cAPI, "call", api_call, -1);
         | 
| @@ -699,38 +812,39 @@ void Init_api(){ | |
| 699 812 |  | 
| 700 813 | 
             
               /* Win32::API::Function Instance Methods */
         | 
| 701 814 | 
             
               rb_define_method(cFunction, "initialize", func_init, -1);
         | 
| 702 | 
            -
             | 
| 815 | 
            +
             | 
| 703 816 | 
             
               /* The name of the DLL that exports the API function */
         | 
| 704 817 | 
             
               rb_define_attr(cAPI, "dll_name", 1, 0);
         | 
| 705 | 
            -
             | 
| 818 | 
            +
             | 
| 706 819 | 
             
               /* The name of the function passed to the constructor */
         | 
| 707 820 | 
             
               rb_define_attr(cAPI, "function_name", 1, 0);
         | 
| 708 | 
            -
             | 
| 821 | 
            +
             | 
| 709 822 | 
             
               /* The name of the actual function that is returned by the constructor.
         | 
| 710 823 | 
             
                * For example, if you passed 'GetUserName' to the constructor, then the
         | 
| 711 824 | 
             
                * effective function name would be either 'GetUserNameA' or 'GetUserNameW'.
         | 
| 712 825 | 
             
                */
         | 
| 713 826 | 
             
               rb_define_attr(cAPI, "effective_function_name", 1, 0);
         | 
| 714 | 
            -
             | 
| 827 | 
            +
             | 
| 715 828 | 
             
               /* The prototype, returned as an array of characters */
         | 
| 716 829 | 
             
               rb_define_attr(cAPI, "prototype", 1, 0);
         | 
| 717 | 
            -
             | 
| 830 | 
            +
             | 
| 718 831 | 
             
               /* The return type, returned as a single character, S, P, L, I, V or B */
         | 
| 719 832 | 
             
               rb_define_attr(cAPI, "return_type", 1, 0);
         | 
| 720 | 
            -
             | 
| 833 | 
            +
             | 
| 721 834 | 
             
               /* Win32::API::Callback Instance Methods */
         | 
| 722 | 
            -
             | 
| 835 | 
            +
             | 
| 723 836 | 
             
               /* The prototype, returned as an array of characters */
         | 
| 724 837 | 
             
               rb_define_attr(cCallback, "prototype", 1, 0);
         | 
| 725 | 
            -
             | 
| 838 | 
            +
             | 
| 726 839 | 
             
               /* The return type, returned as a single character, S, P, L, I, V or B */
         | 
| 727 840 | 
             
               rb_define_attr(cCallback, "return_type", 1, 0);
         | 
| 728 841 |  | 
| 729 842 | 
             
               /* The numeric address of the function pointer */
         | 
| 843 | 
            +
               rb_define_attr(cCallback, "address", 1, 0);
         | 
| 730 844 | 
             
               rb_define_attr(cFunction, "address", 1, 0);
         | 
| 731 | 
            -
             | 
| 845 | 
            +
             | 
| 732 846 | 
             
               /* Constants */
         | 
| 733 | 
            -
             | 
| 847 | 
            +
             | 
| 734 848 | 
             
               /* 1.2.0: The version of this library, returned as a String */
         | 
| 735 849 | 
             
               rb_define_const(cAPI, "VERSION", rb_str_new2(WINDOWS_API_VERSION));
         | 
| 736 850 | 
             
            }
         | 
    
        data/lib/win32/api.so
    CHANGED
    
    | Binary file | 
    
        data/test/test_win32_api.rb
    CHANGED
    
    | @@ -11,13 +11,13 @@ include Win32 | |
| 11 11 | 
             
            class TC_Win32_API < Test::Unit::TestCase
         | 
| 12 12 | 
             
               def setup
         | 
| 13 13 | 
             
                  @buf = 0.chr * 260
         | 
| 14 | 
            -
                  @ | 
| 14 | 
            +
                  @gcd = API.new('GetCurrentDirectory', 'LP')
         | 
| 15 15 | 
             
                  @gle = API.new('GetLastError', 'V', 'L')
         | 
| 16 16 | 
             
                  @str = API.new('strstr', 'PP', 'P', 'msvcrt')
         | 
| 17 17 | 
             
               end
         | 
| 18 18 |  | 
| 19 19 | 
             
               def test_version
         | 
| 20 | 
            -
                  assert_equal('1.2. | 
| 20 | 
            +
                  assert_equal('1.2.1', API::VERSION)
         | 
| 21 21 | 
             
               end
         | 
| 22 22 |  | 
| 23 23 | 
             
               def test_constructor_basic
         | 
| @@ -28,8 +28,8 @@ class TC_Win32_API < Test::Unit::TestCase | |
| 28 28 | 
             
               end
         | 
| 29 29 |  | 
| 30 30 | 
             
               def test_call
         | 
| 31 | 
            -
                  assert_respond_to(@ | 
| 32 | 
            -
                  assert_nothing_raised{ @ | 
| 31 | 
            +
                  assert_respond_to(@gcd, :call)
         | 
| 32 | 
            +
                  assert_nothing_raised{ @gcd.call(@buf.length, @buf) }
         | 
| 33 33 | 
             
                  assert_equal(Dir.pwd.tr('/', "\\"), @buf.strip)
         | 
| 34 34 | 
             
               end
         | 
| 35 35 |  | 
| @@ -39,36 +39,36 @@ class TC_Win32_API < Test::Unit::TestCase | |
| 39 39 | 
             
               end
         | 
| 40 40 |  | 
| 41 41 | 
             
               def test_dll_name
         | 
| 42 | 
            -
                  assert_respond_to(@ | 
| 43 | 
            -
                  assert_equal('kernel32', @ | 
| 42 | 
            +
                  assert_respond_to(@gcd, :dll_name)
         | 
| 43 | 
            +
                  assert_equal('kernel32', @gcd.dll_name)
         | 
| 44 44 | 
             
               end
         | 
| 45 45 |  | 
| 46 46 | 
             
               def test_function_name
         | 
| 47 | 
            -
                  assert_respond_to(@ | 
| 48 | 
            -
                  assert_equal('GetCurrentDirectory', @ | 
| 47 | 
            +
                  assert_respond_to(@gcd, :function_name)
         | 
| 48 | 
            +
                  assert_equal('GetCurrentDirectory', @gcd.function_name)
         | 
| 49 49 | 
             
                  assert_equal('strstr', @str.function_name)
         | 
| 50 50 | 
             
               end
         | 
| 51 51 |  | 
| 52 52 | 
             
               def test_effective_function_name
         | 
| 53 | 
            -
                  assert_respond_to(@ | 
| 54 | 
            -
                  assert_equal('GetCurrentDirectoryA', @ | 
| 53 | 
            +
                  assert_respond_to(@gcd, :effective_function_name)
         | 
| 54 | 
            +
                  assert_equal('GetCurrentDirectoryA', @gcd.effective_function_name)
         | 
| 55 55 | 
             
                  assert_equal('strstr', @str.effective_function_name)
         | 
| 56 56 |  | 
| 57 | 
            -
                  @ | 
| 58 | 
            -
                  assert_equal('GetCurrentDirectoryA', @ | 
| 57 | 
            +
                  @gcd = API.new('GetCurrentDirectoryA', 'LP')
         | 
| 58 | 
            +
                  assert_equal('GetCurrentDirectoryA', @gcd.effective_function_name)
         | 
| 59 59 |  | 
| 60 | 
            -
                  @ | 
| 61 | 
            -
                  assert_equal('GetCurrentDirectoryW', @ | 
| 60 | 
            +
                  @gcd = API.new('GetCurrentDirectoryW', 'LP')
         | 
| 61 | 
            +
                  assert_equal('GetCurrentDirectoryW', @gcd.effective_function_name)
         | 
| 62 62 | 
             
               end
         | 
| 63 63 |  | 
| 64 64 | 
             
               def test_prototype
         | 
| 65 | 
            -
                  assert_respond_to(@ | 
| 66 | 
            -
                  assert_equal(['L', 'P'], @ | 
| 65 | 
            +
                  assert_respond_to(@gcd, :prototype)
         | 
| 66 | 
            +
                  assert_equal(['L', 'P'], @gcd.prototype)
         | 
| 67 67 | 
             
               end
         | 
| 68 68 |  | 
| 69 69 | 
             
               def test_return_type
         | 
| 70 | 
            -
                  assert_respond_to(@ | 
| 71 | 
            -
                  assert_equal('L', @ | 
| 70 | 
            +
                  assert_respond_to(@gcd, :return_type)
         | 
| 71 | 
            +
                  assert_equal('L', @gcd.return_type)
         | 
| 72 72 | 
             
               end
         | 
| 73 73 |  | 
| 74 74 | 
             
               def test_constructor_high_iteration
         | 
| @@ -86,31 +86,43 @@ class TC_Win32_API < Test::Unit::TestCase | |
| 86 86 |  | 
| 87 87 | 
             
               # Compare MSVCRT error messages vs regular error messages. This validates
         | 
| 88 88 | 
             
               # that we're skipping the 'A' and 'W' lookups for MSVCRT functions.
         | 
| 89 | 
            +
               #
         | 
| 90 | 
            +
               # The JRuby test message is somewhat different because we're not using
         | 
| 91 | 
            +
               # GetLastError().
         | 
| 92 | 
            +
               #
         | 
| 89 93 | 
             
               def test_constructor_expected_failure_messages
         | 
| 90 94 | 
             
                  begin
         | 
| 91 95 | 
             
                     API.new('GetBlah')
         | 
| 92 96 | 
             
                  rescue API::Error => err
         | 
| 93 | 
            -
                      | 
| 94 | 
            -
             | 
| 97 | 
            +
                     if RUBY_PLATFORM.match('java')
         | 
| 98 | 
            +
                        expected = "Unable to load function 'GetBlah', 'GetBlahA', or 'GetBlahW'"
         | 
| 99 | 
            +
                     else
         | 
| 100 | 
            +
                        expected = "GetProcAddress() failed for 'GetBlah', 'GetBlahA' and "
         | 
| 101 | 
            +
                        expected += "'GetBlahW': The specified procedure could not be found."
         | 
| 102 | 
            +
                     end
         | 
| 95 103 | 
             
                     assert_equal(expected, err.to_s)
         | 
| 96 104 | 
             
                  end
         | 
| 97 105 |  | 
| 98 106 | 
             
                  begin
         | 
| 99 107 | 
             
                     API.new('strxxx', 'P', 'P', 'msvcrt')
         | 
| 100 108 | 
             
                  rescue API::Error => err
         | 
| 101 | 
            -
                      | 
| 102 | 
            -
             | 
| 109 | 
            +
                     if RUBY_PLATFORM.match('java')
         | 
| 110 | 
            +
                        expected = "Unable to load function 'strxxx'"
         | 
| 111 | 
            +
                     else
         | 
| 112 | 
            +
                        expected = "GetProcAddress() failed for 'strxxx': The specified "
         | 
| 113 | 
            +
                        expected += "procedure could not be found."
         | 
| 114 | 
            +
                     end
         | 
| 103 115 | 
             
                     assert_equal(expected, err.to_s)
         | 
| 104 116 | 
             
                  end
         | 
| 105 117 | 
             
               end
         | 
| 106 118 |  | 
| 107 119 | 
             
               def test_call_expected_failures
         | 
| 108 | 
            -
                  assert_raise(TypeError){ @ | 
| 120 | 
            +
                  assert_raise(TypeError){ @gcd.call('test', @buf) }
         | 
| 109 121 | 
             
               end
         | 
| 110 122 |  | 
| 111 123 | 
             
               def teardown
         | 
| 112 124 | 
             
                  @buf = nil
         | 
| 113 | 
            -
                  @ | 
| 125 | 
            +
                  @gcd = nil
         | 
| 114 126 | 
             
                  @gle = nil
         | 
| 115 127 | 
             
                  @str = nil
         | 
| 116 128 | 
             
               end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: win32-api
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 1.2. | 
| 4 | 
            +
              version: 1.2.1
         | 
| 5 5 | 
             
            platform: x86-mswin32-60
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Daniel J. Berger
         | 
| @@ -10,7 +10,7 @@ autorequire: | |
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 |  | 
| 13 | 
            -
            date: 2008- | 
| 13 | 
            +
            date: 2008-11-14 00:00:00 -07:00
         | 
| 14 14 | 
             
            default_executable: 
         | 
| 15 15 | 
             
            dependencies: []
         | 
| 16 16 |  |