win32-api 1.0.6-x86-mswin32-60 → 1.1.0-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 +5 -0
- data/MANIFEST +3 -2
- data/README +97 -84
- data/ext/extconf.rb +11 -0
- data/ext/win32/api.c +196 -41
- data/lib/win32/api.so +0 -0
- data/test/{tc_win32_api.rb → test_win32_api.rb} +8 -2
- data/test/{tc_win32_api_callback.rb → test_win32_api_callback.rb} +2 -2
- data/test/test_win32_api_function.rb +48 -0
- metadata +11 -9
    
        data/CHANGES
    CHANGED
    
    | @@ -1,3 +1,8 @@ | |
| 1 | 
            +
            = 1.1.0 - 12-Jun-2008
         | 
| 2 | 
            +
            * Added the Windows::API::Function class. This is a subclass of Win32::API
         | 
| 3 | 
            +
              meant only for use with raw function pointers.
         | 
| 4 | 
            +
            * Some documentation updates in the source and README files.
         | 
| 5 | 
            +
             | 
| 1 6 | 
             
            = 1.0.6 - 18-Apr-2008
         | 
| 2 7 | 
             
            * Added the effective_function_name method. This allows you to see what the
         | 
| 3 8 | 
             
              actual function name is that was defined, e.g. GetUserNameA vs GetUserNameW.
         | 
    
        data/MANIFEST
    CHANGED
    
    
    
        data/README
    CHANGED
    
    | @@ -1,85 +1,98 @@ | |
| 1 | 
            -
            = Description
         | 
| 2 | 
            -
               This is a drop-in replacement for the Win32API library currently part of
         | 
| 3 | 
            -
               Ruby's standard library.
         | 
| 4 | 
            -
            	
         | 
| 5 | 
            -
            = Synopsis
         | 
| 6 | 
            -
               require 'win32/api'
         | 
| 7 | 
            -
               include Win32
         | 
| 8 | 
            -
               
         | 
| 9 | 
            -
                | 
| 10 | 
            -
                | 
| 11 | 
            -
               
         | 
| 12 | 
            -
                | 
| 13 | 
            -
               GetUserName. | 
| 14 | 
            -
               
         | 
| 15 | 
            -
                | 
| 16 | 
            -
               
         | 
| 17 | 
            -
                | 
| 18 | 
            -
                | 
| 19 | 
            -
                | 
| 20 | 
            -
                | 
| 21 | 
            -
             | 
| 22 | 
            -
                   | 
| 23 | 
            -
                   | 
| 24 | 
            -
                  buf. | 
| 25 | 
            -
             | 
| 26 | 
            -
               
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                | 
| 29 | 
            -
                | 
| 30 | 
            -
                | 
| 31 | 
            -
                | 
| 32 | 
            -
                | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                | 
| 36 | 
            -
             | 
| 37 | 
            -
               
         | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
                | 
| 41 | 
            -
                | 
| 42 | 
            -
                | 
| 43 | 
            -
               
         | 
| 44 | 
            -
                | 
| 45 | 
            -
                | 
| 46 | 
            -
                | 
| 47 | 
            -
             | 
| 48 | 
            -
               
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                | 
| 51 | 
            -
             | 
| 52 | 
            -
                | 
| 53 | 
            -
               
         | 
| 54 | 
            -
                | 
| 55 | 
            -
                | 
| 56 | 
            -
                | 
| 57 | 
            -
                | 
| 58 | 
            -
                | 
| 59 | 
            -
               
         | 
| 60 | 
            -
                | 
| 61 | 
            -
                | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
                | 
| 65 | 
            -
                | 
| 66 | 
            -
               
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                | 
| 69 | 
            -
                | 
| 70 | 
            -
                | 
| 71 | 
            -
               
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                | 
| 74 | 
            -
                | 
| 75 | 
            -
             | 
| 76 | 
            -
            =  | 
| 77 | 
            -
                | 
| 78 | 
            -
                | 
| 79 | 
            -
             | 
| 80 | 
            -
            =  | 
| 81 | 
            -
                | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
                | 
| 1 | 
            +
            = Description
         | 
| 2 | 
            +
               This is a drop-in replacement for the Win32API library currently part of
         | 
| 3 | 
            +
               Ruby's standard library.
         | 
| 4 | 
            +
            	
         | 
| 5 | 
            +
            = Synopsis
         | 
| 6 | 
            +
               require 'win32/api'
         | 
| 7 | 
            +
               include Win32
         | 
| 8 | 
            +
               
         | 
| 9 | 
            +
               # Typical example - Get user name
         | 
| 10 | 
            +
               buf = 0.chr * 260
         | 
| 11 | 
            +
               len = [buf.length].pack('L')
         | 
| 12 | 
            +
               
         | 
| 13 | 
            +
               GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
         | 
| 14 | 
            +
               GetUserName.call(buf, len)
         | 
| 15 | 
            +
               
         | 
| 16 | 
            +
               puts buf.strip
         | 
| 17 | 
            +
               
         | 
| 18 | 
            +
               # Callback example - Enumerate windows
         | 
| 19 | 
            +
               EnumWindows     = API.new('EnumWindows', 'KP', 'L', 'user32')
         | 
| 20 | 
            +
               GetWindowText   = API.new('GetWindowText', 'LPI', 'I', 'user32')
         | 
