diff options
Diffstat (limited to 'ext/fiddle')
| -rw-r--r-- | ext/fiddle/closure.c | 316 | ||||
| -rw-r--r-- | ext/fiddle/closure.h | 8 | ||||
| -rw-r--r-- | ext/fiddle/conversions.c | 141 | ||||
| -rw-r--r-- | ext/fiddle/conversions.h | 44 | ||||
| -rw-r--r-- | ext/fiddle/depend | 4 | ||||
| -rw-r--r-- | ext/fiddle/extconf.rb | 58 | ||||
| -rw-r--r-- | ext/fiddle/fiddle.c | 458 | ||||
| -rw-r--r-- | ext/fiddle/fiddle.h | 143 | ||||
| -rw-r--r-- | ext/fiddle/function.c | 245 | ||||
| -rw-r--r-- | ext/fiddle/function.h | 8 | ||||
| -rw-r--r-- | ext/fiddle/handle.c | 469 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle.rb | 46 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/closure.rb | 48 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/cparser.rb | 176 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/function.rb | 17 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/import.rb | 314 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/pack.rb | 128 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/struct.rb | 243 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/types.rb | 71 | ||||
| -rw-r--r-- | ext/fiddle/lib/fiddle/value.rb | 112 | ||||
| -rw-r--r-- | ext/fiddle/pointer.c | 716 | ||||
| -rw-r--r-- | ext/fiddle/win32/extconf.rb | 3 | ||||
| -rw-r--r-- | ext/fiddle/win32/lib/win32/registry.rb | 845 | ||||
| -rw-r--r-- | ext/fiddle/win32/lib/win32/resolv.rb | 379 |
24 files changed, 0 insertions, 4992 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c deleted file mode 100644 index 121a08ea19..0000000000 --- a/ext/fiddle/closure.c +++ /dev/null @@ -1,316 +0,0 @@ -#include <fiddle.h> - -VALUE cFiddleClosure; - -typedef struct { - void * code; - ffi_closure *pcl; - ffi_cif cif; - int argc; - ffi_type **argv; -} fiddle_closure; - -#if defined(USE_FFI_CLOSURE_ALLOC) -#elif defined(__OpenBSD__) || defined(__APPLE__) || defined(__linux__) -# define USE_FFI_CLOSURE_ALLOC 0 -#elif defined(RUBY_LIBFFI_MODVERSION) && RUBY_LIBFFI_MODVERSION < 3000005 && \ - (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)) -# define USE_FFI_CLOSURE_ALLOC 0 -#else -# define USE_FFI_CLOSURE_ALLOC 1 -#endif - -static void -dealloc(void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; -#if USE_FFI_CLOSURE_ALLOC - ffi_closure_free(cls->pcl); -#else - munmap(cls->pcl, sizeof(cls->pcl)); -#endif - if (cls->argv) xfree(cls->argv); - xfree(cls); -} - -static size_t -closure_memsize(const void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; - size_t size = 0; - - if (ptr) { - size += sizeof(*cls); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(&cls->cif); -#endif - size += sizeof(*cls->argv); - size += sizeof(ffi_closure); - } - return size; -} - -const rb_data_type_t closure_data_type = { - "fiddle/closure", - {0, dealloc, closure_memsize,}, -}; - -void -callback(ffi_cif *cif, void *resp, void **args, void *ctx) -{ - VALUE self = (VALUE)ctx; - VALUE rbargs = rb_iv_get(self, "@args"); - VALUE ctype = rb_iv_get(self, "@ctype"); - int argc = RARRAY_LENINT(rbargs); - VALUE params = rb_ary_tmp_new(argc); - VALUE ret; - VALUE cPointer; - int i, type; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - for (i = 0; i < argc; i++) { - type = NUM2INT(RARRAY_PTR(rbargs)[i]); - switch (type) { - case TYPE_VOID: - argc = 0; - break; - case TYPE_INT: - rb_ary_push(params, INT2NUM(*(int *)args[i])); - break; - case -TYPE_INT: - rb_ary_push(params, UINT2NUM(*(unsigned int *)args[i])); - break; - case TYPE_VOIDP: - rb_ary_push(params, - rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM(*(void **)args[i]))); - break; - case TYPE_LONG: - rb_ary_push(params, LONG2NUM(*(long *)args[i])); - break; - case -TYPE_LONG: - rb_ary_push(params, ULONG2NUM(*(unsigned long *)args[i])); - break; - case TYPE_CHAR: - rb_ary_push(params, INT2NUM(*(signed char *)args[i])); - break; - case -TYPE_CHAR: - rb_ary_push(params, UINT2NUM(*(unsigned char *)args[i])); - break; - case TYPE_SHORT: - rb_ary_push(params, INT2NUM(*(signed short *)args[i])); - break; - case -TYPE_SHORT: - rb_ary_push(params, UINT2NUM(*(unsigned short *)args[i])); - break; - case TYPE_DOUBLE: - rb_ary_push(params, rb_float_new(*(double *)args[i])); - break; - case TYPE_FLOAT: - rb_ary_push(params, rb_float_new(*(float *)args[i])); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - rb_ary_push(params, LL2NUM(*(LONG_LONG *)args[i])); - break; - case -TYPE_LONG_LONG: - rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)args[i])); - break; -#endif - default: - rb_raise(rb_eRuntimeError, "closure args: %d", type); - } - } - - ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_PTR(params)); - RB_GC_GUARD(params); - - type = NUM2INT(ctype); - switch (type) { - case TYPE_VOID: - break; - case TYPE_LONG: - *(long *)resp = NUM2LONG(ret); - break; - case -TYPE_LONG: - *(unsigned long *)resp = NUM2ULONG(ret); - break; - case TYPE_CHAR: - case TYPE_SHORT: - case TYPE_INT: - *(ffi_sarg *)resp = NUM2INT(ret); - break; - case -TYPE_CHAR: - case -TYPE_SHORT: - case -TYPE_INT: - *(ffi_arg *)resp = NUM2UINT(ret); - break; - case TYPE_VOIDP: - *(void **)resp = NUM2PTR(ret); - break; - case TYPE_DOUBLE: - *(double *)resp = NUM2DBL(ret); - break; - case TYPE_FLOAT: - *(float *)resp = (float)NUM2DBL(ret); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - *(LONG_LONG *)resp = NUM2LL(ret); - break; - case -TYPE_LONG_LONG: - *(unsigned LONG_LONG *)resp = NUM2ULL(ret); - break; -#endif - default: - rb_raise(rb_eRuntimeError, "closure retval: %d", type); - } -} - -static VALUE -allocate(VALUE klass) -{ - fiddle_closure * closure; - - VALUE i = TypedData_Make_Struct(klass, fiddle_closure, - &closure_data_type, closure); - -#if USE_FFI_CLOSURE_ALLOC - closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code); -#else - closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); -#endif - - return i; -} - -static VALUE -initialize(int rbargc, VALUE argv[], VALUE self) -{ - VALUE ret; - VALUE args; - VALUE abi; - fiddle_closure * cl; - ffi_cif * cif; - ffi_closure *pcl; - ffi_status result; - int i, argc; - - if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi)) - abi = INT2NUM(FFI_DEFAULT_ABI); - - Check_Type(args, T_ARRAY); - - argc = RARRAY_LENINT(args); - - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); - - cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); - - for (i = 0; i < argc; i++) { - int type = NUM2INT(RARRAY_PTR(args)[i]); - cl->argv[i] = INT2FFI_TYPE(type); - } - cl->argv[argc] = NULL; - - rb_iv_set(self, "@ctype", ret); - rb_iv_set(self, "@args", args); - - cif = &cl->cif; - pcl = cl->pcl; - - result = ffi_prep_cif(cif, NUM2INT(abi), argc, - INT2FFI_TYPE(NUM2INT(ret)), - cl->argv); - - if (FFI_OK != result) - rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); - -#if USE_FFI_CLOSURE_ALLOC - result = ffi_prep_closure_loc(pcl, cif, callback, - (void *)self, cl->code); -#else - result = ffi_prep_closure(pcl, cif, callback, (void *)self); - cl->code = (void *)pcl; - i = mprotect(pcl, sizeof(pcl), PROT_READ | PROT_EXEC); - if (i) { - rb_sys_fail("mprotect"); - } -#endif - - if (FFI_OK != result) - rb_raise(rb_eRuntimeError, "error prepping closure %d", result); - - return self; -} - -static VALUE -to_i(VALUE self) -{ - fiddle_closure * cl; - void *code; - - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); - - code = cl->code; - - return PTR2NUM(code); -} - -void -Init_fiddle_closure() -{ -#if 0 - mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */ -#endif - - /* - * Document-class: Fiddle::Closure - * - * == Description - * - * An FFI closure wrapper, for handling callbacks. - * - * == Example - * - * closure = Class.new(Fiddle::Closure) { - * def call - * 10 - * end - * }.new(Fiddle::TYPE_INT, []) - * #=> #<#<Class:0x0000000150d308>:0x0000000150d240> - * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT) - * #=> #<Fiddle::Function:0x00000001516e58> - * func.call - * #=> 10 - */ - cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject); - - rb_define_alloc_func(cFiddleClosure, allocate); - - /* - * Document-method: new - * - * call-seq: new(ret, args, abi = Fiddle::DEFAULT) - * - * Construct a new Closure object. - * - * * +ret+ is the C type to be returned - * * +args+ is an Array of arguments, passed to the callback function - * * +abi+ is the abi of the closure - * - * If there is an error in preparing the ffi_cif or ffi_prep_closure, - * then a RuntimeError will be raised. - */ - rb_define_method(cFiddleClosure, "initialize", initialize, -1); - - /* - * Document-method: to_i - * - * Returns the memory address for this closure - */ - rb_define_method(cFiddleClosure, "to_i", to_i, 0); -} -/* vim: set noet sw=4 sts=4 */ diff --git a/ext/fiddle/closure.h b/ext/fiddle/closure.h deleted file mode 100644 index 1e870e2285..0000000000 --- a/ext/fiddle/closure.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_CLOSURE_H -#define FIDDLE_CLOSURE_H - -#include <fiddle.h> - -void Init_fiddle_closure(); - -#endif diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c deleted file mode 100644 index d40ddc1f38..0000000000 --- a/ext/fiddle/conversions.c +++ /dev/null @@ -1,141 +0,0 @@ -#include <fiddle.h> - -ffi_type * -int_to_ffi_type(int type) -{ - int signed_p = 1; - - if (type < 0) { - type = -1 * type; - signed_p = 0; - } - -#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t) - - switch (type) { - case TYPE_VOID: - return &ffi_type_void; - case TYPE_VOIDP: - return &ffi_type_pointer; - case TYPE_CHAR: - return rb_ffi_type_of(char); - case TYPE_SHORT: - return rb_ffi_type_of(short); - case TYPE_INT: - return rb_ffi_type_of(int); - case TYPE_LONG: - return rb_ffi_type_of(long); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return rb_ffi_type_of(long_long); -#endif - case TYPE_FLOAT: - return &ffi_type_float; - case TYPE_DOUBLE: - return &ffi_type_double; - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } - return &ffi_type_pointer; -} - -void -value_to_generic(int type, VALUE src, fiddle_generic * dst) -{ - switch (type) { - case TYPE_VOID: - break; - case TYPE_VOIDP: - dst->pointer = NUM2PTR(rb_Integer(src)); - break; - case TYPE_CHAR: - dst->schar = (signed char)NUM2INT(src); - break; - case -TYPE_CHAR: - dst->uchar = (unsigned char)NUM2UINT(src); - break; - case TYPE_SHORT: - dst->sshort = (unsigned short)NUM2INT(src); - break; - case -TYPE_SHORT: - dst->sshort = (signed short)NUM2UINT(src); - break; - case TYPE_INT: - dst->sint = NUM2INT(src); - break; - case -TYPE_INT: - dst->uint = NUM2UINT(src); - break; - case TYPE_LONG: - dst->slong = NUM2LONG(src); - break; - case -TYPE_LONG: - dst->ulong = NUM2ULONG(src); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - dst->slong_long = NUM2LL(src); - break; - case -TYPE_LONG_LONG: - dst->ulong_long = NUM2ULL(src); - break; -#endif - case TYPE_FLOAT: - dst->ffloat = (float)NUM2DBL(src); - break; - case TYPE_DOUBLE: - dst->ddouble = NUM2DBL(src); - break; - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } -} - -VALUE -generic_to_value(VALUE rettype, fiddle_generic retval) -{ - int type = NUM2INT(rettype); - VALUE cPointer; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - switch (type) { - case TYPE_VOID: - return Qnil; - case TYPE_VOIDP: - return rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM((void *)retval.pointer)); - case TYPE_CHAR: - return INT2NUM((signed char)retval.fffi_sarg); - case -TYPE_CHAR: - return INT2NUM((unsigned char)retval.fffi_arg); - case TYPE_SHORT: - return INT2NUM((signed short)retval.fffi_sarg); - case -TYPE_SHORT: - return INT2NUM((unsigned short)retval.fffi_arg); - case TYPE_INT: - return INT2NUM((signed int)retval.fffi_sarg); - case -TYPE_INT: - return UINT2NUM((unsigned int)retval.fffi_arg); - case TYPE_LONG: - return LONG2NUM(retval.slong); - case -TYPE_LONG: - return ULONG2NUM(retval.ulong); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return LL2NUM(retval.slong_long); - case -TYPE_LONG_LONG: - return ULL2NUM(retval.ulong_long); -#endif - case TYPE_FLOAT: - return rb_float_new(retval.ffloat); - case TYPE_DOUBLE: - return rb_float_new(retval.ddouble); - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } - - UNREACHABLE; -} - -/* vim: set noet sw=4 sts=4 */ diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h deleted file mode 100644 index d0a08d6bc0..0000000000 --- a/ext/fiddle/conversions.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef FIDDLE_CONVERSIONS_H -#define FIDDLE_CONVERSIONS_H - -#include <fiddle.h> - -typedef union -{ - ffi_arg fffi_arg; /* rvalue smaller than unsigned long */ - ffi_sarg fffi_sarg; /* rvalue smaller than signed long */ - unsigned char uchar; /* ffi_type_uchar */ - signed char schar; /* ffi_type_schar */ - unsigned short ushort; /* ffi_type_sshort */ - signed short sshort; /* ffi_type_ushort */ - unsigned int uint; /* ffi_type_uint */ - signed int sint; /* ffi_type_sint */ - unsigned long ulong; /* ffi_type_ulong */ - signed long slong; /* ffi_type_slong */ - float ffloat; /* ffi_type_float */ - double ddouble; /* ffi_type_double */ -#if HAVE_LONG_LONG - unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */ - signed LONG_LONG slong_long; /* ffi_type_ulong_long */ -#endif - void * pointer; /* ffi_type_pointer */ -} fiddle_generic; - -ffi_type * int_to_ffi_type(int type); -void value_to_generic(int type, VALUE src, fiddle_generic * dst); -VALUE generic_to_value(VALUE rettype, fiddle_generic retval); - -#define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst)) -#define INT2FFI_TYPE(_type) int_to_ffi_type(_type) -#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval)) - -#if SIZEOF_VOIDP == SIZEOF_LONG -# define PTR2NUM(x) (ULONG2NUM((unsigned long)(x))) -# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) -#else -/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */ -# define PTR2NUM(x) (ULL2NUM((unsigned long long)(x))) -# define NUM2PTR(x) ((void*)(NUM2ULL(x))) -#endif - -#endif diff --git a/ext/fiddle/depend b/ext/fiddle/depend deleted file mode 100644 index e786dc71d2..0000000000 --- a/ext/fiddle/depend +++ /dev/null @@ -1,4 +0,0 @@ -$(OBJS): $(HDRS) $(ruby_headers) \ - $(hdrdir)/ruby/io.h \ - $(hdrdir)/ruby/encoding.h \ - $(hdrdir)/ruby/oniguruma.h diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb deleted file mode 100644 index 9c7991ec44..0000000000 --- a/ext/fiddle/extconf.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'mkmf' - -# :stopdoc: - -dir_config 'libffi' - -pkg_config("libffi") -if ver = pkg_config("libffi", "modversion") - $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver.split('.') }}) -end - -unless have_header('ffi.h') - if have_header('ffi/ffi.h') - $defs.push(format('-DUSE_HEADER_HACKS')) - else - raise "ffi.h is missing. Please install libffi." - end -end - -unless have_library('ffi') || have_library('libffi') - raise "libffi is missing. Please install libffi." -end - -have_header 'sys/mman.h' - -if have_header "dlfcn.h" - have_library "dl" - - %w{ dlopen dlclose dlsym }.each do |func| - abort "missing function #{func}" unless have_func(func) - end - - have_func "dlerror" -elsif have_header "windows.h" - %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func| - abort "missing function #{func}" unless have_func(func) - end -end - -have_const('FFI_STDCALL', 'ffi.h') || have_const('FFI_STDCALL', 'ffi/ffi.h') - -config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h"))) -types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil} -types.each do |type, signed| - if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config - if size = $2 and size != 'VOIDP' - size = types.fetch(size) {size} - $defs << format("-DTYPE_%s=TYPE_%s", signed||type, size) - end - if signed - check_signedness(type.downcase, "stddef.h") - end - end -end - -create_makefile 'fiddle' - -# :startdoc: diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c deleted file mode 100644 index 89644301aa..0000000000 --- a/ext/fiddle/fiddle.c +++ /dev/null @@ -1,458 +0,0 @@ -#include <fiddle.h> - -VALUE mFiddle; -VALUE rb_eFiddleError; - -#ifndef TYPE_SSIZE_T -# if SIZEOF_SIZE_T == SIZEOF_INT -# define TYPE_SSIZE_T TYPE_INT -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define TYPE_SSIZE_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG -# define TYPE_SSIZE_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T) - -#ifndef TYPE_PTRDIFF_T -# if SIZEOF_PTRDIFF_T == SIZEOF_INT -# define TYPE_PTRDIFF_T TYPE_INT -# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG -# define TYPE_PTRDIFF_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG -# define TYPE_PTRDIFF_T TYPE_LONG_LONG -# endif -#endif - -#ifndef TYPE_INTPTR_T -# if SIZEOF_INTPTR_T == SIZEOF_INT -# define TYPE_INTPTR_T TYPE_INT -# elif SIZEOF_INTPTR_T == SIZEOF_LONG -# define TYPE_INTPTR_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG -# define TYPE_INTPTR_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_UINTPTR_T (-TYPE_INTPTR_T) - -void Init_fiddle_pointer(void); - -/* - * call-seq: Fiddle.malloc(size) - * - * Allocate +size+ bytes of memory and return the integer memory address - * for the allocated memory. - */ -static VALUE -rb_fiddle_malloc(VALUE self, VALUE size) -{ - void *ptr; - - rb_secure(4); - ptr = (void*)ruby_xmalloc(NUM2INT(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.realloc(addr, size) - * - * Change the size of the memory allocated at the memory location +addr+ to - * +size+ bytes. Returns the memory address of the reallocated memory, which - * may be different than the address passed in. - */ -static VALUE -rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size) -{ - void *ptr = NUM2PTR(addr); - - rb_secure(4); - ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.free(addr) - * - * Free the memory at address +addr+ - */ -VALUE -rb_fiddle_free(VALUE self, VALUE addr) -{ - void *ptr = NUM2PTR(addr); - - rb_secure(4); - ruby_xfree(ptr); - return Qnil; -} - -/* - * call-seq: Fiddle.dlunwrap(addr) - * - * Returns the hexadecimal representation of a memory pointer address +addr+ - * - * Example: - * - * lib = Fiddle.dlopen('/lib64/libc-2.15.so') - * => #<Fiddle::Handle:0x00000001342460> - * - * lib['strcpy'].to_s(16) - * => "7f59de6dd240" - * - * Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16))) - * => "7f59de6dd240" - */ -VALUE -rb_fiddle_ptr2value(VALUE self, VALUE addr) -{ - rb_secure(4); - return (VALUE)NUM2PTR(addr); -} - -/* - * call-seq: Fiddle.dlwrap(val) - * - * Returns a memory pointer of a function's hexadecimal address location +val+ - * - * Example: - * - * lib = Fiddle.dlopen('/lib64/libc-2.15.so') - * => #<Fiddle::Handle:0x00000001342460> - * - * Fiddle.dlwrap(lib['strcpy'].to_s(16)) - * => 25522520 - */ -static VALUE -rb_fiddle_value2ptr(VALUE self, VALUE val) -{ - return PTR2NUM((void*)val); -} - -void Init_fiddle_handle(void); - -void -Init_fiddle(void) -{ - /* - * Document-module: Fiddle - * - * A libffi wrapper for Ruby. - * - * == Description - * - * Fiddle is an extension to translate a foreign function interface (FFI) - * with ruby. - * - * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library - * which provides a portable interface that allows code written in one - * language to clal code written in another language. - * - * == Example - * - * Here we will use Fiddle::Function to wrap {floor(3) from - * libm}[http://linux.die.net/man/3/floor] - * - * require 'fiddle' - * - * libm = Fiddle.dlopen('/lib/libm.so.6') - * - * floor = Fiddle::Function.new( - * libm['floor'], - * [Fiddle::TYPE_DOUBLE], - * Fiddle::TYPE_DOUBLE - * ) - * - * puts floor.call(3.14159) #=> 3.0 - * - * - */ - mFiddle = rb_define_module("Fiddle"); - - /* - * Document-class: Fiddle::DLError - * - * standard dynamic load exception - */ - rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError); - - /* Document-const: TYPE_VOID - * - * C type - void - */ - rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID)); - - /* Document-const: TYPE_VOIDP - * - * C type - void* - */ - rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP)); - - /* Document-const: TYPE_CHAR - * - * C type - char - */ - rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR)); - - /* Document-const: TYPE_SHORT - * - * C type - short - */ - rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT)); - - /* Document-const: TYPE_INT - * - * C type - int - */ - rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT)); - - /* Document-const: TYPE_LONG - * - * C type - long - */ - rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG)); - -#if HAVE_LONG_LONG - /* Document-const: TYPE_LONG_LONG - * - * C type - long long - */ - rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG)); -#endif - - /* Document-const: TYPE_FLOAT - * - * C type - float - */ - rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT)); - - /* Document-const: TYPE_DOUBLE - * - * C type - double - */ - rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE)); - - /* Document-const: TYPE_SIZE_T - * - * C type - size_t - */ - rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T)); - - /* Document-const: TYPE_SSIZE_T - * - * C type - ssize_t - */ - rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T)); - - /* Document-const: TYPE_PTRDIFF_T - * - * C type - ptrdiff_t - */ - rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); - - /* Document-const: TYPE_INTPTR_T - * - * C type - intptr_t - */ - rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T)); - - /* Document-const: TYPE_UINTPTR_T - * - * C type - uintptr_t - */ - rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T)); - - /* Document-const: ALIGN_VOIDP - * - * The alignment size of a void* - */ - rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); - - /* Document-const: ALIGN_CHAR - * - * The alignment size of a char - */ - rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); - - /* Document-const: ALIGN_SHORT - * - * The alignment size of a short - */ - rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); - - /* Document-const: ALIGN_INT - * - * The alignment size of an int - */ - rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT)); - - /* Document-const: ALIGN_LONG - * - * The alignment size of a long - */ - rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); - -#if HAVE_LONG_LONG - /* Document-const: ALIGN_LONG_LONG - * - * The alignment size of a long long - */ - rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); -#endif - - /* Document-const: ALIGN_FLOAT - * - * The alignment size of a float - */ - rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); - - /* Document-const: ALIGN_DOUBLE - * - * The alignment size of a double - */ - rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); - - /* Document-const: ALIGN_SIZE_T - * - * The alignment size of a size_t - */ - rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t))); - - /* Document-const: ALIGN_SSIZE_T - * - * The alignment size of a ssize_t - */ - rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */ - - /* Document-const: ALIGN_PTRDIFF_T - * - * The alignment size of a ptrdiff_t - */ - rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t))); - - /* Document-const: ALIGN_INTPTR_T - * - * The alignment size of a intptr_t - */ - rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t))); - - /* Document-const: ALIGN_UINTPTR_T - * - * The alignment size of a uintptr_t - */ - rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); - - /* Document-const: WINDOWS - * - * Returns a boolean regarding whether the host is WIN32 - */ -#if defined(_WIN32) - rb_define_const(mFiddle, "WINDOWS", Qtrue); -#else - rb_define_const(mFiddle, "WINDOWS", Qfalse); -#endif - - /* Document-const: SIZEOF_VOIDP - * - * size of a void* - */ - rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); - - /* Document-const: SIZEOF_CHAR - * - * size of a char - */ - rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char))); - - /* Document-const: SIZEOF_SHORT - * - * size of a short - */ - rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short))); - - /* Document-const: SIZEOF_INT - * - * size of an int - */ - rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int))); - - /* Document-const: SIZEOF_LONG - * - * size of a long - */ - rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long))); - -#if HAVE_LONG_LONG - /* Document-const: SIZEOF_LONG_LONG - * - * size of a long long - */ - rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); -#endif - - /* Document-const: SIZEOF_FLOAT - * - * size of a float - */ - rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); - - /* Document-const: SIZEOF_DOUBLE - * - * size of a double - */ - rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); - - /* Document-const: SIZEOF_SIZE_T - * - * size of a size_t - */ - rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t))); - - /* Document-const: SIZEOF_SSIZE_T - * - * size of a ssize_t - */ - rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */ - - /* Document-const: SIZEOF_PTRDIFF_T - * - * size of a ptrdiff_t - */ - rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t))); - - /* Document-const: SIZEOF_INTPTR_T - * - * size of a intptr_t - */ - rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t))); - - /* Document-const: SIZEOF_UINTPTR_T - * - * size of a uintptr_t - */ - rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t))); - - /* Document-const: RUBY_FREE - * - * Address of the ruby_xfree() function - */ - rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree)); - - /* Document-const: BUILD_RUBY_PLATFORM - * - * Platform built against (i.e. "x86_64-linux", etc.) - * - * See also RUBY_PLATFORM - */ - rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); - - rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1); - rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1); - rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1); - rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2); - rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1); - - Init_fiddle_function(); - Init_fiddle_closure(); - Init_fiddle_handle(); - Init_fiddle_pointer(); -} -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h deleted file mode 100644 index b37c37bc65..0000000000 --- a/ext/fiddle/fiddle.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef FIDDLE_H -#define FIDDLE_H - -#include <ruby.h> -#include <errno.h> - -#if defined(_WIN32) -#include <windows.h> -#endif - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#if defined(HAVE_DLFCN_H) -# include <dlfcn.h> -# /* some stranger systems may not define all of these */ -#ifndef RTLD_LAZY -#define RTLD_LAZY 0 -#endif -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif -#ifndef RTLD_NOW -#define RTLD_NOW 0 -#endif -#else -# if defined(_WIN32) -# include <windows.h> -# define dlopen(name,flag) ((void*)LoadLibrary(name)) -# define dlerror() strerror(rb_w32_map_errno(GetLastError())) -# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) -# define RTLD_LAZY -1 -# define RTLD_NOW -1 -# define RTLD_GLOBAL -1 -# endif -#endif - -#ifdef USE_HEADER_HACKS -#include <ffi/ffi.h> -#else -#include <ffi.h> -#endif - -#undef ffi_type_uchar -#undef ffi_type_schar -#undef ffi_type_ushort -#undef ffi_type_sshort -#undef ffi_type_uint -#undef ffi_type_sint -#undef ffi_type_ulong -#undef ffi_type_slong - -#if CHAR_BIT == 8 -# define ffi_type_uchar ffi_type_uint8 -# define ffi_type_schar ffi_type_sint8 -#else -# error "CHAR_BIT not supported" -#endif - -# if SIZEOF_SHORT == 2 -# define ffi_type_ushort ffi_type_uint16 -# define ffi_type_sshort ffi_type_sint16 -# elif SIZEOF_SHORT == 4 -# define ffi_type_ushort ffi_type_uint32 -# define ffi_type_sshort ffi_type_sint32 -# else -# error "short size not supported" -# endif - -# if SIZEOF_INT == 2 -# define ffi_type_uint ffi_type_uint16 -# define ffi_type_sint ffi_type_sint16 -# elif SIZEOF_INT == 4 -# define ffi_type_uint ffi_type_uint32 -# define ffi_type_sint ffi_type_sint32 -# elif SIZEOF_INT == 8 -# define ffi_type_uint ffi_type_uint64 -# define ffi_type_sint ffi_type_sint64 -# else -# error "int size not supported" -# endif - -# if SIZEOF_LONG == 4 -# define ffi_type_ulong ffi_type_uint32 -# define ffi_type_slong ffi_type_sint32 -# elif SIZEOF_LONG == 8 -# define ffi_type_ulong ffi_type_uint64 -# define ffi_type_slong ffi_type_sint64 -# else -# error "long size not supported" -# endif - -#if HAVE_LONG_LONG -# if SIZEOF_LONG_LONG == 8 -# define ffi_type_slong_long ffi_type_sint64 -# define ffi_type_ulong_long ffi_type_uint64 -# else -# error "long long size not supported" -# endif -#endif - -#include <closure.h> -#include <conversions.h> -#include <function.h> - -/* FIXME - * These constants need to match up with DL. We need to refactor this to use - * the DL header files or vice versa. - */ - -#define TYPE_VOID 0 -#define TYPE_VOIDP 1 -#define TYPE_CHAR 2 -#define TYPE_SHORT 3 -#define TYPE_INT 4 -#define TYPE_LONG 5 -#if HAVE_LONG_LONG -#define TYPE_LONG_LONG 6 -#endif -#define TYPE_FLOAT 7 -#define TYPE_DOUBLE 8 - -#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) - -#define ALIGN_VOIDP ALIGN_OF(void*) -#define ALIGN_SHORT ALIGN_OF(short) -#define ALIGN_CHAR ALIGN_OF(char) -#define ALIGN_INT ALIGN_OF(int) -#define ALIGN_LONG ALIGN_OF(long) -#if HAVE_LONG_LONG -#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG) -#endif -#define ALIGN_FLOAT ALIGN_OF(float) -#define ALIGN_DOUBLE ALIGN_OF(double) - -extern VALUE mFiddle; -extern VALUE rb_eFiddleError; - -VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type); - -#endif -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c deleted file mode 100644 index 72a1a6238d..0000000000 --- a/ext/fiddle/function.c +++ /dev/null @@ -1,245 +0,0 @@ -#include <fiddle.h> - -VALUE cFiddleFunction; - -static void -deallocate(void *p) -{ - ffi_cif *ptr = p; - if (ptr->arg_types) xfree(ptr->arg_types); - xfree(ptr); -} - -static size_t -function_memsize(const void *p) -{ - /* const */ffi_cif *ptr = (ffi_cif *)p; - size_t size = 0; - - if (ptr) { - size += sizeof(*ptr); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(ptr); -#endif - } - return size; -} - -const rb_data_type_t function_data_type = { - "fiddle/function", - {0, deallocate, function_memsize,}, -}; - -static VALUE -allocate(VALUE klass) -{ - ffi_cif * cif; - - return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif); -} - -VALUE -rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type) -{ - VALUE argv[3]; - - argv[0] = address; - argv[1] = arg_types; - argv[2] = ret_type; - - return rb_class_new_instance(3, argv, cFiddleFunction); -} - -static int -parse_keyword_arg_i(VALUE key, VALUE value, VALUE self) -{ - if (key == ID2SYM(rb_intern("name"))) { - rb_iv_set(self, "@name", value); - } else { - rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key); - } - return ST_CONTINUE; -} - -static VALUE -initialize(int argc, VALUE argv[], VALUE self) -{ - ffi_cif * cif; - ffi_type **arg_types; - ffi_status result; - VALUE ptr, args, ret_type, abi, kwds; - int i; - - rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds); - if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI); - - Check_Type(args, T_ARRAY); - - rb_iv_set(self, "@ptr", ptr); - rb_iv_set(self, "@args", args); - rb_iv_set(self, "@return_type", ret_type); - rb_iv_set(self, "@abi", abi); - - if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self); - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); - - arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *)); - - for (i = 0; i < RARRAY_LEN(args); i++) { - int type = NUM2INT(RARRAY_PTR(args)[i]); - arg_types[i] = INT2FFI_TYPE(type); - } - arg_types[RARRAY_LEN(args)] = NULL; - - result = ffi_prep_cif ( - cif, - NUM2INT(abi), - RARRAY_LENINT(args), - INT2FFI_TYPE(NUM2INT(ret_type)), - arg_types); - - if (result) - rb_raise(rb_eRuntimeError, "error creating CIF %d", result); - - return self; -} - -static VALUE -function_call(int argc, VALUE argv[], VALUE self) -{ - ffi_cif * cif; - fiddle_generic retval; - fiddle_generic *generic_args; - void **values; - VALUE cfunc, types, cPointer; - int i; - - cfunc = rb_iv_get(self, "@ptr"); - types = rb_iv_get(self, "@args"); - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - if(argc != RARRAY_LENINT(types)) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", - argc, RARRAY_LENINT(types)); - } - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); - - values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *)); - generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic)); - - for (i = 0; i < argc; i++) { - VALUE type = RARRAY_PTR(types)[i]; - VALUE src = argv[i]; - - if(NUM2INT(type) == TYPE_VOIDP) { - if(NIL_P(src)) { - src = INT2FIX(0); - } else if(cPointer != CLASS_OF(src)) { - src = rb_funcall(cPointer, rb_intern("[]"), 1, src); - } - src = rb_Integer(src); - } - - VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]); - values[i] = (void *)&generic_args[i]; - } - values[argc] = NULL; - - ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values); - - rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno)); -#if defined(_WIN32) - rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno)); -#endif - - xfree(values); - xfree(generic_args); - - return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval); -} - -void -Init_fiddle_function(void) -{ - /* - * Document-class: Fiddle::Function - * - * == Description - * - * A representation of a C function - * - * == Examples - * - * === 'strcpy' - * - * @libc = Fiddle.dlopen "/lib/libc.so.6" - * #=> #<Fiddle::Handle:0x00000001d7a8d8> - * f = Fiddle::Function.new( - * @libc['strcpy'], - * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], - * Fiddle::TYPE_VOIDP) - * #=> #<Fiddle::Function:0x00000001d8ee00> - * buff = "000" - * #=> "000" - * str = f.call(buff, "123") - * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000> - * str.to_s - * => "123" - * - * === ABI check - * - * @libc = DL.dlopen "/lib/libc.so.6" - * #=> #<Fiddle::Handle:0x00000001d7a8d8> - * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - * #=> #<Fiddle::Function:0x00000001d8ee00> - * f.abi == Fiddle::Function::DEFAULT - * #=> true - */ - cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject); - - /* - * Document-const: DEFAULT - * - * Default ABI - * - */ - rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI)); - -#ifdef HAVE_CONST_FFI_STDCALL - /* - * Document-const: STDCALL - * - * FFI implementation of WIN32 stdcall convention - * - */ - rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL)); -#endif - - rb_define_alloc_func(cFiddleFunction, allocate); - - /* - * Document-method: call - * - * Calls the constructed Function, with +args+ - * - * For an example see Fiddle::Function - * - */ - rb_define_method(cFiddleFunction, "call", function_call, -1); - - /* - * Document-method: new - * call-seq: new(ptr, args, ret_type, abi = DEFAULT) - * - * Constructs a Function object. - * * +ptr+ is a referenced function, of a Fiddle::Handle - * * +args+ is an Array of arguments, passed to the +ptr+ function - * * +ret_type+ is the return type of the function - * * +abi+ is the ABI of the function - * - */ - rb_define_method(cFiddleFunction, "initialize", initialize, -1); -} -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/function.h b/ext/fiddle/function.h deleted file mode 100644 index e5465ab64f..0000000000 --- a/ext/fiddle/function.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_FUNCTION_H -#define FIDDLE_FUNCTION_H - -#include <fiddle.h> - -void Init_fiddle_function(); - -#endif diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c deleted file mode 100644 index 832ff3319a..0000000000 --- a/ext/fiddle/handle.c +++ /dev/null @@ -1,469 +0,0 @@ -#include <ruby.h> -#include <fiddle.h> - -VALUE rb_cHandle; - -struct dl_handle { - void *ptr; - int open; - int enable_close; -}; - -#ifdef _WIN32 -# ifndef _WIN32_WCE -static void * -w32_coredll(void) -{ - MEMORY_BASIC_INFORMATION m; - memset(&m, 0, sizeof(m)); - if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL; - return m.AllocationBase; -} -# endif - -static int -w32_dlclose(void *ptr) -{ -# ifndef _WIN32_WCE - if( ptr == w32_coredll() ) return 0; -# endif - if( FreeLibrary((HMODULE)ptr) ) return 0; - return errno = rb_w32_map_errno(GetLastError()); -} -#define dlclose(ptr) w32_dlclose(ptr) -#endif - -static void -fiddle_handle_free(void *ptr) -{ - struct dl_handle *fiddle_handle = ptr; - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } -} - -static size_t -fiddle_handle_memsize(const void *ptr) -{ - return ptr ? sizeof(struct dl_handle) : 0; -} - -static const rb_data_type_t fiddle_handle_data_type = { - "fiddle/handle", - {0, fiddle_handle_free, fiddle_handle_memsize,}, -}; - -/* - * call-seq: close - * - * Close this handle. - * - * Calling close more than once will raise a Fiddle::DLError exception. - */ -static VALUE -rb_fiddle_handle_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if(fiddle_handle->open) { - int ret = dlclose(fiddle_handle->ptr); - fiddle_handle->open = 0; - - /* Check dlclose for successful return value */ - if(ret) { -#if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleError, "%s", dlerror()); -#else - rb_raise(rb_eFiddleError, "could not close handle"); -#endif - } - return INT2NUM(ret); - } - rb_raise(rb_eFiddleError, "dlclose() called too many times"); - - UNREACHABLE; -} - -static VALUE -rb_fiddle_handle_s_allocate(VALUE klass) -{ - VALUE obj; - struct dl_handle *fiddle_handle; - - obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->ptr = 0; - fiddle_handle->open = 0; - fiddle_handle->enable_close = 0; - - return obj; -} - -static VALUE -predefined_fiddle_handle(void *handle) -{ - VALUE obj = rb_fiddle_handle_s_allocate(rb_cHandle); - struct dl_handle *fiddle_handle = DATA_PTR(obj); - - fiddle_handle->ptr = handle; - fiddle_handle->open = 1; - OBJ_FREEZE(obj); - return obj; -} - -/* - * call-seq: - * new(lib = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * - * Create a new handler that opens library named +lib+ with +flags+. If no - * library is specified, RTLD_DEFAULT is used. - */ -static VALUE -rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self) -{ - void *ptr; - struct dl_handle *fiddle_handle; - VALUE lib, flag; - char *clib; - int cflag; - const char *err; - - switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){ - case 0: - clib = NULL; - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 1: - clib = NIL_P(lib) ? NULL : StringValuePtr(lib); - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 2: - clib = NIL_P(lib) ? NULL : StringValuePtr(lib); - cflag = NUM2INT(flag); - break; - default: - rb_bug("rb_fiddle_handle_new"); - } - - rb_secure(2); - -#if defined(_WIN32) - if( !clib ){ - HANDLE rb_libruby_handle(void); - ptr = rb_libruby_handle(); - } - else if( STRCASECMP(clib, "libc") == 0 -# ifdef RUBY_COREDLL - || STRCASECMP(clib, RUBY_COREDLL) == 0 - || STRCASECMP(clib, RUBY_COREDLL".dll") == 0 -# endif - ){ -# ifdef _WIN32_WCE - ptr = dlopen("coredll.dll", cflag); -# else - ptr = w32_coredll(); -# endif - } - else -#endif - ptr = dlopen(clib, cflag); -#if defined(HAVE_DLERROR) - if( !ptr && (err = dlerror()) ){ - rb_raise(rb_eFiddleError, "%s", err); - } -#else - if( !ptr ){ - err = dlerror(); - rb_raise(rb_eFiddleError, "%s", err); - } -#endif - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } - fiddle_handle->ptr = ptr; - fiddle_handle->open = 1; - fiddle_handle->enable_close = 0; - - if( rb_block_given_p() ){ - rb_ensure(rb_yield, self, rb_fiddle_handle_close, self); - } - - return Qnil; -} - -/* - * call-seq: enable_close - * - * Enable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_enable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 1; - return Qnil; -} - -/* - * call-seq: disable_close - * - * Disable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_disable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 0; - return Qnil; -} - -/* - * call-seq: close_enabled? - * - * Returns +true+ if dlclose() will be called when this handle is garbage collected. - * - * See man(3) dlclose() for more info. - */ -static VALUE -rb_fiddle_handle_close_enabled_p(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - - if(fiddle_handle->enable_close) return Qtrue; - return Qfalse; -} - -/* - * call-seq: to_i - * - * Returns the memory address for this handle. - */ -static VALUE -rb_fiddle_handle_to_i(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - return PTR2NUM(fiddle_handle); -} - -static VALUE fiddle_handle_sym(void *handle, const char *symbol); - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. - */ -static VALUE -rb_fiddle_handle_sym(VALUE self, VALUE sym) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( ! fiddle_handle->open ){ - rb_raise(rb_eFiddleError, "closed handle"); - } - - return fiddle_handle_sym(fiddle_handle->ptr, StringValueCStr(sym)); -} - -#ifndef RTLD_NEXT -#define RTLD_NEXT NULL -#endif -#ifndef RTLD_DEFAULT -#define RTLD_DEFAULT NULL -#endif - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. The function - * is searched via dlsym on RTLD_NEXT. - * - * See man(3) dlsym() for more info. - */ -static VALUE -rb_fiddle_handle_s_sym(VALUE self, VALUE sym) -{ - return fiddle_handle_sym(RTLD_NEXT, StringValueCStr(sym)); -} - -static VALUE -fiddle_handle_sym(void *handle, const char *name) -{ -#if defined(HAVE_DLERROR) - const char *err; -# define CHECK_DLERROR if( err = dlerror() ){ func = 0; } -#else -# define CHECK_DLERROR -#endif - void (*func)(); - - rb_secure(2); -#ifdef HAVE_DLERROR - dlerror(); -#endif - func = (void (*)())(VALUE)dlsym(handle, name); - CHECK_DLERROR; -#if defined(FUNC_STDCALL) - if( !func ){ - int i; - int len = (int)strlen(name); - char *name_n; -#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__) - { - char *name_a = (char*)xmalloc(len+2); - strcpy(name_a, name); - name_n = name_a; - name_a[len] = 'A'; - name_a[len+1] = '\0'; - func = dlsym(handle, name_a); - CHECK_DLERROR; - if( func ) goto found; - name_n = xrealloc(name_a, len+6); - } -#else - name_n = (char*)xmalloc(len+6); -#endif - memcpy(name_n, name, len); - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - if( func ) goto found; - name_n[len-1] = 'A'; - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - found: - xfree(name_n); - } -#endif - if( !func ){ - rb_raise(rb_eFiddleError, "unknown symbol \"%s\"", name); - } - - return PTR2NUM(func); -} - -void -Init_fiddle_handle(void) -{ - /* - * Document-class: Fiddle::Handle - * - * The Fiddle::Handle is the manner to access the dynamic library - * - * == Example - * - * === Setup - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so) - * => #<Fiddle::Handle:0x00000000d69ef8> - * - * === Setup, with flags - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * => #<Fiddle::Handle:0x00000000d69ef8> - * - * See RTLD_LAZY and RTLD_GLOBAL - * - * === Addresses to symbols - * - * strcpy_addr = @handle['strcpy'] - * => 140062278451968 - * - * or - * - * strcpy_addr = @handle.sym('strcpy') - * => 140062278451968 - * - */ - rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject); - rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate); - rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1); - rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1); - - /* Document-const: NEXT - * - * A predefined pseudo-handle of RTLD_NEXT - * - * Which will find the next occurrence of a function in the search order - * after the current library. - */ - rb_define_const(rb_cHandle, "NEXT", predefined_fiddle_handle(RTLD_NEXT)); - - /* Document-const: DEFAULT - * - * A predefined pseudo-handle of RTLD_DEFAULT - * - * Which will find the first occurrence of the desired symbol using the - * default library search order - */ - rb_define_const(rb_cHandle, "DEFAULT", predefined_fiddle_handle(RTLD_DEFAULT)); - - /* Document-const: RTLD_GLOBAL - * - * rtld Fiddle::Handle flag. - * - * The symbols defined by this library will be made available for symbol - * resolution of subsequently loaded libraries. - */ - rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); - - /* Document-const: RTLD_LAZY - * - * rtld Fiddle::Handle flag. - * - * Perform lazy binding. Only resolve symbols as the code that references - * them is executed. If the symbol is never referenced, then it is never - * resolved. (Lazy binding is only performed for function references; - * references to variables are always immediately bound when the library - * is loaded.) - */ - rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); - - /* Document-const: RTLD_NOW - * - * rtld Fiddle::Handle flag. - * - * If this value is specified or the environment variable LD_BIND_NOW is - * set to a nonempty string, all undefined symbols in the library are - * resolved before Fiddle.dlopen returns. If this cannot be done an error - * is returned. - */ - rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW)); - - rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1); - rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0); - rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0); - rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1); - rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1); - rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0); - rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0); - rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0); -} - -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb deleted file mode 100644 index c8a7ef1b05..0000000000 --- a/ext/fiddle/lib/fiddle.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'fiddle.so' -require 'fiddle/function' -require 'fiddle/closure' - -module Fiddle - if WINDOWS - # Returns the last win32 +Error+ of the current executing +Thread+ or nil - # if none - def self.win32_last_error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] - end - - # Sets the last win32 +Error+ of the current executing +Thread+ to +error+ - def self.win32_last_error= error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error - end - end - - # Returns the last +Error+ of the current executing +Thread+ or nil if none - def self.last_error - Thread.current[:__FIDDLE_LAST_ERROR__] - end - - # Sets the last +Error+ of the current executing +Thread+ to +error+ - def self.last_error= error - Thread.current[:__DL2_LAST_ERROR__] = error - Thread.current[:__FIDDLE_LAST_ERROR__] = error - end - - # call-seq: dlopen(library) => Fiddle::Handle - # - # Creates a new handler that opens +library+, and returns an instance of - # Fiddle::Handle. - # - # See Fiddle::Handle.new for more. - def dlopen library - Fiddle::Handle.new library - end - module_function :dlopen - - # Add constants for backwards compat - - RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc: - RTLD_LAZY = Handle::RTLD_LAZY # :nodoc: - RTLD_NOW = Handle::RTLD_NOW # :nodoc: -end diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb deleted file mode 100644 index beb90ecbe5..0000000000 --- a/ext/fiddle/lib/fiddle/closure.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Fiddle - class Closure - - # the C type of the return of the FFI closure - attr_reader :ctype - - # arguments of the FFI closure - attr_reader :args - - # Extends Fiddle::Closure to allow for building the closure in a block - class BlockCaller < Fiddle::Closure - - # == Description - # - # Construct a new BlockCaller object. - # - # * +ctype+ is the C type to be returned - # * +args+ are passed the callback - # * +abi+ is the abi of the closure - # - # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, - # then a RuntimeError will be raised. - # - # == Example - # - # include Fiddle - # - # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| - # one - # end - # - # func = Function.new(cb, [TYPE_INT], TYPE_INT) - # - def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block - super(ctype, args, abi) - @block = block - end - - # Calls the constructed BlockCaller, with +args+ - # - # For an example see Fiddle::Closure::BlockCaller.new - # - def call *args - @block.call(*args) - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb deleted file mode 100644 index 43fb184a12..0000000000 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ /dev/null @@ -1,176 +0,0 @@ -module Fiddle - # A mixin that provides methods for parsing C struct and prototype signatures. - # - # == Example - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int increment(int)') - # #=> ["increment", Fiddle::TYPE_INT, [Fiddle::TYPE_INT]] - # - module CParser - # Parses a C struct's members - # - # Example: - # - # include Fiddle::CParser - # #=> Object - # - # parse_struct_signature(['int i', 'char c']) - # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] - # - def parse_struct_signature(signature, tymap=nil) - if( signature.is_a?(String) ) - signature = signature.split(/\s*,\s*/) - end - mems = [] - tys = [] - signature.each{|msig| - tks = msig.split(/\s+(\*)?/) - ty = tks[0..-2].join(" ") - member = tks[-1] - - case ty - when /\[(\d+)\]/ - n = $1.to_i - ty.gsub!(/\s*\[\d+\]/,"") - ty = [ty, n] - when /\[\]/ - ty.gsub!(/\s*\[\]/, "*") - end - - case member - when /\[(\d+)\]/ - ty = [ty, $1.to_i] - member.gsub!(/\s*\[\d+\]/,"") - when /\[\]/ - ty = ty + "*" - member.gsub!(/\s*\[\]/, "") - end - - mems.push(member) - tys.push(parse_ctype(ty,tymap)) - } - return tys, mems - end - - # Parses a C prototype signature - # - # If Hash +tymap+ is provided, the return value and the arguments from the - # +signature+ are expected to be keys, and the value will be the C type to - # be looked up. - # - # Example: - # - # include Fiddle::CParser - # #=> Object - # - # parse_signature('double sum(double, double)') - # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] - # - def parse_signature(signature, tymap=nil) - tymap ||= {} - signature = signature.gsub(/\s+/, " ").strip - case signature - when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/ - ret = $1 - (args = $2).strip! - ret = ret.split(/\s+/) - args = args.split(/\s*,\s*/) - func = ret.pop - if( func =~ /^\*/ ) - func.gsub!(/^\*+/,"") - ret.push("*") - end - ret = ret.join(" ") - return [func, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}] - else - raise(RuntimeError,"can't parse the function prototype: #{signature}") - end - end - - # Given a String of C type +ty+, returns the corresponding Fiddle constant. - # - # +ty+ can also accept an Array of C type Strings, and will be returned in - # a corresponding Array. - # - # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the - # value will be the C type to be looked up. - # - # Example: - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int') - # #=> Fiddle::TYPE_INT - # - # parse_ctype('double') - # #=> Fiddle::TYPE_DOUBLE - # - # parse_ctype('unsigned char') - # #=> -Fiddle::TYPE_CHAR - # - def parse_ctype(ty, tymap=nil) - tymap ||= {} - case ty - when Array - return [parse_ctype(ty[0], tymap), ty[1]] - when "void" - return TYPE_VOID - when "char" - return TYPE_CHAR - when "unsigned char" - return -TYPE_CHAR - when "short" - return TYPE_SHORT - when "unsigned short" - return -TYPE_SHORT - when "int" - return TYPE_INT - when "unsigned int", 'uint' - return -TYPE_INT - when "long" - return TYPE_LONG - when "unsigned long" - return -TYPE_LONG - when "long long" - if( defined?(TYPE_LONG_LONG) ) - return TYPE_LONG_LONG - else - raise(RuntimeError, "unsupported type: #{ty}") - end - when "unsigned long long" - if( defined?(TYPE_LONG_LONG) ) - return -TYPE_LONG_LONG - else - raise(RuntimeError, "unsupported type: #{ty}") - end - when "float" - return TYPE_FLOAT - when "double" - return TYPE_DOUBLE - when "size_t" - return TYPE_SIZE_T - when "ssize_t" - return TYPE_SSIZE_T - when "ptrdiff_t" - return TYPE_PTRDIFF_T - when "intptr_t" - return TYPE_INTPTR_T - when "uintptr_t" - return TYPE_UINTPTR_T - when /\*/, /\[\s*\]/ - return TYPE_VOIDP - else - if( tymap[ty] ) - return parse_ctype(tymap[ty], tymap) - else - raise(DLError, "unknown type: #{ty}") - end - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb deleted file mode 100644 index ab7496e944..0000000000 --- a/ext/fiddle/lib/fiddle/function.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Fiddle - class Function - # The ABI of the Function. - attr_reader :abi - - # The address of this function - attr_reader :ptr - - # The name of this function - attr_reader :name - - # The integer memory location of this function - def to_i - ptr.to_i - end - end -end diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb deleted file mode 100644 index 8b948e8f23..0000000000 --- a/ext/fiddle/lib/fiddle/import.rb +++ /dev/null @@ -1,314 +0,0 @@ -require 'fiddle' -require 'fiddle/struct' -require 'fiddle/cparser' - -module Fiddle - - # Used internally by Fiddle::Importer - class CompositeHandler - # Create a new handler with the open +handlers+ - # - # Used internally by Fiddle::Importer.dlload - def initialize(handlers) - @handlers = handlers - end - - # Array of the currently loaded libraries. - def handlers() - @handlers - end - - # Returns the address as an Integer from any handlers with the function - # named +symbol+. - # - # Raises a DLError if the handle is closed. - def sym(symbol) - @handlers.each{|handle| - if( handle ) - begin - addr = handle.sym(symbol) - return addr - rescue DLError - end - end - } - return nil - end - - # See Fiddle::CompositeHandler.sym - def [](symbol) - sym(symbol) - end - end - - # A DSL that provides the means to dynamically load libraries and build - # modules around them including calling extern functions within the C - # library that has been loaded. - # - # == Example - # - # require 'fiddle' - # require 'fiddle/import' - # - # module LibSum - # extend Fiddle::Importer - # dlload './libsum.so' - # extern 'double sum(double*, int)' - # extern 'double split(double)' - # end - # - module Importer - include Fiddle - include CParser - extend Importer - - # Creates an array of handlers for the given +libs+, can be an instance of - # Fiddle::Handle, Fiddle::Importer, or will create a new istance of - # Fiddle::Handle using Fiddle.dlopen - # - # Raises a DLError if the library cannot be loaded. - # - # See Fiddle.dlopen - def dlload(*libs) - handles = libs.collect{|lib| - case lib - when nil - nil - when Handle - lib - when Importer - lib.handlers - else - begin - Fiddle.dlopen(lib) - rescue DLError - raise(DLError, "can't load #{lib}") - end - end - }.flatten() - @handler = CompositeHandler.new(handles) - @func_map = {} - @type_alias = {} - end - - # Sets the type alias for +alias_type+ as +orig_type+ - def typealias(alias_type, orig_type) - @type_alias[alias_type] = orig_type - end - - # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine - # the C type and the appropriate Fiddle constant. - def sizeof(ty) - case ty - when String - ty = parse_ctype(ty, @type_alias).abs() - case ty - when TYPE_CHAR - return SIZEOF_CHAR - when TYPE_SHORT - return SIZEOF_SHORT - when TYPE_INT - return SIZEOF_INT - when TYPE_LONG - return SIZEOF_LONG - when TYPE_LONG_LONG - return SIZEOF_LONG_LON - when TYPE_FLOAT - return SIZEOF_FLOAT - when TYPE_DOUBLE - return SIZEOF_DOUBLE - when TYPE_VOIDP - return SIZEOF_VOIDP - else - raise(DLError, "unknown type: #{ty}") - end - when Class - if( ty.instance_methods().include?(:to_ptr) ) - return ty.size() - end - end - return Pointer[ty].size() - end - - def parse_bind_options(opts) - h = {} - while( opt = opts.shift() ) - case opt - when :stdcall, :cdecl - h[:call_type] = opt - when :carried, :temp, :temporal, :bind - h[:callback_type] = opt - h[:carrier] = opts.shift() - else - h[opt] = true - end - end - h - end - private :parse_bind_options - - # :stopdoc: - CALL_TYPE_TO_ABI = Hash.new { |h, k| - raise RuntimeError, "unsupported call type: #{k}" - }.merge({ :stdcall => (Function::STDCALL rescue Function::DEFAULT), - :cdecl => Function::DEFAULT, - nil => Function::DEFAULT - }).freeze - private_constant :CALL_TYPE_TO_ABI - # :startdoc: - - # Creates a global method from the given C +signature+. - def extern(signature, *opts) - symname, ctype, argtype = parse_signature(signature, @type_alias) - opt = parse_bind_options(opts) - f = import_function(symname, ctype, argtype, opt[:call_type]) - name = symname.gsub(/@.+/,'') - @func_map[name] = f - # define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args, &block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a global method from the given C +signature+ using the given - # +opts+ as bind parameters with the given block. - def bind(signature, *opts, &blk) - name, ctype, argtype = parse_signature(signature, @type_alias) - h = parse_bind_options(opts) - case h[:callback_type] - when :bind, nil - f = bind_function(name, ctype, argtype, h[:call_type], &blk) - else - raise(RuntimeError, "unknown callback type: #{h[:callback_type]}") - end - @func_map[name] = f - #define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args,&block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a class to wrap the C struct described by +signature+. - # - # MyStruct = struct ['int i', 'char c'] - def struct(signature) - tys, mems = parse_struct_signature(signature, @type_alias) - Fiddle::CStructBuilder.create(CStruct, tys, mems) - end - - # Creates a class to wrap the C union described by +signature+. - # - # MyUnion = union ['int i', 'char c'] - def union(signature) - tys, mems = parse_struct_signature(signature, @type_alias) - Fiddle::CStructBuilder.create(CUnion, tys, mems) - end - - # Returns the function mapped to +name+, that was created by either - # Fiddle::Importer.extern or Fiddle::Importer.bind - def [](name) - @func_map[name] - end - - # Creates a class to wrap the C struct with the value +ty+ - # - # See also Fiddle::Importer.struct - def create_value(ty, val=nil) - s = struct([ty + " value"]) - ptr = s.malloc() - if( val ) - ptr.value = val - end - return ptr - end - alias value create_value - - # Returns a new instance of the C struct with the value +ty+ at the +addr+ - # address. - def import_value(ty, addr) - s = struct([ty + " value"]) - ptr = s.new(addr) - return ptr - end - - - # The Fiddle::CompositeHandler instance - # - # Will raise an error if no handlers are open. - def handler - @handler or raise "call dlload before importing symbols and functions" - end - - # Returns a new Fiddle::Pointer instance at the memory address of the given - # +name+ symbol. - # - # Raises a DLError if the +name+ doesn't exist. - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym - def import_symbol(name) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the symbol: #{name}") - end - Pointer.new(addr) - end - - # Returns a new Fiddle::Function instance at the memory address of the given - # +name+ function. - # - # Raises a DLError if the +name+ doesn't exist. - # - # * +argtype+ is an Array of arguments, passed to the +name+ function. - # * +ctype+ is the return type of the function - # * +call_type+ is the ABI of the function - # - # See also Fiddle:Function.new - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym - def import_function(name, ctype, argtype, call_type = nil) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the function: #{name}()") - end - Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], - name: name) - end - - # Returns a new closure wrapper for the +name+ function. - # - # * +ctype+ is the return type of the function - # * +argtype+ is an Array of arguments, passed to the callback function - # * +call_type+ is the abi of the closure - # * +block+ is passed to the callback - # - # See Fiddle::Closure - def bind_function(name, ctype, argtype, call_type = nil, &block) - abi = CALL_TYPE_TO_ABI[call_type] - closure = Class.new(Fiddle::Closure) { - define_method(:call, block) - }.new(ctype, argtype, abi) - - Function.new(closure, argtype, ctype, abi, name: name) - end - end -end diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb deleted file mode 100644 index e4e9542cc0..0000000000 --- a/ext/fiddle/lib/fiddle/pack.rb +++ /dev/null @@ -1,128 +0,0 @@ -require 'fiddle' - -module Fiddle - module PackInfo # :nodoc: all - ALIGN_MAP = { - TYPE_VOIDP => ALIGN_VOIDP, - TYPE_CHAR => ALIGN_CHAR, - TYPE_SHORT => ALIGN_SHORT, - TYPE_INT => ALIGN_INT, - TYPE_LONG => ALIGN_LONG, - TYPE_FLOAT => ALIGN_FLOAT, - TYPE_DOUBLE => ALIGN_DOUBLE, - -TYPE_CHAR => ALIGN_CHAR, - -TYPE_SHORT => ALIGN_SHORT, - -TYPE_INT => ALIGN_INT, - -TYPE_LONG => ALIGN_LONG, - } - - PACK_MAP = { - TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"), - TYPE_CHAR => "c", - TYPE_SHORT => "s!", - TYPE_INT => "i!", - TYPE_LONG => "l!", - TYPE_FLOAT => "f", - TYPE_DOUBLE => "d", - -TYPE_CHAR => "c", - -TYPE_SHORT => "s!", - -TYPE_INT => "i!", - -TYPE_LONG => "l!", - } - - SIZE_MAP = { - TYPE_VOIDP => SIZEOF_VOIDP, - TYPE_CHAR => SIZEOF_CHAR, - TYPE_SHORT => SIZEOF_SHORT, - TYPE_INT => SIZEOF_INT, - TYPE_LONG => SIZEOF_LONG, - TYPE_FLOAT => SIZEOF_FLOAT, - TYPE_DOUBLE => SIZEOF_DOUBLE, - -TYPE_CHAR => SIZEOF_CHAR, - -TYPE_SHORT => SIZEOF_SHORT, - -TYPE_INT => SIZEOF_INT, - -TYPE_LONG => SIZEOF_LONG, - } - if defined?(TYPE_LONG_LONG) - ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG - PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q" - SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG - end - - def align(addr, align) - d = addr % align - if( d == 0 ) - addr - else - addr + (align - d) - end - end - module_function :align - end - - class Packer # :nodoc: all - include PackInfo - - def self.[](*types) - new(types) - end - - def initialize(types) - parse_types(types) - end - - def size() - @size - end - - def pack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.pack(@template) - when SIZEOF_LONG_LONG - ary.pack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - - def unpack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.join().unpack(@template) - when SIZEOF_LONG_LONG - ary.join().unpack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - - private - - def parse_types(types) - @template = "" - addr = 0 - types.each{|t| - orig_addr = addr - if( t.is_a?(Array) ) - addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) - else - addr = align(orig_addr, ALIGN_MAP[t]) - end - d = addr - orig_addr - if( d > 0 ) - @template << "x#{d}" - end - if( t.is_a?(Array) ) - @template << (PACK_MAP[t[0]] * t[1]) - addr += (SIZE_MAP[t[0]] * t[1]) - else - @template << PACK_MAP[t] - addr += SIZE_MAP[t] - end - } - addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) - @size = addr - end - end -end diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb deleted file mode 100644 index 695a4d2247..0000000000 --- a/ext/fiddle/lib/fiddle/struct.rb +++ /dev/null @@ -1,243 +0,0 @@ -require 'fiddle' -require 'fiddle/value' -require 'fiddle/pack' - -module Fiddle - # C struct shell - class CStruct - # accessor to Fiddle::CStructEntity - def CStruct.entity_class - CStructEntity - end - end - - # C union shell - class CUnion - # accessor to Fiddle::CUnionEntity - def CUnion.entity_class - CUnionEntity - end - end - - # Used to construct C classes (CUnion, CStruct, etc) - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - module CStructBuilder - # Construct a new class given a C: - # * class +klass+ (CUnion, CStruct, or other that provide an - # #entity_class) - # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types - # constants) - # * corresponding +members+ - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - # - # Example: - # - # require 'fiddle/struct' - # require 'fiddle/cparser' - # - # include Fiddle::CParser - # - # types, members = parse_struct_signature(['int i','char c']) - # - # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) - # - # obj = MyStruct.allocate - # - def create(klass, types, members) - new_class = Class.new(klass){ - define_method(:initialize){|addr| - @entity = klass.entity_class.new(addr, types) - @entity.assign_names(members) - } - define_method(:to_ptr){ @entity } - define_method(:to_i){ @entity.to_i } - members.each{|name| - define_method(name){ @entity[name] } - define_method(name + "="){|val| @entity[name] = val } - } - } - size = klass.entity_class.size(types) - new_class.module_eval(<<-EOS, __FILE__, __LINE__+1) - def new_class.size() - #{size} - end - def new_class.malloc() - addr = Fiddle.malloc(#{size}) - new(addr) - end - EOS - return new_class - end - module_function :create - end - - # A C struct wrapper - class CStructEntity < Fiddle::Pointer - include PackInfo - include ValueUtil - - # Allocates a C struct with the +types+ provided. - # - # When the instance is garbage collected, the C function +func+ is called. - def CStructEntity.malloc(types, func = nil) - addr = Fiddle.malloc(CStructEntity.size(types)) - CStructEntity.new(addr, types, func) - end - - # Returns the offset for the packed sizes for the given +types+. - # - # Fiddle::CStructEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 24 - def CStructEntity.size(types) - offset = 0 - - max_align = types.map { |type, count = 1| - last_offset = offset - - align = PackInfo::ALIGN_MAP[type] - offset = PackInfo.align(last_offset, align) + - (PackInfo::SIZE_MAP[type] * count) - - align - }.max - - PackInfo.align(offset, max_align) - end - - # Wraps the C pointer +addr+ as a C struct with the given +types+. - # - # When the instance is garbage collected, the C function +func+ is called. - # - # See also Fiddle::Pointer.new - def initialize(addr, types, func = nil) - set_ctypes(types) - super(addr, @size, func) - end - - # Set the names of the +members+ in this C struct - def assign_names(members) - @members = members - end - - # Calculates the offsets and sizes for the given +types+ in the struct. - def set_ctypes(types) - @ctypes = types - @offset = [] - offset = 0 - - max_align = types.map { |type, count = 1| - orig_offset = offset - align = ALIGN_MAP[type] - offset = PackInfo.align(orig_offset, align) - - @offset << offset - - offset += (SIZE_MAP[type] * count) - - align - }.max - - @size = PackInfo.align(offset, max_align) - end - - # Fetch struct member +name+ - def [](name) - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - if( ty.is_a?(Array) ) - r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) - else - r = super(@offset[idx], SIZE_MAP[ty.abs]) - end - packer = Packer.new([ty]) - val = packer.unpack([r]) - case ty - when Array - case ty[0] - when TYPE_VOIDP - val = val.collect{|v| Pointer.new(v)} - end - when TYPE_VOIDP - val = Pointer.new(val[0]) - else - val = val[0] - end - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return val.collect{|v| unsigned_value(v,ty[0])} - else - return val - end - end - - # Set struct member +name+, to value +val+ - def []=(name, val) - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - packer = Packer.new([ty]) - val = wrap_arg(val, ty, []) - buff = packer.pack([val].flatten()) - super(@offset[idx], buff.size, buff) - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return val.collect{|v| unsigned_value(v,ty[0])} - else - return val - end - end - - def to_s() # :nodoc: - super(@size) - end - end - - # A C union wrapper - class CUnionEntity < CStructEntity - include PackInfo - - # Allocates a C union the +types+ provided. - # - # When the instance is garbage collected, the C function +func+ is called. - def CUnionEntity.malloc(types, func=nil) - addr = Fiddle.malloc(CUnionEntity.size(types)) - CUnionEntity.new(addr, types, func) - end - - # Returns the size needed for the union with the given +types+. - # - # Fiddle::CUnionEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 8 - def CUnionEntity.size(types) - types.map { |type, count = 1| - PackInfo::SIZE_MAP[type] * count - }.max - end - - # Calculate the necessary offset and for each union member with the given - # +types+ - def set_ctypes(types) - @ctypes = types - @offset = Array.new(types.length, 0) - @size = self.class.size types - end - end -end - diff --git a/ext/fiddle/lib/fiddle/types.rb b/ext/fiddle/lib/fiddle/types.rb deleted file mode 100644 index 02c1d25a37..0000000000 --- a/ext/fiddle/lib/fiddle/types.rb +++ /dev/null @@ -1,71 +0,0 @@ -module Fiddle - # Adds Windows type aliases to the including class for use with - # Fiddle::Importer. - # - # The aliases added are: - # * ATOM - # * BOOL - # * BYTE - # * DWORD - # * DWORD32 - # * DWORD64 - # * HANDLE - # * HDC - # * HINSTANCE - # * HWND - # * LPCSTR - # * LPSTR - # * PBYTE - # * PDWORD - # * PHANDLE - # * PVOID - # * PWORD - # * UCHAR - # * UINT - # * ULONG - # * WORD - module Win32Types - def included(m) # :nodoc: - m.module_eval{ - typealias "DWORD", "unsigned long" - typealias "PDWORD", "unsigned long *" - typealias "DWORD32", "unsigned long" - typealias "DWORD64", "unsigned long long" - typealias "WORD", "unsigned short" - typealias "PWORD", "unsigned short *" - typealias "BOOL", "int" - typealias "ATOM", "int" - typealias "BYTE", "unsigned char" - typealias "PBYTE", "unsigned char *" - typealias "UINT", "unsigned int" - typealias "ULONG", "unsigned long" - typealias "UCHAR", "unsigned char" - typealias "HANDLE", "uintptr_t" - typealias "PHANDLE", "void*" - typealias "PVOID", "void*" - typealias "LPCSTR", "char*" - typealias "LPSTR", "char*" - typealias "HINSTANCE", "unsigned int" - typealias "HDC", "unsigned int" - typealias "HWND", "unsigned int" - } - end - module_function :included - end - - # Adds basic type aliases to the including class for use with Fiddle::Importer. - # - # The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and - # +ulong+ and +u_long+ (<tt>unsigned long</tt>) - module BasicTypes - def included(m) # :nodoc: - m.module_eval{ - typealias "uint", "unsigned int" - typealias "u_int", "unsigned int" - typealias "ulong", "unsigned long" - typealias "u_long", "unsigned long" - } - end - module_function :included - end -end diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb deleted file mode 100644 index 8d71e47ce6..0000000000 --- a/ext/fiddle/lib/fiddle/value.rb +++ /dev/null @@ -1,112 +0,0 @@ -require 'fiddle' - -module Fiddle - module ValueUtil #:nodoc: all - def unsigned_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("c").unpack("C")[0] - when TYPE_SHORT - [val].pack("s!").unpack("S!")[0] - when TYPE_INT - [val].pack("i!").unpack("I!")[0] - when TYPE_LONG - [val].pack("l!").unpack("L!")[0] - when TYPE_LONG_LONG - [val].pack("q").unpack("Q")[0] - else - val - end - end - - def signed_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("C").unpack("c")[0] - when TYPE_SHORT - [val].pack("S!").unpack("s!")[0] - when TYPE_INT - [val].pack("I!").unpack("i!")[0] - when TYPE_LONG - [val].pack("L!").unpack("l!")[0] - when TYPE_LONG_LONG - [val].pack("Q").unpack("q")[0] - else - val - end - end - - def wrap_args(args, tys, funcs, &block) - result = [] - tys ||= [] - args.each_with_index{|arg, idx| - result.push(wrap_arg(arg, tys[idx], funcs, &block)) - } - result - end - - def wrap_arg(arg, ty, funcs = [], &block) - funcs ||= [] - case arg - when nil - return 0 - when Pointer - return arg.to_i - when IO - case ty - when TYPE_VOIDP - return Pointer[arg].to_i - else - return arg.to_i - end - when Function - if( block ) - arg.bind_at_call(&block) - funcs.push(arg) - elsif !arg.bound? - raise(RuntimeError, "block must be given.") - end - return arg.to_i - when String - if( ty.is_a?(Array) ) - return arg.unpack('C*') - else - case SIZEOF_VOIDP - when SIZEOF_LONG - return [arg].pack("p").unpack("l!")[0] - when SIZEOF_LONG_LONG - return [arg].pack("p").unpack("q")[0] - else - raise(RuntimeError, "sizeof(void*)?") - end - end - when Float, Integer - return arg - when Array - if( ty.is_a?(Array) ) # used only by struct - case ty[0] - when TYPE_VOIDP - return arg.collect{|v| Integer(v)} - when TYPE_CHAR - if( arg.is_a?(String) ) - return val.unpack('C*') - end - end - return arg - else - return arg - end - else - if( arg.respond_to?(:to_ptr) ) - return arg.to_ptr.to_i - else - begin - return Integer(arg) - rescue - raise(ArgumentError, "unknown argument type: #{arg.class}") - end - end - end - end - end -end diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c deleted file mode 100644 index fb9b31012f..0000000000 --- a/ext/fiddle/pointer.c +++ /dev/null @@ -1,716 +0,0 @@ -/* -*- C -*- - * $Id$ - */ - -#include <ruby/ruby.h> -#include <ruby/io.h> -#include <ctype.h> -#include <fiddle.h> - -VALUE rb_cPointer; - -typedef void (*freefunc_t)(void*); - -struct ptr_data { - void *ptr; - long size; - freefunc_t free; - VALUE wrap[2]; -}; - -#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj))) - -static inline freefunc_t -get_freefunc(VALUE func, volatile VALUE *wrap) -{ - VALUE addrnum; - if (NIL_P(func)) { - *wrap = 0; - return NULL; - } - addrnum = rb_Integer(func); - *wrap = (addrnum != func) ? func : 0; - return (freefunc_t)(VALUE)NUM2PTR(addrnum); -} - -static ID id_to_ptr; - -static void -fiddle_ptr_mark(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->wrap[0]) { - rb_gc_mark(data->wrap[0]); - } - if (data->wrap[1]) { - rb_gc_mark(data->wrap[1]); - } -} - -static void -fiddle_ptr_free(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->ptr) { - if (data->free) { - (*(data->free))(data->ptr); - } - } -} - -static size_t -fiddle_ptr_memsize(const void *ptr) -{ - const struct ptr_data *data = ptr; - return data ? sizeof(*data) + data->size : 0; -} - -static const rb_data_type_t fiddle_ptr_data_type = { - "fiddle/pointer", - {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,}, -}; - -static VALUE -rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func) -{ - struct ptr_data *data; - VALUE val; - - rb_secure(4); - val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = ptr; - data->free = func; - data->size = size; - OBJ_TAINT(val); - - return val; -} - -static VALUE -rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func) -{ - return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func); -} - -static VALUE -rb_fiddle_ptr_malloc(long size, freefunc_t func) -{ - void *ptr; - - rb_secure(4); - ptr = ruby_xmalloc((size_t)size); - memset(ptr,0,(size_t)size); - return rb_fiddle_ptr_new(ptr, size, func); -} - -static void * -rb_fiddle_ptr2cptr(VALUE val) -{ - struct ptr_data *data; - void *ptr; - - if (rb_obj_is_kind_of(val, rb_cPointer)) { - TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data); - ptr = data->ptr; - } - else if (val == Qnil) { - ptr = NULL; - } - else{ - rb_raise(rb_eTypeError, "Fiddle::Pointer was expected"); - } - - return ptr; -} - -static VALUE -rb_fiddle_ptr_s_allocate(VALUE klass) -{ - VALUE obj; - struct ptr_data *data; - - rb_secure(4); - obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = 0; - data->size = 0; - data->free = 0; - - return obj; -} - -/* - * call-seq: - * Fiddle::Pointer.new(address) => fiddle_cptr - * new(address, size) => fiddle_cptr - * new(address, size, freefunc) => fiddle_cptr - * - * Create a new pointer to +address+ with an optional +size+ and +freefunc+. - * - * +freefunc+ will be called when the instance is garbage collected. - */ -static VALUE -rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self) -{ - VALUE ptr, sym, size, wrap = 0, funcwrap = 0; - struct ptr_data *data; - void *p = NULL; - freefunc_t f = NULL; - long s = 0; - - if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) { - VALUE addrnum = rb_Integer(ptr); - if (addrnum != ptr) wrap = ptr; - p = NUM2PTR(addrnum); - } - if (argc >= 2) { - s = NUM2LONG(size); - } - if (argc >= 3) { - f = get_freefunc(sym, &funcwrap); - } - - if (p) { - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (data->ptr && data->free) { - /* Free previous memory. Use of inappropriate initialize may cause SEGV. */ - (*(data->free))(data->ptr); - } - data->wrap[0] = wrap; - data->wrap[1] = funcwrap; - data->ptr = p; - data->size = s; - data->free = f; - } - - return Qnil; -} - -/* - * call-seq: - * - * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance - * - * Allocate +size+ bytes of memory and associate it with an optional - * +freefunc+ that will be called when the pointer is garbage collected. - * - * +freefunc+ must be an address pointing to a function or an instance of - * Fiddle::Function - */ -static VALUE -rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) -{ - VALUE size, sym, obj, wrap = 0; - long s; - freefunc_t f; - - switch (rb_scan_args(argc, argv, "11", &size, &sym)) { - case 1: - s = NUM2LONG(size); - f = NULL; - break; - case 2: - s = NUM2LONG(size); - f = get_freefunc(sym, &wrap); - break; - default: - rb_bug("rb_fiddle_ptr_s_malloc"); - } - - obj = rb_fiddle_ptr_malloc(s,f); - if (wrap) RPTR_DATA(obj)->wrap[1] = wrap; - - return obj; -} - -/* - * call-seq: to_i - * - * Returns the integer memory location of this pointer. - */ -static VALUE -rb_fiddle_ptr_to_i(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return PTR2NUM(data->ptr); -} - -/* - * call-seq: to_value - * - * Cast this pointer to a ruby object. - */ -static VALUE -rb_fiddle_ptr_to_value(VALUE self) -{ - struct ptr_data *data; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return (VALUE)(data->ptr); -} - -/* - * call-seq: ptr - * - * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for - * this pointer. - * - * Analogous to the star operator in C. - */ -static VALUE -rb_fiddle_ptr_ptr(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0); -} - -/* - * call-seq: ref - * - * Returns a new Fiddle::Pointer instance that is a reference pointer for this - * pointer. - * - * Analogous to the ampersand operator in C. - */ -static VALUE -rb_fiddle_ptr_ref(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(&(data->ptr),0,0); -} - -/* - * call-seq: null? - * - * Returns +true+ if this is a null pointer. - */ -static VALUE -rb_fiddle_ptr_null_p(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return data->ptr ? Qfalse : Qtrue; -} - -/* - * call-seq: free=(function) - * - * Set the free function for this pointer to +function+ in the given - * Fiddle::Function. - */ -static VALUE -rb_fiddle_ptr_free_set(VALUE self, VALUE val) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - data->free = get_freefunc(val, &data->wrap[1]); - - return Qnil; -} - -/* - * call-seq: free => Fiddle::Function - * - * Get the free function for this pointer. - * - * Returns a new instance of Fiddle::Function. - * - * See Fiddle::Function.new - */ -static VALUE -rb_fiddle_ptr_free_get(VALUE self) -{ - struct ptr_data *pdata; - VALUE address; - VALUE arg_types; - VALUE ret_type; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - - if (!pdata->free) - return Qnil; - - address = PTR2NUM(pdata->free); - ret_type = INT2NUM(TYPE_VOID); - arg_types = rb_ary_new(); - rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP)); - - return rb_fiddle_new_function(address, arg_types, ret_type); -} - -/* - * call-seq: - * - * ptr.to_s => string - * ptr.to_s(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents until - * the first NULL byte. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_str - */ -static VALUE -rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_tainted_str_new2((char*)(data->ptr)); - break; - case 1: - len = NUM2INT(arg1); - val = rb_tainted_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_s"); - } - - return val; -} - -/* - * call-seq: - * - * ptr.to_str => string - * ptr.to_str(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents with the - * length of this pointer's +size+. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_s - */ -static VALUE -rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_tainted_str_new((char*)(data->ptr),data->size); - break; - case 1: - len = NUM2INT(arg1); - val = rb_tainted_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_str"); - } - - return val; -} - -/* - * call-seq: inspect - * - * Returns a string formatted with an easily readable representation of the - * internal state of the pointer. - */ -static VALUE -rb_fiddle_ptr_inspect(VALUE self) -{ - struct ptr_data *data; - char str[1024]; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - snprintf(str, 1023, "#<%s:%p ptr=%p size=%ld free=%p>", - rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free); - return rb_str_new2(str); -} - -/* - * call-seq: - * ptr == other => true or false - * ptr.eql?(other) => true or false - * - * Returns true if +other+ wraps the same pointer, otherwise returns - * false. - */ -static VALUE -rb_fiddle_ptr_eql(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - - return ptr1 == ptr2 ? Qtrue : Qfalse; -} - -/* - * call-seq: - * ptr <=> other => -1, 0, 1, or nil - * - * Returns -1 if less than, 0 if equal to, 1 if greater than +other+. - * - * Returns nil if +ptr+ cannot be compared to +other+. - */ -static VALUE -rb_fiddle_ptr_cmp(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - SIGNED_VALUE diff; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2; - if (!diff) return INT2FIX(0); - return diff > 0 ? INT2NUM(1) : INT2NUM(-1); -} - -/* - * call-seq: - * ptr + n => new cptr - * - * Returns a new pointer instance that has been advanced +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_plus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0); -} - -/* - * call-seq: - * ptr - n => new cptr - * - * Returns a new pointer instance that has been moved back +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_minus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0); -} - -/* - * call-seq: - * ptr[index] -> an_integer - * ptr[start, length] -> a_string - * - * Returns integer stored at _index_. - * - * If _start_ and _length_ are given, a string containing the bytes from - * _start_ of _length_ will be returned. - */ -static VALUE -rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1; - VALUE retval = Qnil; - size_t offset, len; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){ - case 1: - offset = NUM2ULONG(arg0); - retval = INT2NUM(*((char *)data->ptr + offset)); - break; - case 2: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - retval = rb_tainted_str_new((char *)data->ptr + offset, len); - break; - default: - rb_bug("rb_fiddle_ptr_aref()"); - } - return retval; -} - -/* - * call-seq: - * ptr[index] = int -> int - * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr - * - * Set the value at +index+ to +int+. - * - * Or, set the memory at +start+ until +length+ with the contents of +string+, - * the memory from +dl_cptr+, or the memory pointed at by the memory address - * +addr+. - */ -static VALUE -rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1, arg2; - VALUE retval = Qnil; - size_t offset, len; - void *mem; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){ - case 2: - offset = NUM2ULONG(arg0); - ((char*)data->ptr)[offset] = NUM2UINT(arg1); - retval = arg1; - break; - case 3: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - if (RB_TYPE_P(arg2, T_STRING)) { - mem = StringValuePtr(arg2); - } - else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){ - mem = rb_fiddle_ptr2cptr(arg2); - } - else{ - mem = NUM2PTR(arg2); - } - memcpy((char *)data->ptr + offset, mem, len); - retval = arg2; - break; - default: - rb_bug("rb_fiddle_ptr_aset()"); - } - return retval; -} - -/* - * call-seq: size=(size) - * - * Set the size of this pointer to +size+ - */ -static VALUE -rb_fiddle_ptr_size_set(VALUE self, VALUE size) -{ - RPTR_DATA(self)->size = NUM2LONG(size); - return size; -} - -/* - * call-seq: size - * - * Get the size of this pointer. - */ -static VALUE -rb_fiddle_ptr_size_get(VALUE self) -{ - return LONG2NUM(RPTR_DATA(self)->size); -} - -/* - * call-seq: - * Fiddle::Pointer[val] => cptr - * to_ptr(val) => cptr - * - * Get the underlying pointer for ruby object +val+ and return it as a - * Fiddle::Pointer object. - */ -static VALUE -rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) -{ - VALUE ptr, wrap = val, vptr; - - if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){ - rb_io_t *fptr; - FILE *fp; - GetOpenFile(val, fptr); - fp = rb_io_stdio_file(fptr); - ptr = rb_fiddle_ptr_new(fp, 0, NULL); - } - else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){ - char *str = StringValuePtr(val); - ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL); - } - else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){ - if (rb_obj_is_kind_of(vptr, rb_cPointer)){ - ptr = vptr; - wrap = 0; - } - else{ - rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object"); - } - } - else{ - VALUE num = rb_Integer(val); - if (num == val) wrap = 0; - ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL); - } - OBJ_INFECT(ptr, val); - if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap; - return ptr; -} - -void -Init_fiddle_pointer(void) -{ - id_to_ptr = rb_intern("to_ptr"); - - /* Document-class: Fiddle::Pointer - * - * Fiddle::Pointer is a class to handle C pointers - * - */ - rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject); - rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate); - rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1); - rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1); - rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1); - rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1); - rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1); - rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0); - rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0); - rb_define_method(rb_cPointer, "ptr", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "ref", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0); - rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1); - rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1); - rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0); - rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1); - rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1); - rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1); - rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1); - rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1); - rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0); - rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1); - - /* Document-const: NULL - * - * A NULL pointer - */ - rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0)); -} diff --git a/ext/fiddle/win32/extconf.rb b/ext/fiddle/win32/extconf.rb deleted file mode 100644 index c4efee8149..0000000000 --- a/ext/fiddle/win32/extconf.rb +++ /dev/null @@ -1,3 +0,0 @@ -if compiled?('fiddle') and $mswin||$mingw||$cygwin - create_makefile('win32') -end diff --git a/ext/fiddle/win32/lib/win32/registry.rb b/ext/fiddle/win32/lib/win32/registry.rb deleted file mode 100644 index f1aa3640a8..0000000000 --- a/ext/fiddle/win32/lib/win32/registry.rb +++ /dev/null @@ -1,845 +0,0 @@ -require 'fiddle/import' -module Win32 - -=begin rdoc -= Win32 Registry - -win32/registry is registry accessor library for Win32 platform. -It uses fiddle/import to call Win32 Registry APIs. - -== example - Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg| - value = reg['foo'] # read a value - value = reg['foo', Win32::Registry::REG_SZ] # read a value with type - type, value = reg.read('foo') # read a value - reg['foo'] = 'bar' # write a value - reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type - reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value - - reg.each_value { |name, type, data| ... } # Enumerate values - reg.each_key { |key, wtime| ... } # Enumerate subkeys - - reg.delete_value(name) # Delete a value - reg.delete_key(name) # Delete a subkey - reg.delete_key(name, true) # Delete a subkey recursively - end - -= Reference - -== Win32::Registry class - ---- info - ---- num_keys - ---- max_key_length - ---- num_values - ---- max_value_name_length - ---- max_value_length - ---- descriptor_length - ---- wtime - Returns an item of key information. - -=== constants ---- HKEY_CLASSES_ROOT - ---- HKEY_CURRENT_USER - ---- HKEY_LOCAL_MACHINE - ---- HKEY_PERFORMANCE_DATA - ---- HKEY_CURRENT_CONFIG - ---- HKEY_DYN_DATA - - Win32::Registry object whose key is predefined key. -For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article. - -=end rdoc - - class Registry - - # - # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp]. - # - # --- HKEY_* - # - # Predefined key ((*handle*)). - # These are Integer, not Win32::Registry. - # - # --- REG_* - # - # Registry value type. - # - # --- KEY_* - # - # Security access mask. - # - # --- KEY_OPTIONS_* - # - # Key options. - # - # --- REG_CREATED_NEW_KEY - # - # --- REG_OPENED_EXISTING_KEY - # - # If the key is created newly or opened existing key. - # See also Registry#disposition method. - module Constants - HKEY_CLASSES_ROOT = 0x80000000 - HKEY_CURRENT_USER = 0x80000001 - HKEY_LOCAL_MACHINE = 0x80000002 - HKEY_USERS = 0x80000003 - HKEY_PERFORMANCE_DATA = 0x80000004 - HKEY_PERFORMANCE_TEXT = 0x80000050 - HKEY_PERFORMANCE_NLSTEXT = 0x80000060 - HKEY_CURRENT_CONFIG = 0x80000005 - HKEY_DYN_DATA = 0x80000006 - - REG_NONE = 0 - REG_SZ = 1 - REG_EXPAND_SZ = 2 - REG_BINARY = 3 - REG_DWORD = 4 - REG_DWORD_LITTLE_ENDIAN = 4 - REG_DWORD_BIG_ENDIAN = 5 - REG_LINK = 6 - REG_MULTI_SZ = 7 - REG_RESOURCE_LIST = 8 - REG_FULL_RESOURCE_DESCRIPTOR = 9 - REG_RESOURCE_REQUIREMENTS_LIST = 10 - REG_QWORD = 11 - REG_QWORD_LITTLE_ENDIAN = 11 - - STANDARD_RIGHTS_READ = 0x00020000 - STANDARD_RIGHTS_WRITE = 0x00020000 - KEY_QUERY_VALUE = 0x0001 - KEY_SET_VALUE = 0x0002 - KEY_CREATE_SUB_KEY = 0x0004 - KEY_ENUMERATE_SUB_KEYS = 0x0008 - KEY_NOTIFY = 0x0010 - KEY_CREATE_LINK = 0x0020 - KEY_READ = STANDARD_RIGHTS_READ | - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY - KEY_WRITE = STANDARD_RIGHTS_WRITE | - KEY_SET_VALUE | KEY_CREATE_SUB_KEY - KEY_EXECUTE = KEY_READ - KEY_ALL_ACCESS = KEY_READ | KEY_WRITE | KEY_CREATE_LINK - - REG_OPTION_RESERVED = 0x0000 - REG_OPTION_NON_VOLATILE = 0x0000 - REG_OPTION_VOLATILE = 0x0001 - REG_OPTION_CREATE_LINK = 0x0002 - REG_OPTION_BACKUP_RESTORE = 0x0004 - REG_OPTION_OPEN_LINK = 0x0008 - REG_LEGAL_OPTION = REG_OPTION_RESERVED | - REG_OPTION_NON_VOLATILE | REG_OPTION_CREATE_LINK | - REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK - - REG_CREATED_NEW_KEY = 1 - REG_OPENED_EXISTING_KEY = 2 - - REG_WHOLE_HIVE_VOLATILE = 0x0001 - REG_REFRESH_HIVE = 0x0002 - REG_NO_LAZY_FLUSH = 0x0004 - REG_FORCE_RESTORE = 0x0008 - - MAX_KEY_LENGTH = 514 - MAX_VALUE_LENGTH = 32768 - end - include Constants - include Enumerable - - # - # Error - # - class Error < ::StandardError - module Kernel32 - extend Fiddle::Importer - dlload "kernel32.dll" - end - FormatMessageA = Kernel32.extern "int FormatMessageA(int, void *, int, int, void *, int, void *)", :stdcall - def initialize(code) - @code = code - msg = "\0".force_encoding(Encoding::ASCII_8BIT) * 1024 - len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0) - msg = msg[0, len].force_encoding(Encoding.find(Encoding.locale_charmap)) - super msg.tr("\r", '').chomp - end - attr_reader :code - end - - # - # Predefined Keys - # - class PredefinedKey < Registry - def initialize(hkey, keyname) - @hkey = hkey - @parent = nil - @keyname = keyname - @disposition = REG_OPENED_EXISTING_KEY - end - - # Predefined keys cannot be closed - def close - raise Error.new(5) ## ERROR_ACCESS_DENIED - end - - # Fake #class method for Registry#open, Registry#create - def class - Registry - end - - # Make all - Constants.constants.grep(/^HKEY_/) do |c| - Registry.const_set c, new(Constants.const_get(c), c.to_s) - end - end - - # - # Win32 APIs - # - module API - extend Fiddle::Importer - dlload "advapi32.dll" - [ - "long RegOpenKeyExA(void *, void *, long, long, void *)", - "long RegCreateKeyExA(void *, void *, long, long, long, long, void *, void *, void *)", - "long RegEnumValueA(void *, long, void *, void *, void *, void *, void *, void *)", - "long RegEnumKeyExA(void *, long, void *, void *, void *, void *, void *, void *)", - "long RegQueryValueExA(void *, void *, void *, void *, void *, void *)", - "long RegSetValueExA(void *, void *, long, long, void *, long)", - "long RegDeleteValue(void *, void *)", - "long RegDeleteKey(void *, void *)", - "long RegFlushKey(void *)", - "long RegCloseKey(void *)", - "long RegQueryInfoKey(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)", - ].each do |fn| - cfunc = extern fn, :stdcall - const_set cfunc.name.intern, cfunc - end - - module_function - - def check(result) - raise Error, result, caller(2) if result != 0 - end - - def packdw(dw) - [dw].pack('V') - end - - def unpackdw(dw) - dw += [0].pack('V') - dw.unpack('V')[0] - end - - def packqw(qw) - [ qw & 0xFFFFFFFF, qw >> 32 ].pack('VV') - end - - def unpackqw(qw) - qw = qw.unpack('VV') - (qw[1] << 32) | qw[0] - end - - def OpenKey(hkey, name, opt, desired) - result = packdw(0) - check RegOpenKeyExA.call(hkey, name, opt, desired, result) - unpackdw(result) - end - - def CreateKey(hkey, name, opt, desired) - result = packdw(0) - disp = packdw(0) - check RegCreateKeyExA.call(hkey, name, 0, 0, opt, desired, - 0, result, disp) - [ unpackdw(result), unpackdw(disp) ] - end - - def EnumValue(hkey, index) - name = ' ' * Constants::MAX_KEY_LENGTH - size = packdw(Constants::MAX_KEY_LENGTH) - check RegEnumValueA.call(hkey, index, name, size, 0, 0, 0, 0) - name[0, unpackdw(size)] - end - - def EnumKey(hkey, index) - name = ' ' * Constants::MAX_KEY_LENGTH - size = packdw(Constants::MAX_KEY_LENGTH) - wtime = ' ' * 8 - check RegEnumKeyExA.call(hkey, index, name, size, 0, 0, 0, wtime) - [ name[0, unpackdw(size)], unpackqw(wtime) ] - end - - def QueryValue(hkey, name) - type = packdw(0) - size = packdw(0) - check RegQueryValueExA.call(hkey, name, 0, type, 0, size) - data = ' ' * unpackdw(size) - check RegQueryValueExA.call(hkey, name, 0, type, data, size) - [ unpackdw(type), data[0, unpackdw(size)] ] - end - - def SetValue(hkey, name, type, data, size) - check RegSetValueExA.call(hkey, name, 0, type, data, size) - end - - def DeleteValue(hkey, name) - check RegDeleteValue.call(hkey, name) - end - - def DeleteKey(hkey, name) - check RegDeleteKey.call(hkey, name) - end - - def FlushKey(hkey) - check RegFlushKey.call(hkey) - end - - def CloseKey(hkey) - check RegCloseKey.call(hkey) - end - - def QueryInfoKey(hkey) - subkeys = packdw(0) - maxsubkeylen = packdw(0) - values = packdw(0) - maxvaluenamelen = packdw(0) - maxvaluelen = packdw(0) - secdescs = packdw(0) - wtime = ' ' * 8 - check RegQueryInfoKey.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0, - values, maxvaluenamelen, maxvaluelen, secdescs, wtime) - [ unpackdw(subkeys), unpackdw(maxsubkeylen), unpackdw(values), - unpackdw(maxvaluenamelen), unpackdw(maxvaluelen), - unpackdw(secdescs), unpackqw(wtime) ] - end - end - - # - # Replace %\w+% into the environment value of what is contained between the %'s - # This method is used for REG_EXPAND_SZ. - # - # For detail, see expandEnvironmentStrings[http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp] \Win32 \API. - # - def self.expand_environ(str) - str.gsub(/%([^%]+)%/) { ENV[$1] || ENV[$1.upcase] || $& } - end - - @@type2name = { } - %w[ - REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD - REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ - REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR - REG_RESOURCE_REQUIREMENTS_LIST REG_QWORD - ].each do |type| - @@type2name[Constants.const_get(type)] = type - end - - # - # Convert registry type value to readable string. - # - def self.type2name(type) - @@type2name[type] || type.to_s - end - - # - # Convert 64-bit FILETIME integer into Time object. - # - def self.wtime2time(wtime) - Time.at((wtime - 116444736000000000) / 10000000) - end - - # - # Convert Time object or Integer object into 64-bit FILETIME. - # - def self.time2wtime(time) - time.to_i * 10000000 + 116444736000000000 - end - - # - # constructor - # - private_class_method :new - - # - # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) - # - # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... } - # - # Open the registry key subkey under key. - # key is Win32::Registry object of parent key. - # You can use predefined key HKEY_* (see Constants) - # desired and opt is access mask and key option. - # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp]. - # If block is given, the key is closed automatically. - def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) - subkey = subkey.chomp('\\') - newkey = API.OpenKey(hkey.hkey, subkey, opt, desired) - obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY) - if block_given? - begin - yield obj - ensure - obj.close - end - else - obj - end - end - - # - # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) - # - # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... } - # - # Create or open the registry key subkey under key. - # You can use predefined key HKEY_* (see Constants) - # - # If subkey is already exists, key is opened and Registry#created? - # method will return false. - # - # If block is given, the key is closed automatically. - # - def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) - newkey, disp = API.CreateKey(hkey.hkey, subkey, opt, desired) - obj = new(newkey, hkey, subkey, disp) - if block_given? - begin - yield obj - ensure - obj.close - end - else - obj - end - end - - # - # finalizer - # - @@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } } - - # - # initialize - # - def initialize(hkey, parent, keyname, disposition) - @hkey = hkey - @parent = parent - @keyname = keyname - @disposition = disposition - @hkeyfinal = [ hkey ] - ObjectSpace.define_finalizer self, @@final.call(@hkeyfinal) - end - - # Returns key handle value. - attr_reader :hkey - # Win32::Registry object of parent key, or nil if predefeined key. - attr_reader :parent - # Same as subkey value of Registry.open or - # Registry.create method. - attr_reader :keyname - # Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY). - attr_reader :disposition - - # - # Returns if key is created ((*newly*)). - # (see Registry.create) -- basically you call create - # then when you call created? on the instance returned - # it will tell if it was successful or not - # - def created? - @disposition == REG_CREATED_NEW_KEY - end - - # - # Returns if key is not closed. - # - def open? - !@hkey.nil? - end - - # - # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'. - # - def name - parent = self - name = @keyname - while parent = parent.parent - name = parent.keyname + '\\' + name - end - name - end - - def inspect - "\#<Win32::Registry key=#{name.inspect}>" - end - - # - # marshalling is not allowed - # - def _dump(depth) - raise TypeError, "can't dump Win32::Registry" - end - - # - # Same as Win32::Registry.open (self, subkey, desired, opt) - # - def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk) - self.class.open(self, subkey, desired, opt, &blk) - end - - # - # Same as Win32::Registry.create (self, subkey, desired, opt) - # - def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk) - self.class.create(self, subkey, desired, opt, &blk) - end - - # - # Close key. - # - # After close, most method raise an error. - # - def close - API.CloseKey(@hkey) - @hkey = @parent = @keyname = nil - @hkeyfinal[0] = nil - end - - # - # Enumerate values. - # - def each_value - index = 0 - while true - begin - subkey = API.EnumValue(@hkey, index) - rescue Error - break - end - begin - type, data = read(subkey) - rescue Error - next - end - yield subkey, type, data - index += 1 - end - index - end - alias each each_value - - # - # Enumerate subkeys. - # - # subkey is String which contains name of subkey. - # wtime is last write time as FILETIME (64-bit integer). - # (see Registry.wtime2time) - # - def each_key - index = 0 - while true - begin - subkey, wtime = API.EnumKey(@hkey, index) - rescue Error - break - end - yield subkey, wtime - index += 1 - end - index - end - - # - # return keys as an array - # - def keys - keys_ary = [] - each_key { |key,| keys_ary << key } - keys_ary - end - - # Read a registry value named name and return array of - # [ type, data ]. - # When name is nil, the `default' value is read. - # type is value type. (see Win32::Registry::Constants module) - # data is value data, its class is: - # :REG_SZ, REG_EXPAND_SZ - # String - # :REG_MULTI_SZ - # Array of String - # :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD - # Integer - # :REG_BINARY - # String (contains binary data) - # - # When rtype is specified, the value type must be included by - # rtype array, or TypeError is raised. - def read(name, *rtype) - type, data = API.QueryValue(@hkey, name) - unless rtype.empty? or rtype.include?(type) - raise TypeError, "Type mismatch (expect #{rtype.inspect} but #{type} present)" - end - case type - when REG_SZ, REG_EXPAND_SZ - [ type, data.chop ] - when REG_MULTI_SZ - [ type, data.split(/\0/) ] - when REG_BINARY - [ type, data ] - when REG_DWORD - [ type, API.unpackdw(data) ] - when REG_DWORD_BIG_ENDIAN - [ type, data.unpack('N')[0] ] - when REG_QWORD - [ type, API.unpackqw(data) ] - else - raise TypeError, "Type #{type} is not supported." - end - end - - # - # Read a registry value named name and return its value data. - # The class of value is same as #read method returns. - # - # If the value type is REG_EXPAND_SZ, returns value data whose environment - # variables are replaced. - # If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD, - # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised. - # - # The meaning of rtype is same as #read method. - # - def [](name, *rtype) - type, data = read(name, *rtype) - case type - when REG_SZ, REG_DWORD, REG_QWORD, REG_MULTI_SZ - data - when REG_EXPAND_SZ - Registry.expand_environ(data) - else - raise TypeError, "Type #{type} is not supported." - end - end - - # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) - # registry value named name. - # - # If the values type does not match, TypeError is raised. - def read_s(name) - read(name, REG_SZ)[1] - end - - # - # Read a REG_SZ or REG_EXPAND_SZ registry value named name. - # - # If the value type is REG_EXPAND_SZ, environment variables are replaced. - # Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised. - # - def read_s_expand(name) - type, data = read(name, REG_SZ, REG_EXPAND_SZ) - if type == REG_EXPAND_SZ - Registry.expand_environ(data) - else - data - end - end - - # - # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) - # registry value named name. - # - # If the values type does not match, TypeError is raised. - # - def read_i(name) - read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1] - end - - # - # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) - # registry value named name. - # - # If the values type does not match, TypeError is raised. - # - def read_bin(name) - read(name, REG_BINARY)[1] - end - - # - # Write data to a registry value named name. - # When name is nil, write to the `default' value. - # - # type is type value. (see Registry::Constants module) - # Class of data must be same as which #read - # method returns. - # - def write(name, type, data) - case type - when REG_SZ, REG_EXPAND_SZ - data = data.to_s + "\0" - when REG_MULTI_SZ - data = data.to_a.join("\0") + "\0\0" - when REG_BINARY - data = data.to_s - when REG_DWORD - data = API.packdw(data.to_i) - when REG_DWORD_BIG_ENDIAN - data = [data.to_i].pack('N') - when REG_QWORD - data = API.packqw(data.to_i) - else - raise TypeError, "Unsupported type #{type}" - end - API.SetValue(@hkey, name, type, data, data.length) - end - - # - # Write value to a registry value named name. - # - # If wtype is specified, the value type is it. - # Otherwise, the value type is depend on class of value: - # :Integer - # REG_DWORD - # :String - # REG_SZ - # :Array - # REG_MULTI_SZ - # - def []=(name, rtype, value = nil) - if value - write name, rtype, value - else - case value = rtype - when Integer - write name, REG_DWORD, value - when String - write name, REG_SZ, value - when Array - write name, REG_MULTI_SZ, value - else - raise TypeError, "Unexpected type #{value.class}" - end - end - value - end - - # - # Write value to a registry value named name. - # - # The value type is REG_SZ(write_s), REG_DWORD(write_i), or - # REG_BINARY(write_bin). - # - def write_s(name, value) - write name, REG_SZ, value.to_s - end - - # - # Write value to a registry value named name. - # - # The value type is REG_SZ(write_s), REG_DWORD(write_i), or - # REG_BINARY(write_bin). - # - def write_i(name, value) - write name, REG_DWORD, value.to_i - end - - # - # Write value to a registry value named name. - # - # The value type is REG_SZ(write_s), REG_DWORD(write_i), or - # REG_BINARY(write_bin). - # - def write_bin(name, value) - write name, REG_BINARY, value.to_s - end - - # - # Delete a registry value named name. - # We can not delete the `default' value. - # - def delete_value(name) - API.DeleteValue(@hkey, name) - end - alias delete delete_value - - # - # Delete a subkey named name and all its values. - # - # If recursive is false, the subkey must not have subkeys. - # Otherwise, this method deletes all subkeys and values recursively. - # - def delete_key(name, recursive = false) - if recursive - open(name, KEY_ALL_ACCESS) do |reg| - reg.keys.each do |key| - begin - reg.delete_key(key, true) - rescue Error - # - end - end - end - API.DeleteKey(@hkey, name) - else - begin - API.EnumKey @hkey, 0 - rescue Error - return API.DeleteKey(@hkey, name) - end - raise Error.new(5) ## ERROR_ACCESS_DENIED - end - end - - # - # Write all the attributes into the registry file. - # - def flush - API.FlushKey @hkey - end - - # - # Returns key information as Array of: - # :num_keys - # The number of subkeys. - # :max_key_length - # Maximum length of name of subkeys. - # :num_values - # The number of values. - # :max_value_name_length - # Maximum length of name of values. - # :max_value_length - # Maximum length of value of values. - # :descriptor_length - # Length of security descriptor. - # :wtime - # Last write time as FILETIME(64-bit integer) - # - # For detail, see RegQueryInfoKey[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API. - # - def info - API.QueryInfoKey(@hkey) - end - - # - # Returns an item of key information. - # - %w[ - num_keys max_key_length - num_values max_value_name_length max_value_length - descriptor_length wtime - ].each_with_index do |s, i| - eval <<-__END__ - def #{s} - info[#{i}] - end - __END__ - end - end -end diff --git a/ext/fiddle/win32/lib/win32/resolv.rb b/ext/fiddle/win32/lib/win32/resolv.rb deleted file mode 100644 index 1315f32c61..0000000000 --- a/ext/fiddle/win32/lib/win32/resolv.rb +++ /dev/null @@ -1,379 +0,0 @@ -=begin -= Win32 DNS and DHCP I/F - -=end - -require "fiddle/import" -require 'win32/registry' - -module Win32 - module Resolv - API = Registry::API - - def self.get_hosts_path - path = get_hosts_dir - path = File.expand_path('hosts', path) - File.exist?(path) ? path : nil - end - - def self.get_resolv_info - search, nameserver = get_info - if search.empty? - search = nil - else - search.delete("") - search.uniq! - end - if nameserver.empty? - nameserver = nil - else - nameserver.delete("") - nameserver.delete("0.0.0.0") - nameserver.uniq! - end - [ search, nameserver ] - end - -module Kernel32 - extend Fiddle::Importer - dlload "kernel32" -end -getv = Kernel32.extern "int GetVersionExA(void *)", :stdcall -info = [ 148, 0, 0, 0, 0 ].pack('V5') + "\0" * 128 -getv.call(info) -if info.unpack('V5')[4] == 2 # VER_PLATFORM_WIN32_NT -#==================================================================== -# Windows NT -#==================================================================== - module_eval <<-'__EOS__', __FILE__, __LINE__+1 - TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters' - - class << self - private - def get_hosts_dir - Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg| - reg.read_s_expand('DataBasePath') - end - end - - def get_info - search = nil - nameserver = [] - Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg| - begin - slist = reg.read_s('SearchList') - search = slist.split(/,\s*/) unless slist.empty? - rescue Registry::Error - end - - if add_search = search.nil? - search = [] - begin - nvdom = reg.read_s('NV Domain') - unless nvdom.empty? - @search = [ nvdom ] - if reg.read_i('UseDomainNameDevolution') != 0 - if /^\w+\./ =~ nvdom - devo = $' - end - end - end - rescue Registry::Error - end - end - - reg.open('Interfaces') do |h| - h.each_key do |iface,| - h.open(iface) do |regif| - begin - [ 'NameServer', 'DhcpNameServer' ].each do |key| - begin - ns = regif.read_s(key) - rescue - else - unless ns.empty? - nameserver.concat(ns.split(/[,\s]\s*/)) - break - end - end - end - rescue Registry::Error - end - - if add_search - begin - [ 'Domain', 'DhcpDomain' ].each do |key| - dom = regif.read_s(key) - unless dom.empty? - search.concat(dom.split(/,\s*/)) - break - end - end - rescue Registry::Error - end - end - end - end - end - search << devo if add_search and devo - end - [ search.uniq, nameserver.uniq ] - end - end - __EOS__ -else -#==================================================================== -# Windows 9x -#==================================================================== - module_eval <<-'__EOS__', __FILE__, __LINE__+1 - TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP' - DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP' - WINDOWS = 'Software\Microsoft\Windows\CurrentVersion' - - class << self - # private - - def get_hosts_dir - Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg| - reg.read_s_expand('SystemRoot') - end - end - - def get_info - search = [] - nameserver = [] - begin - Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg| - if reg.read_s("EnableDNS") == "1" - domain = reg.read_s("Domain") - ns = reg.read_s("NameServer") - slist = reg.read_s("SearchList") - search << domain unless domain.empty? - search.concat(slist.split(/,\s*/)) - nameserver.concat(ns.split(/[,\s]\s*/)) - end - end - rescue Registry::Error - end - - dhcpinfo = get_dhcpinfo - search.concat(dhcpinfo[0]) - nameserver.concat(dhcpinfo[1]) - [ search, nameserver ] - end - - def get_dhcpinfo - macaddrs = {} - ipaddrs = {} - WsControl.get_iflist.each do |index, macaddr, *ipaddr| - macaddrs[macaddr] = 1 - ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 } - end - iflist = [ macaddrs, ipaddrs ] - - search = [] - nameserver = [] - version = -1 - Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg| - begin - version = API.unpackdw(reg.read_bin("Version")) - rescue Registry::Error - end - - reg.each_key do |key,| - catch(:not_used) do - reg.open(key) do |regdi| - dom, ns = get_dhcpinfo_key(version, regdi, iflist) - search << dom if dom - nameserver.concat(ns) if ns - end - end - end - end - [ search, nameserver ] - end - - def get_dhcpinfo_95(reg) - dhcp = reg.read_bin("DhcpInfo") - [ - API.unpackdw(dhcp[4..7]), - API.unpackdw(dhcp[8..11]), - 1, - dhcp[45..50], - reg.read_bin("OptionInfo"), - ] - end - - def get_dhcpinfo_98(reg) - [ - API.unpackdw(reg.read_bin("DhcpIPAddress")), - API.unpackdw(reg.read_bin("DhcpSubnetMask")), - API.unpackdw(reg.read_bin("HardwareType")), - reg.read_bin("HardwareAddress"), - reg.read_bin("OptionInfo"), - ] - end - - def get_dhcpinfo_key(version, reg, iflist) - info = case version - when 1 - get_dhcpinfo_95(reg) - when 2 - get_dhcpinfo_98(reg) - else - begin - get_dhcpinfo_98(reg) - rescue Registry::Error - get_dhcpinfo_95(reg) - end - end - ipaddr, netmask, hwtype, macaddr, opt = info - throw :not_used unless - ipaddr and ipaddr != 0 and - netmask and netmask != 0 and - macaddr and macaddr.size == 6 and - hwtype == 1 and - iflist[0][macaddr] and iflist[1][ipaddr] - - size = opt.size - idx = 0 - while idx <= size - opttype = opt[idx] - optsize = opt[idx + 1] - optval = opt[idx + 2, optsize] - case opttype - when 0xFF ## term - break - when 0x0F ## domain - domain = optval.chomp("\0") - when 0x06 ## dns - nameserver = optval.scan(/..../).collect { |addr| - "%d.%d.%d.%d" % addr.unpack('C4') - } - end - idx += optsize + 2 - end - [ domain, nameserver ] - rescue Registry::Error - throw :not_used - end - end - - module WsControl - module WSock32 - extend Fiddle::Importer - dlload "wsock32.dll" - end - WsControl = WSock32.extern "int WsControl(int, int, void *, void *, void *, void *", :stdcall - WSAGetLastError = WSock32.extern "int WSAGetLastError(void)", :stdcall - - MAX_TDI_ENTITIES = 512 - IPPROTO_TCP = 6 - WSCTL_TCP_QUERY_INFORMATION = 0 - INFO_CLASS_GENERIC = 0x100 - INFO_CLASS_PROTOCOL = 0x200 - INFO_TYPE_PROVIDER = 0x100 - ENTITY_LIST_ID = 0 - GENERIC_ENTITY = 0 - CL_NL_ENTITY = 0x301 - IF_ENTITY = 0x200 - ENTITY_TYPE_ID = 1 - CL_NL_IP = 0x303 - IF_MIB = 0x202 - IF_MIB_STATS_ID = 1 - IP_MIB_ADDRTABLE_ENTRY_ID = 0x102 - - def self.wsctl(tei_entity, tei_instance, - toi_class, toi_type, toi_id, - buffsize) - reqinfo = [ - ## TDIEntityID - tei_entity, tei_instance, - ## TDIObjectID - toi_class, toi_type, toi_id, - ## TCP_REQUEST_INFORMATION_EX - "" - ].pack('VVVVVa16') - reqsize = API.packdw(reqinfo.size) - buff = "\0" * buffsize - buffsize = API.packdw(buffsize) - result = WsControl.call( - IPPROTO_TCP, - WSCTL_TCP_QUERY_INFORMATION, - reqinfo, reqsize, - buff, buffsize) - if result != 0 - raise RuntimeError, "WsControl failed.(#{result})" - end - [ buff, API.unpackdw(buffsize) ] - end - private_class_method :wsctl - - def self.get_iflist - # Get TDI Entity List - entities, size = - wsctl(GENERIC_ENTITY, 0, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_LIST_ID, - MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID) - entities = entities[0, size]. - scan(/.{8}/). - collect { |e| e.unpack('VV') } - - # Get MIB Interface List - iflist = [] - ifcount = 0 - entities.each do |entity, instance| - if( (entity & IF_ENTITY)>0 ) - ifcount += 1 - etype, = wsctl(entity, instance, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_TYPE_ID, - 4) - if( (API.unpackdw(etype) & IF_MIB)==IF_MIB ) - ifentry, = wsctl(entity, instance, - INFO_CLASS_PROTOCOL, - INFO_TYPE_PROVIDER, - IF_MIB_STATS_ID, - 21 * 4 + 8 + 130) # sizeof(IFEntry) - iflist << [ - API.unpackdw(ifentry[0,4]), - ifentry[20, 6] - ] - end - end - end - - # Get IP Addresses - entities.each do |entity, instance| - if entity == CL_NL_ENTITY - etype, = wsctl(entity, instance, - INFO_CLASS_GENERIC, - INFO_TYPE_PROVIDER, - ENTITY_TYPE_ID, - 4) - if API.unpackdw(etype) == CL_NL_IP - ipentries, = wsctl(entity, instance, - INFO_CLASS_PROTOCOL, - INFO_TYPE_PROVIDER, - IP_MIB_ADDRTABLE_ENTRY_ID, - 24 * (ifcount+1)) # sizeof(IPAddrEntry) - ipentries.scan(/.{24}/) do |ipentry| - ipaddr, index = ipentry.unpack('VV') - if ifitem = iflist.assoc(index) - ifitem << ipaddr - end - end - end - end - end - iflist - end - end - __EOS__ -end -#==================================================================== - end -end |
