1# -*- ruby -*- 2# frozen_string_literal: true 3 4# for backward compatibility 5warn "Win32API is deprecated after Ruby 1.9.1; use fiddle directly instead", uplevel: 2 6 7require 'fiddle/import' 8 9class Win32API 10 DLL = {} 11 TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG} 12 POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*' 13 14 WIN32_TYPES = "VPpNnLlIi" 15 DL_TYPES = "0SSI" 16 17 def initialize(dllname, func, import, export = "0", calltype = :stdcall) 18 @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1') 19 import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]} 20 export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)] 21 calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype] 22 23 handle = DLL[dllname] ||= 24 begin 25 Fiddle.dlopen(dllname) 26 rescue Fiddle::DLError 27 raise unless File.extname(dllname).empty? 28 Fiddle.dlopen(dllname + ".dll") 29 end 30 31 @func = Fiddle::Function.new(handle[func], import, export, calltype) 32 rescue Fiddle::DLError => e 33 raise LoadError, e.message, e.backtrace 34 end 35 36 def call(*args) 37 import = @proto.split("") 38 args.each_with_index do |x, i| 39 args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S" 40 args[i], = [x].pack("I").unpack("i") if import[i] == "I" 41 end 42 ret, = @func.call(*args) 43 return ret || 0 44 end 45 46 alias Call call 47end 48