| 21 | 
            +
               EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
         | 
| 22 | 
            +
                  buf = "\0" * 200
         | 
| 23 | 
            +
                  GetWindowText.call(handle, buf, 200);
         | 
| 24 | 
            +
                  puts buf.strip unless buf.strip.empty?
         | 
| 25 | 
            +
                  buf.index(param).nil? ? true : false
         | 
| 26 | 
            +
               }
         | 
| 27 | 
            +
               
         | 
| 28 | 
            +
               EnumWindows.call(EnumWindowsProc, 'UEDIT32')
         | 
| 29 | 
            +
               
         | 
| 30 | 
            +
               # Raw function pointer example - System beep
         | 
| 31 | 
            +
               LoadLibrary    = API.new('LoadLibrary', 'P', 'L')
         | 
| 32 | 
            +
               GetProcAddress = API.new('GetProcAddress', 'LP', 'L')
         | 
| 33 | 
            +
             
         | 
| 34 | 
            +
               hlib = LoadLibrary.call('user32')
         | 
| 35 | 
            +
               addr = GetProcAddress.call(hlib, 'MessageBeep')
         | 
| 36 | 
            +
               func = Win32::API::Function.new(addr, 'L', 'L')
         | 
| 37 | 
            +
               func.call(0)
         | 
| 38 | 
            +
               
         | 
| 39 | 
            +
            = Differences between win32-api and Win32API
         | 
| 40 | 
            +
               * This library has callback support
         | 
| 41 | 
            +
               * This library supports raw function pointers.
         | 
| 42 | 
            +
               * Argument order change. The DLL name is now last, not first.
         | 
| 43 | 
            +
               * Removed the 'N' and 'n'. Always use 'L' for longs now.
         | 
| 44 | 
            +
               * Sensible default arguments for the prototype, return type and DLL name.
         | 
| 45 | 
            +
               * Reader methods for the function name, prototype, return type and DLL.
         | 
| 46 | 
            +
               * Removed the support for lower case prototype and return types. Always
         | 
| 47 | 
            +
                 use capital letters.
         | 
| 48 | 
            +
               * Resorts to wide character functions (where possible) when $KCODE is set
         | 
| 49 | 
            +
                 to UTF8.
         | 
| 50 | 
            +
               
         | 
| 51 | 
            +
            = Developer's Notes
         | 
| 52 | 
            +
               The current Win32API library that ships with the standard library has been
         | 
| 53 | 
            +
               slated for removal from Ruby 2.0 and it will not receive any updates in the
         | 
| 54 | 
            +
               Ruby 1.8.x branch. I have far too many libraries invested in it to let it
         | 
| 55 | 
            +
               die at this point.
         | 
| 56 | 
            +
               
         | 
| 57 | 
            +
               In addition, the current Win32API library was written in the bad old Ruby
         | 
| 58 | 
            +
               1.6.x days, which means it doesn't use the newer allocation framework.
         | 
| 59 | 
            +
               There were several other refactorings that I felt it needed to more closely
         | 
| 60 | 
            +
               match how it was actually being used in practice.
         | 
| 61 | 
            +
               
         | 
| 62 | 
            +
               The first order of business was changing the order of the arguments. By
         | 
| 63 | 
            +
               moving the DLL name from first to last, I was able to provide reasonable
         | 
| 64 | 
            +
               default arguments for the prototype, return type and the DLL. Only the
         | 
| 65 | 
            +
               function name is required now.
         | 
| 66 | 
            +
               
         | 
| 67 | 
            +
               There was a laundry list of other refactorings that were needed: sensical
         | 
| 68 | 
            +
               instance variable names with proper accessors, removing support for lower
         | 
| 69 | 
            +
               case prototype and return value characters that no one used in practice,
         | 
| 70 | 
            +
               better naming conventions, the addition of RDoc ready comments and,
         | 
| 71 | 
            +
               especially, callback support.
         | 
| 72 | 
            +
               
         | 
| 73 | 
            +
               Most importantly, we can now add, modify and fix any features that we feel
         | 
| 74 | 
            +
               best benefit our end users.
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            = Documentation
         | 
| 77 | 
            +
               The source file contains inline RDoc documentation. If you installed
         | 
| 78 | 
            +
               this file as a gem, then you have the docs.
         | 
| 79 | 
            +
               
         | 
| 80 | 
            +
            = Warranty
         | 
| 81 | 
            +
               This package is provided "as is" and without any express or
         | 
| 82 | 
            +
               implied warranties, including, without limitation, the implied
         | 
| 83 | 
            +
               warranties of merchantability and fitness for a particular purpose.
         | 
| 84 | 
            +
               
         | 
| 85 | 
            +
            = Known Bugs
         | 
| 86 | 
            +
               None that I'm aware of. Please submit any bug reports to the project page
         | 
| 87 | 
            +
               at http://www.rubyforge.org/projects/win32utils.
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            = Copyright
         | 
| 90 | 
            +
               (C) 2003-2008 Daniel J. Berger
         | 
| 91 | 
            +
               All Rights Reserved
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            = License
         | 
| 94 | 
            +
               Ruby's
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            = Authors
         | 
| 97 | 
            +
               Daniel J. Berger
         | 
| 85 98 | 
             
               Park Heesob
         | 
    
        data/ext/extconf.rb
    ADDED
    
    | @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            ##########################################################################
         | 
| 2 | 
            +
            # extconf.rb
         | 
| 3 | 
            +
            # 
         | 
| 4 | 
            +
            # The Windows::API binary should be built using the Rake task, i.e.
         | 
| 5 | 
            +
            # 'rake build' or 'rake install'.
         | 
| 6 | 
            +
            ##########################################################################
         | 
| 7 | 
            +
            require 'mkmf'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            have_func('strncpy_s')
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            create_makefile('win32/api', 'win32')
         | 
    
        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.0 | 
| 5 | 
            +
            #define WINDOWS_API_VERSION "1.1.0"
         | 
| 6 6 |  | 
| 7 7 | 
             
            #define _T_VOID     0
         | 
| 8 8 | 
             
            #define _T_LONG     1
         | 
| @@ -12,8 +12,28 @@ | |
| 12 12 |  | 
| 13 13 | 
             
            VALUE cAPIError, cCallbackError;
         | 
| 14 14 |  | 
| 15 | 
            +
            typedef struct {
         | 
| 16 | 
            +
                HANDLE library;
         | 
| 17 | 
            +
                FARPROC function;
         | 
| 18 | 
            +
                int return_type;
         | 
| 19 | 
            +
                int prototype[16];
         | 
| 20 | 
            +
            } Win32API;
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            static void api_free(Win32API* ptr){
         | 
| 23 | 
            +
               if(ptr->library)
         | 
| 24 | 
            +
                  FreeLibrary(ptr->library);
         | 
| 25 | 
            +
             | 
| 26 | 
            +
               if(ptr)
         | 
| 27 | 
            +
                  free(ptr);
         | 
| 28 | 
            +
            }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            static VALUE api_allocate(VALUE klass){
         | 
| 31 | 
            +
               Win32API* ptr = malloc(sizeof(Win32API));
         | 
| 32 | 
            +
               return Data_Wrap_Struct(klass, 0, api_free, ptr);
         | 
| 33 | 
            +
            }
         | 
| 34 | 
            +
             | 
| 15 35 | 
             
            /* Helper function that converts the error number returned by GetLastError()
         | 
| 16 | 
            -
             * into a human readable string. | 
| 36 | 
            +
             * into a human readable string. Internal use only.
         | 
| 17 37 | 
             
             */
         | 
| 18 38 | 
             
            char* StringError(DWORD dwError){
         | 
| 19 39 | 
             
               LPVOID lpMsgBuf;
         | 
| @@ -52,10 +72,11 @@ char* StringError(DWORD dwError){ | |
| 52 72 |  | 
| 53 73 | 
             
            /*
         | 
| 54 74 | 
             
             * call-seq:
         | 
| 55 | 
            -
             *    Win32::API::Callback.new(prototype, return='L')
         | 
| 75 | 
            +
             *    Win32::API::Callback.new(prototype, return='L'){ |proto| ... }
         | 
| 56 76 | 
             
             * 
         | 
| 57 | 
            -
             * Creates and returns a new Win32::API::Callback object. The  | 
| 58 | 
            -
             * the  | 
| 77 | 
            +
             * Creates and returns a new Win32::API::Callback object. The prototype
         | 
| 78 | 
            +
             * arguments are yielded back to the block in the same order they were
         | 
| 79 | 
            +
             * declared.
         | 
| 59 80 | 
             
             * 
         | 
| 60 81 | 
             
             * The +prototype+ is the function prototype for the callback function. This
         | 
| 61 82 | 
             
             * is a string. The possible valid characters are 'I' (integer), 'L' (long),
         | 
| @@ -65,6 +86,21 @@ char* StringError(DWORD dwError){ | |
| 65 86 | 
             
             * The +return+ argument is the return type for the callback function. The
         | 
| 66 87 | 
             
             * valid characters are the same as for the +prototype+. The default is
         | 
| 67 88 | 
             
             * 'L' (long).
         | 
| 89 | 
            +
             * 
         | 
| 90 | 
            +
             * Example:
         | 
| 91 | 
            +
             *    require 'win32/api'
         | 
| 92 | 
            +
             *    include Win32
         | 
| 93 | 
            +
             * 
         | 
| 94 | 
            +
             *    EnumWindows = API.new('EnumWindows', 'KP', 'L', 'user32')
         | 
| 95 | 
            +
             *    GetWindowText = API.new('GetWindowText', 'LPI', 'I', 'user32')
         | 
| 96 | 
            +
             *    EnumWindowsProc = API::Callback.new('LP', 'I'){ |handle, param|
         | 
| 97 | 
            +
             *       buf = "\0" * 200
         | 
| 98 | 
            +
             *       GetWindowText.call(handle, buf, 200);
         | 
| 99 | 
            +
             *       puts buf.strip unless buf.strip.empty?
         | 
| 100 | 
            +
             *       buf.index(param).nil? ? true : false
         | 
| 101 | 
            +
             *    }
         | 
| 102 | 
            +
             *  
         | 
| 103 | 
            +
             *    EnumWindows.call(EnumWindowsProc, 'UEDIT32')
         | 
| 68 104 | 
             
             */
         | 
| 69 105 | 
             
            static VALUE callback_init(int argc, VALUE* argv, VALUE self)
         | 
| 70 106 | 
             
            {
         | 
| @@ -91,27 +127,7 @@ static VALUE callback_init(int argc, VALUE* argv, VALUE self) | |
| 91 127 | 
             
               rb_iv_set(self, "@prototype", v_proto);
         | 
| 92 128 | 
             
               rb_iv_set(self, "@return_type", v_return);
         | 
| 93 129 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
            }
         | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
            typedef struct {
         | 
| 99 | 
            -
                HANDLE library;
         | 
| 100 | 
            -
                FARPROC function;
         | 
| 101 | 
            -
                int return_type;
         | 
| 102 | 
            -
                int prototype[16];
         | 
| 103 | 
            -
            } Win32API;
         | 
| 104 | 
            -
             | 
| 105 | 
            -
            static void api_free(Win32API* ptr){
         | 
| 106 | 
            -
               if(ptr->library)
         | 
| 107 | 
            -
                  FreeLibrary(ptr->library);
         | 
| 108 | 
            -
             | 
| 109 | 
            -
               free(ptr);
         | 
| 110 | 
            -
            }
         | 
| 111 | 
            -
             | 
| 112 | 
            -
            static VALUE api_allocate(VALUE klass){
         | 
| 113 | 
            -
               Win32API* ptr = malloc(sizeof(Win32API));
         | 
| 114 | 
            -
               return Data_Wrap_Struct(klass, 0, api_free, ptr);
         | 
| 130 | 
            +
               return self;
         | 
| 115 131 | 
             
            }
         | 
| 116 132 |  | 
| 117 133 | 
             
            /*
         | 
| @@ -134,6 +150,19 @@ static VALUE api_allocate(VALUE klass){ | |
| 134 150 | 
             
             * 
         | 
| 135 151 | 
             
             * If the function cannot be found then an API::Error is raised (a subclass
         | 
| 136 152 | 
             
             * of RuntimeError).
         | 
| 153 | 
            +
             * 
         | 
| 154 | 
            +
             * Example:
         | 
| 155 | 
            +
             * 
         | 
| 156 | 
            +
             *    require 'win32/api'
         | 
| 157 | 
            +
             *    include Win32
         | 
| 158 | 
            +
             * 
         | 
| 159 | 
            +
             *    buf = 0.chr * 260
         | 
| 160 | 
            +
             *    len = [buf.length].pack('L')
         | 
| 161 | 
            +
             *  
         | 
| 162 | 
            +
             *    GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
         | 
| 163 | 
            +
             *    GetUserName.call(buf, len)
         | 
| 164 | 
            +
             * 
         | 
| 165 | 
            +
             *    puts buf.strip
         | 
| 137 166 | 
             
             */
         | 
| 138 167 | 
             
            static VALUE api_init(int argc, VALUE* argv, VALUE self)
         | 
| 139 168 | 
             
            {
         | 
| @@ -149,25 +178,25 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 149 178 |  | 
| 150 179 | 
             
               Data_Get_Struct(self, Win32API, ptr);
         | 
| 151 180 |  | 
| 152 | 
            -
                | 
| 181 | 
            +
               // Convert a string prototype to an array of characters
         | 
| 153 182 | 
             
               if(rb_respond_to(v_proto, rb_intern("split")))
         | 
| 154 183 | 
             
                  v_proto = rb_str_split(v_proto, "");
         | 
| 155 184 |  | 
| 156 | 
            -
                | 
| 157 | 
            -
               if(16 < RARRAY(v_proto)->len)
         | 
| 158 | 
            -
                  rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
         | 
| 159 | 
            -
             | 
| 160 | 
            -
               /* Convert a nil or empty prototype to 'V' (void) automatically */
         | 
| 185 | 
            +
               // Convert a nil or empty prototype to 'V' (void) automatically
         | 
| 161 186 | 
             
               if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
         | 
| 162 187 | 
             
                  v_proto = rb_ary_new();
         | 
| 163 188 | 
             
                  rb_ary_push(v_proto, rb_str_new2("V"));
         | 
| 164 189 | 
             
               }
         | 
| 190 | 
            +
             | 
| 191 | 
            +
               // Set an arbitrary limit of 16 parameters
         | 
| 192 | 
            +
               if(16 < RARRAY(v_proto)->len)
         | 
| 193 | 
            +
                  rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
         | 
| 165 194 |  | 
| 166 | 
            -
                | 
| 195 | 
            +
               // Set the default dll to 'kernel32'
         | 
| 167 196 | 
             
               if(NIL_P(v_dll))
         | 
| 168 197 | 
             
               	v_dll = rb_str_new2("kernel32");
         | 
| 169 198 |  | 
| 170 | 
            -
                | 
| 199 | 
            +
               // Set the default return type to 'L' (DWORD)
         | 
| 171 200 | 
             
               if(NIL_P(v_return))
         | 
| 172 201 | 
             
               	v_return = rb_str_new2("L");
         | 
| 173 202 |  | 
| @@ -176,7 +205,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 176 205 |  | 
| 177 206 | 
             
               hLibrary = LoadLibrary(TEXT(RSTRING(v_dll)->ptr));
         | 
| 178 207 |  | 
| 179 | 
            -
                | 
| 208 | 
            +
               // The most likely cause of failure is a bad DLL load path
         | 
| 180 209 | 
             
               if(!hLibrary){
         | 
| 181 210 | 
             
                  rb_raise(cAPIError, "LoadLibrary() function failed for '%s': %s",
         | 
| 182 211 | 
             
                     RSTRING(v_dll)->ptr,
         | 
| @@ -192,7 +221,7 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 192 221 | 
             
                */
         | 
| 193 222 | 
             
               fProc = GetProcAddress(hLibrary, TEXT(RSTRING(v_proc)->ptr));
         | 
| 194 223 |  | 
| 195 | 
            -
                | 
| 224 | 
            +
               // The order of 'A' and 'W' is reversed if $KCODE is set to 'UTF8'.
         | 
| 196 225 | 
             
               if(!strcmp(rb_get_kcode(), "UTF8")){
         | 
| 197 226 | 
             
                  first  = "W";
         | 
| 198 227 | 
             
                  second = "A";
         | 
| @@ -232,7 +261,8 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 232 261 |  | 
| 233 262 | 
             
               ptr->function = fProc;
         | 
| 234 263 |  | 
| 235 | 
            -
                | 
| 264 | 
            +
               // Push the numeric prototypes onto our int array for later use.
         | 
| 265 | 
            +
             | 
| 236 266 | 
             
               for(i = 0; i < RARRAY(v_proto)->len; i++){
         | 
| 237 267 | 
             
                  SafeStringValue(RARRAY(v_proto)->ptr[i]);
         | 
| 238 268 | 
             
                  switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
         | 
| @@ -256,9 +286,9 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 256 286 | 
             
                  }
         | 
| 257 287 | 
             
               }
         | 
| 258 288 |  | 
| 259 | 
            -
                | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 289 | 
            +
               // Store the return type for later use.
         | 
| 290 | 
            +
             | 
| 291 | 
            +
               // Automatically convert empty strings or nil to type void.
         | 
| 262 292 | 
             
               if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
         | 
| 263 293 | 
             
                  v_return = rb_str_new2("V");
         | 
| 264 294 | 
             
                  ptr->return_type = _T_VOID;
         | 
| @@ -291,6 +321,121 @@ static VALUE api_init(int argc, VALUE* argv, VALUE self) | |
| 291 321 | 
             
               return self;
         | 
| 292 322 | 
             
            }
         | 
| 293 323 |  | 
| 324 | 
            +
            /*
         | 
| 325 | 
            +
             * call-seq:
         | 
| 326 | 
            +
             *
         | 
| 327 | 
            +
             *    API::Function.new(address, prototype = 'V', return_type = 'L')
         | 
| 328 | 
            +
             *
         | 
| 329 | 
            +
             * Creates and returns an API::Function object. This object is similar to an
         | 
| 330 | 
            +
             * API object, except that instead of a character function name you pass a
         | 
| 331 | 
            +
             * function pointer address as the first argument, and there's no associated
         | 
| 332 | 
            +
             * DLL file.
         | 
| 333 | 
            +
             *
         | 
| 334 | 
            +
             * Once you have your API::Function object you can then call it the same way
         | 
| 335 | 
            +
             * you would an API object.
         | 
| 336 | 
            +
             *
         | 
| 337 | 
            +
             * Example:
         | 
| 338 | 
            +
             *
         | 
| 339 | 
            +
             *    require 'win32/api'
         | 
| 340 | 
            +
             *    include Win32
         | 
| 341 | 
            +
             *
         | 
| 342 | 
            +
             *    LoadLibrary = API.new('LoadLibrary', 'P', 'L')
         | 
| 343 | 
            +
             *    GetProcAddress = API.new('GetProcAddress', 'LP', 'L')
         | 
| 344 | 
            +
             *
         | 
| 345 | 
            +
             *    # Play a system beep
         | 
| 346 | 
            +
             *    hlib = LoadLibrary.call('user32')
         | 
| 347 | 
            +
             *    addr = GetProcAddress.call(hlib, 'MessageBeep')
         | 
| 348 | 
            +
             *    func = Win32::API::Function.new(addr, 'L', 'L')
         | 
| 349 | 
            +
             *    func.call(0)
         | 
| 350 | 
            +
             */
         | 
| 351 | 
            +
            static VALUE func_init(int argc, VALUE* argv, VALUE self){
         | 
| 352 | 
            +
               Win32API* ptr;
         | 
| 353 | 
            +
               int i;
         | 
| 354 | 
            +
               VALUE v_address, v_proto, v_return;
         | 
| 355 | 
            +
             | 
| 356 | 
            +
               rb_scan_args(argc, argv, "12", &v_address, &v_proto, &v_return);
         | 
| 357 | 
            +
             | 
| 358 | 
            +
               Data_Get_Struct(self, Win32API, ptr);
         | 
| 359 | 
            +
             | 
| 360 | 
            +
               // Convert a string prototype to an array of characters
         | 
| 361 | 
            +
               if(rb_respond_to(v_proto, rb_intern("split")))
         | 
| 362 | 
            +
                  v_proto = rb_str_split(v_proto, "");
         | 
| 363 | 
            +
             | 
| 364 | 
            +
               // Convert a nil or empty prototype to 'V' (void) automatically
         | 
| 365 | 
            +
               if(NIL_P(v_proto) || RARRAY(v_proto)->len == 0){
         | 
| 366 | 
            +
                  v_proto = rb_ary_new();
         | 
| 367 | 
            +
                  rb_ary_push(v_proto, rb_str_new2("V"));
         | 
| 368 | 
            +
               }
         | 
| 369 | 
            +
             | 
| 370 | 
            +
               // Set an arbitrary limit of 16 parameters
         | 
| 371 | 
            +
               if(16 < RARRAY(v_proto)->len)
         | 
| 372 | 
            +
                  rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY(v_proto)->len);
         | 
| 373 | 
            +
             | 
| 374 | 
            +
               // Set the default return type to 'L' (DWORD)
         | 
| 375 | 
            +
               if(NIL_P(v_return))
         | 
| 376 | 
            +
               	v_return = rb_str_new2("L");
         | 
| 377 | 
            +
             | 
| 378 | 
            +
               ptr->function = (FARPROC)NUM2LONG(v_address);
         | 
| 379 | 
            +
             | 
| 380 | 
            +
               // Push the numeric prototypes onto our int array for later use.
         | 
| 381 | 
            +
             | 
| 382 | 
            +
               for(i = 0; i < RARRAY(v_proto)->len; i++){
         | 
| 383 | 
            +
                  SafeStringValue(RARRAY(v_proto)->ptr[i]);
         | 
| 384 | 
            +
                  switch(*(char*)StringValuePtr(RARRAY(v_proto)->ptr[i])){
         | 
| 385 | 
            +
                     case 'L':
         | 
| 386 | 
            +
                        ptr->prototype[i] = _T_LONG;
         | 
| 387 | 
            +
                        break;
         | 
| 388 | 
            +
                     case 'P':
         | 
| 389 | 
            +
                        ptr->prototype[i] = _T_POINTER;
         | 
| 390 | 
            +
                        break;
         | 
| 391 | 
            +
                     case 'I': case 'B':
         | 
| 392 | 
            +
                        ptr->prototype[i] = _T_INTEGER;
         | 
| 393 | 
            +
                        break;
         | 
| 394 | 
            +
                     case 'V':
         | 
| 395 | 
            +
                        ptr->prototype[i] = _T_VOID;
         | 
| 396 | 
            +
                        break;
         | 
| 397 | 
            +
                     case 'K':
         | 
| 398 | 
            +
                        ptr->prototype[i] = _T_CALLBACK;
         | 
| 399 | 
            +
                        break;
         | 
| 400 | 
            +
                     default:
         | 
| 401 | 
            +
                        rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
         | 
| 402 | 
            +
                  }
         | 
| 403 | 
            +
               }
         | 
| 404 | 
            +
             | 
| 405 | 
            +
               // Store the return type for later use.
         | 
| 406 | 
            +
             | 
| 407 | 
            +
               // Automatically convert empty strings or nil to type void.
         | 
| 408 | 
            +
               if(NIL_P(v_return) || RSTRING(v_return)->len == 0){
         | 
| 409 | 
            +
                  v_return = rb_str_new2("V");
         | 
| 410 | 
            +
                  ptr->return_type = _T_VOID;
         | 
| 411 | 
            +
               }
         | 
| 412 | 
            +
               else{
         | 
| 413 | 
            +
                  SafeStringValue(v_return);
         | 
| 414 | 
            +
                  switch(*RSTRING(v_return)->ptr){
         | 
| 415 | 
            +
                     case 'L':
         | 
| 416 | 
            +
                        ptr->return_type = _T_LONG;
         | 
| 417 | 
            +
                        break;
         | 
| 418 | 
            +
                     case 'P':
         | 
| 419 | 
            +
                        ptr->return_type = _T_POINTER;
         | 
| 420 | 
            +
                        break;
         | 
| 421 | 
            +
                     case 'I': case 'B':
         | 
| 422 | 
            +
                        ptr->return_type = _T_INTEGER;
         | 
| 423 | 
            +
                        break;
         | 
| 424 | 
            +
                     case 'V':
         | 
| 425 | 
            +
                        ptr->return_type = _T_VOID;
         | 
| 426 | 
            +
                        break;
         | 
| 427 | 
            +
                     default:
         | 
| 428 | 
            +
                        rb_raise(cAPIError, "Illegal prototype '%s'", RARRAY(v_proto)->ptr[i]);
         | 
| 429 | 
            +
                  }
         | 
| 430 | 
            +
               }
         | 
| 431 | 
            +
             | 
| 432 | 
            +
               rb_iv_set(self, "@address", v_address);
         | 
| 433 | 
            +
               rb_iv_set(self, "@prototype", v_proto);
         | 
| 434 | 
            +
               rb_iv_set(self, "@return_type", v_return);
         | 
| 435 | 
            +
             | 
| 436 | 
            +
               return self;
         | 
| 437 | 
            +
            }
         | 
| 438 | 
            +
             | 
| 294 439 | 
             
            typedef struct {
         | 
| 295 440 | 
             
               DWORD params[1];
         | 
| 296 441 | 
             
            } PARAM;
         | 
| @@ -481,7 +626,7 @@ static VALUE api_call(int argc, VALUE* argv, VALUE self){ | |
| 481 626 | 
             
             * Wraps the Windows API functions in a Ruby interface.
         | 
| 482 627 | 
             
             */
         | 
| 483 628 | 
             
            void Init_api(){
         | 
| 484 | 
            -
               VALUE mWin32, cAPI, cCallback;
         | 
| 629 | 
            +
               VALUE mWin32, cAPI, cCallback, cFunction;
         | 
| 485 630 |  | 
| 486 631 | 
             
               /* Modules and Classes */
         | 
| 487 632 |  | 
| @@ -493,6 +638,9 @@ void Init_api(){ | |
| 493 638 |  | 
| 494 639 | 
             
               /* The API::Callback class encapsulates a Windows CALLBACK function */ 
         | 
| 495 640 | 
             
               cCallback = rb_define_class_under(cAPI, "Callback", rb_cObject);
         | 
| 641 | 
            +
             | 
| 642 | 
            +
               /* The API::Function class encapsulates a raw function pointer */
         | 
| 643 | 
            +
               cFunction = rb_define_class_under(cAPI, "Function", cAPI);
         | 
| 496 644 |  | 
| 497 645 | 
             
               /* The API::Error class is raised if the constructor fails */
         | 
| 498 646 | 
             
               cAPIError = rb_define_class_under(cAPI, "Error", rb_eRuntimeError);
         | 
| @@ -507,7 +655,11 @@ void Init_api(){ | |
| 507 655 | 
             
               rb_define_method(cAPI, "initialize", api_init, -1);
         | 
| 508 656 | 
             
               rb_define_method(cAPI, "call", api_call, -1);
         | 
| 509 657 |  | 
| 658 | 
            +
               /* Win32::API::Callback Instance Methods */
         | 
| 510 659 | 
             
               rb_define_method(cCallback, "initialize", callback_init, -1);
         | 
| 660 | 
            +
             | 
| 661 | 
            +
               /* Win32::API::Function Instance Methods */
         | 
| 662 | 
            +
               rb_define_method(cFunction, "initialize", func_init, -1);
         | 
| 511 663 |  | 
| 512 664 | 
             
               /* The name of the DLL that exports the API function */
         | 
| 513 665 | 
             
               rb_define_attr(cAPI, "dll_name", 1, 0);
         | 
| @@ -534,6 +686,9 @@ void Init_api(){ | |
| 534 686 |  | 
| 535 687 | 
             
               /* The return type, returned as a single character, P, L, I, V or B */
         | 
| 536 688 | 
             
               rb_define_attr(cCallback, "return_type", 1, 0);
         | 
| 689 | 
            +
             | 
| 690 | 
            +
               /* The numeric address of the function pointer */
         | 
| 691 | 
            +
               rb_define_attr(cFunction, "address", 1, 0);
         | 
| 537 692 |  | 
| 538 693 | 
             
               /* Constants */
         | 
| 539 694 |  | 
    
        data/lib/win32/api.so
    CHANGED
    
    | Binary file | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            ############################################################################
         | 
| 2 | 
            -
            #  | 
| 2 | 
            +
            # test_win32_api.rb
         | 
| 3 3 | 
             
            # 
         | 
| 4 4 | 
             
            # Test case for the Win32::API class. You should run this as Rake task,
         | 
| 5 5 | 
             
            # i.e. 'rake test', instead of running it directly.
         | 
| @@ -16,7 +16,7 @@ class TC_Win32_API < Test::Unit::TestCase | |
| 16 16 | 
             
               end
         | 
| 17 17 |  | 
| 18 18 | 
             
               def test_version
         | 
| 19 | 
            -
                  assert_equal('1.0 | 
| 19 | 
            +
                  assert_equal('1.1.0', API::VERSION)
         | 
| 20 20 | 
             
               end
         | 
| 21 21 |  | 
| 22 22 | 
             
               def test_call
         | 
| @@ -43,6 +43,12 @@ class TC_Win32_API < Test::Unit::TestCase | |
| 43 43 | 
             
               def test_effective_function_name
         | 
| 44 44 | 
             
                  assert_respond_to(@api, :effective_function_name)
         | 
| 45 45 | 
             
                  assert_equal('GetCurrentDirectoryA', @api.effective_function_name)
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  @api = API.new('GetCurrentDirectoryA', 'LP')
         | 
| 48 | 
            +
                  assert_equal('GetCurrentDirectoryA', @api.effective_function_name)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  @api = API.new('GetCurrentDirectoryW', 'LP')
         | 
| 51 | 
            +
                  assert_equal('GetCurrentDirectoryW', @api.effective_function_name)
         | 
| 46 52 | 
             
               end
         | 
| 47 53 |  | 
| 48 54 | 
             
               def test_prototype
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            ############################################################################
         | 
| 2 | 
            -
            #  | 
| 2 | 
            +
            # test_win32_api_callback.rb
         | 
| 3 3 | 
             
            # 
         | 
| 4 4 | 
             
            # Test case for the Win32::API::Callback class. You should run this as Rake
         | 
| 5 5 | 
             
            # task, i.e. 'rake test', instead of running it directly.
         | 
| @@ -55,4 +55,4 @@ class TC_Win32_API_Callback < Test::Unit::TestCase | |
| 55 55 | 
             
                  @api_gwt  = nil
         | 
| 56 56 | 
             
                  @callback = nil
         | 
| 57 57 | 
             
               end
         | 
| 58 | 
            -
            end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            ########################################################################
         | 
| 2 | 
            +
            # test_win32_api_function.rb
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Test case for the Win32::API::Function class. You should run these
         | 
| 5 | 
            +
            # tests via the 'rake test' task.
         | 
| 6 | 
            +
            ########################################################################
         | 
| 7 | 
            +
            require 'test/unit'
         | 
| 8 | 
            +
            require 'win32/api'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class TC_Win32_API_Function < Test::Unit::TestCase
         | 
| 11 | 
            +
               def setup
         | 
| 12 | 
            +
                  @func = Win32::API::Function.new(123456789, 'LP', 'L')
         | 
| 13 | 
            +
               end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
               def test_constructor
         | 
| 16 | 
            +
                  assert_nothing_raised{ Win32::API::Function.new(1) }
         | 
| 17 | 
            +
                  assert_nothing_raised{ Win32::API::Function.new(1, 'LL') }
         | 
| 18 | 
            +
                  assert_nothing_raised{ Win32::API::Function.new(1, 'LL', 'I') }
         | 
| 19 | 
            +
               end
         | 
| 20 | 
            +
               
         | 
| 21 | 
            +
               def test_subclass
         | 
| 22 | 
            +
                  assert_kind_of(Win32::API, @func)
         | 
| 23 | 
            +
                  assert_respond_to(@func, :call)
         | 
| 24 | 
            +
               end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
               def test_address
         | 
| 27 | 
            +
                  assert_respond_to(@func, :address)
         | 
| 28 | 
            +
                  assert_equal(123456789, @func.address)
         | 
| 29 | 
            +
               end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
               def test_prototype
         | 
| 32 | 
            +
                  assert_respond_to(@func, :prototype)
         | 
| 33 | 
            +
                  assert_equal(['L', 'P'], @func.prototype)
         | 
| 34 | 
            +
               end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
               def test_return_type
         | 
| 37 | 
            +
                  assert_respond_to(@func, :return_type)
         | 
| 38 | 
            +
                  assert_equal('L', @func.return_type)
         | 
| 39 | 
            +
               end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
               def test_expected_errors
         | 
| 42 | 
            +
                  assert_raise(ArgumentError){ Win32::API::Function.new }
         | 
| 43 | 
            +
               end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
               def teardown
         | 
| 46 | 
            +
                  @func = nil
         | 
| 47 | 
            +
               end
         | 
| 48 | 
            +
            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.0 | 
| 4 | 
            +
              version: 1.1.0
         | 
| 5 5 | 
             
            platform: x86-mswin32-60
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Daniel J. Berger
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2008- | 
| 12 | 
            +
            date: 2008-06-12 00:00:00 -06:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: []
         | 
| 15 15 |  | 
| @@ -25,14 +25,17 @@ extra_rdoc_files: | |
| 25 25 | 
             
            - MANIFEST
         | 
| 26 26 | 
             
            - ext/win32/api.c
         | 
| 27 27 | 
             
            files: 
         | 
| 28 | 
            +
            - ext/extconf.rb
         | 
| 29 | 
            +
            - ext/win32
         | 
| 30 | 
            +
            - ext/win32/api.c
         | 
| 31 | 
            +
            - test/test_win32_api.rb
         | 
| 32 | 
            +
            - test/test_win32_api_callback.rb
         | 
| 33 | 
            +
            - test/test_win32_api_function.rb
         | 
| 28 34 | 
             
            - lib/win32
         | 
| 29 35 | 
             
            - lib/win32/api.so
         | 
| 30 | 
            -
            - test/tc_win32_api.rb
         | 
| 31 | 
            -
            - test/tc_win32_api_callback.rb
         | 
| 32 36 | 
             
            - README
         | 
| 33 37 | 
             
            - CHANGES
         | 
| 34 38 | 
             
            - MANIFEST
         | 
| 35 | 
            -
            - ext/win32/api.c
         | 
| 36 39 | 
             
            has_rdoc: true
         | 
| 37 40 | 
             
            homepage: http://www.rubyforge.org/projects/win32utils
         | 
| 38 41 | 
             
            post_install_message: 
         | 
| @@ -44,7 +47,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 44 47 | 
             
              requirements: 
         | 
| 45 48 | 
             
              - - ">="
         | 
| 46 49 | 
             
                - !ruby/object:Gem::Version 
         | 
| 47 | 
            -
                  version: 1.8. | 
| 50 | 
            +
                  version: 1.8.2
         | 
| 48 51 | 
             
              version: 
         | 
| 49 52 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 50 53 | 
             
              requirements: 
         | 
| @@ -59,6 +62,5 @@ rubygems_version: 1.1.1 | |
| 59 62 | 
             
            signing_key: 
         | 
| 60 63 | 
             
            specification_version: 2
         | 
| 61 64 | 
             
            summary: A superior replacement for Win32API
         | 
| 62 | 
            -
            test_files: 
         | 
| 63 | 
            -
             | 
| 64 | 
            -
            - test/tc_win32_api_callback.rb
         | 
| 65 | 
            +
            test_files: []
         | 
| 66 | 
            +
             |