From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/ext/win32ole/Makefile | 150 + jni/ruby/ext/win32ole/depend | 12 + jni/ruby/ext/win32ole/extconf.rb | 44 + jni/ruby/ext/win32ole/lib/win32ole/property.rb | 16 + jni/ruby/ext/win32ole/sample/excel1.rb | 36 + jni/ruby/ext/win32ole/sample/excel2.rb | 30 + jni/ruby/ext/win32ole/sample/excel3.rb | 20 + jni/ruby/ext/win32ole/sample/ie.rb | 11 + jni/ruby/ext/win32ole/sample/ieconst.rb | 32 + jni/ruby/ext/win32ole/sample/ienavi.rb | 40 + jni/ruby/ext/win32ole/sample/ienavi2.rb | 40 + jni/ruby/ext/win32ole/sample/oledirs.rb | 23 + jni/ruby/ext/win32ole/sample/olegen.rb | 347 ++ jni/ruby/ext/win32ole/sample/xml.rb | 7306 ++++++++++++++++++++++++ jni/ruby/ext/win32ole/win32ole.c | 4073 +++++++++++++ jni/ruby/ext/win32ole/win32ole.h | 155 + jni/ruby/ext/win32ole/win32ole_error.c | 83 + jni/ruby/ext/win32ole/win32ole_error.h | 8 + jni/ruby/ext/win32ole/win32ole_event.c | 1275 +++++ jni/ruby/ext/win32ole/win32ole_event.h | 6 + jni/ruby/ext/win32ole/win32ole_method.c | 950 +++ jni/ruby/ext/win32ole/win32ole_method.h | 16 + jni/ruby/ext/win32ole/win32ole_param.c | 438 ++ jni/ruby/ext/win32ole/win32ole_param.h | 8 + jni/ruby/ext/win32ole/win32ole_record.c | 604 ++ jni/ruby/ext/win32ole/win32ole_record.h | 10 + jni/ruby/ext/win32ole/win32ole_type.c | 915 +++ jni/ruby/ext/win32ole/win32ole_type.h | 8 + jni/ruby/ext/win32ole/win32ole_typelib.c | 846 +++ jni/ruby/ext/win32ole/win32ole_typelib.h | 11 + jni/ruby/ext/win32ole/win32ole_variable.c | 380 ++ jni/ruby/ext/win32ole/win32ole_variable.h | 8 + jni/ruby/ext/win32ole/win32ole_variant.c | 734 +++ jni/ruby/ext/win32ole/win32ole_variant.h | 9 + jni/ruby/ext/win32ole/win32ole_variant_m.c | 149 + jni/ruby/ext/win32ole/win32ole_variant_m.h | 7 + 36 files changed, 18800 insertions(+) create mode 100644 jni/ruby/ext/win32ole/Makefile create mode 100644 jni/ruby/ext/win32ole/depend create mode 100644 jni/ruby/ext/win32ole/extconf.rb create mode 100644 jni/ruby/ext/win32ole/lib/win32ole/property.rb create mode 100644 jni/ruby/ext/win32ole/sample/excel1.rb create mode 100644 jni/ruby/ext/win32ole/sample/excel2.rb create mode 100644 jni/ruby/ext/win32ole/sample/excel3.rb create mode 100644 jni/ruby/ext/win32ole/sample/ie.rb create mode 100644 jni/ruby/ext/win32ole/sample/ieconst.rb create mode 100644 jni/ruby/ext/win32ole/sample/ienavi.rb create mode 100644 jni/ruby/ext/win32ole/sample/ienavi2.rb create mode 100644 jni/ruby/ext/win32ole/sample/oledirs.rb create mode 100644 jni/ruby/ext/win32ole/sample/olegen.rb create mode 100644 jni/ruby/ext/win32ole/sample/xml.rb create mode 100644 jni/ruby/ext/win32ole/win32ole.c create mode 100644 jni/ruby/ext/win32ole/win32ole.h create mode 100644 jni/ruby/ext/win32ole/win32ole_error.c create mode 100644 jni/ruby/ext/win32ole/win32ole_error.h create mode 100644 jni/ruby/ext/win32ole/win32ole_event.c create mode 100644 jni/ruby/ext/win32ole/win32ole_event.h create mode 100644 jni/ruby/ext/win32ole/win32ole_method.c create mode 100644 jni/ruby/ext/win32ole/win32ole_method.h create mode 100644 jni/ruby/ext/win32ole/win32ole_param.c create mode 100644 jni/ruby/ext/win32ole/win32ole_param.h create mode 100644 jni/ruby/ext/win32ole/win32ole_record.c create mode 100644 jni/ruby/ext/win32ole/win32ole_record.h create mode 100644 jni/ruby/ext/win32ole/win32ole_type.c create mode 100644 jni/ruby/ext/win32ole/win32ole_type.h create mode 100644 jni/ruby/ext/win32ole/win32ole_typelib.c create mode 100644 jni/ruby/ext/win32ole/win32ole_typelib.h create mode 100644 jni/ruby/ext/win32ole/win32ole_variable.c create mode 100644 jni/ruby/ext/win32ole/win32ole_variable.h create mode 100644 jni/ruby/ext/win32ole/win32ole_variant.c create mode 100644 jni/ruby/ext/win32ole/win32ole_variant.h create mode 100644 jni/ruby/ext/win32ole/win32ole_variant_m.c create mode 100644 jni/ruby/ext/win32ole/win32ole_variant_m.h (limited to 'jni/ruby/ext/win32ole') diff --git a/jni/ruby/ext/win32ole/Makefile b/jni/ruby/ext/win32ole/Makefile new file mode 100644 index 0000000..e4fe34e --- /dev/null +++ b/jni/ruby/ext/win32ole/Makefile @@ -0,0 +1,150 @@ +# ***DUMMY MAKEFILE*** + +SHELL = /bin/sh + +# V=0 quiet, V=1 verbose. other values don't work. +V = 0 +Q1 = $(V:1=) +Q = $(Q1:0=@) +ECHO1 = $(V:1=@:) +ECHO = $(ECHO1:0=@echo) +NULLCMD = : + +#### Start of system configuration section. #### +top_srcdir = $(topdir)/. +srcdir = $(top_srcdir)/ext/win32ole +topdir = ../.. +hdrdir = $(top_srcdir)/include +arch_hdrdir = $(extout)/include/$(arch) +PATH_SEPARATOR = : +VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby +RUBYLIB = +RUBYOPT = - +prefix = $(DESTDIR)/usr/local +rubysitearchprefix = $(rubylibprefix)/$(sitearch) +rubyarchprefix = $(rubylibprefix)/$(arch) +rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) +exec_prefix = $(prefix) +vendorarchhdrdir = $(vendorhdrdir)/$(sitearch) +sitearchhdrdir = $(sitehdrdir)/$(sitearch) +rubyarchhdrdir = $(rubyhdrdir)/$(arch) +vendorhdrdir = $(rubyhdrdir)/vendor_ruby +sitehdrdir = $(rubyhdrdir)/site_ruby +rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) +vendorarchdir = $(vendorlibdir)/$(sitearch) +vendorlibdir = $(vendordir)/$(ruby_version) +vendordir = $(rubylibprefix)/vendor_ruby +sitearchdir = $(sitelibdir)/$(sitearch) +sitelibdir = $(sitedir)/$(ruby_version) +sitedir = $(rubylibprefix)/site_ruby +rubyarchdir = $(rubylibdir)/$(arch) +rubylibdir = $(rubylibprefix)/$(ruby_version) +sitearchincludedir = $(includedir)/$(sitearch) +archincludedir = $(includedir)/$(arch) +sitearchlibdir = $(libdir)/$(sitearch) +archlibdir = $(libdir)/$(arch) +ridir = $(datarootdir)/$(RI_BASE_NAME) +mandir = $(datarootdir)/man +localedir = $(datarootdir)/locale +libdir = $(exec_prefix)/lib +psdir = $(docdir) +pdfdir = $(docdir) +dvidir = $(docdir) +htmldir = $(docdir) +infodir = $(datarootdir)/info +docdir = $(datarootdir)/doc/$(PACKAGE) +oldincludedir = $(DESTDIR)/usr/include +includedir = $(prefix)/include +localstatedir = $(prefix)/var +sharedstatedir = $(prefix)/com +sysconfdir = $(prefix)/etc +datadir = $(datarootdir) +datarootdir = $(prefix)/share +libexecdir = $(exec_prefix)/libexec +sbindir = $(exec_prefix)/sbin +bindir = $(exec_prefix)/bin +archdir = $(rubyarchdir) + + +CC = gcc +CXX = g++ +LIBRUBY = $(LIBRUBY_SO) +LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a +LIBRUBYARG_SHARED = -Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME) +LIBRUBYARG_STATIC = -Wl,-R$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static +empty = +OUTFLAG = -o $(empty) +COUTFLAG = -o $(empty) + +RUBY_EXTCONF_H = +cflags = $(optflags) $(debugflags) $(warnflags) +optflags = -O3 -fno-fast-math +debugflags = -ggdb3 +warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat +CCDLFLAGS = -fPIC +CFLAGS = $(CCDLFLAGS) $(cflags) -fPIC $(ARCH_FLAG) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) +DEFS = +CPPFLAGS = $(DEFS) $(cppflags) +CXXFLAGS = $(CCDLFLAGS) $(cxxflags) $(ARCH_FLAG) +ldflags = -L. -fstack-protector -rdynamic -Wl,-export-dynamic +dldflags = +ARCH_FLAG = +DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) +LDSHARED = $(CC) -shared +LDSHAREDXX = $(CXX) -shared +AR = ar +EXEEXT = + +RUBY_INSTALL_NAME = $(RUBY_BASE_NAME) +RUBY_SO_NAME = ruby +RUBYW_INSTALL_NAME = +RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) +RUBYW_BASE_NAME = rubyw +RUBY_BASE_NAME = ruby + +arch = x86_64-linux +sitearch = $(arch) +ruby_version = 2.2.0 +ruby = $(topdir)/miniruby -I'$(topdir)' -I'$(top_srcdir)/lib' -I'$(extout)/$(arch)' -I'$(extout)/common' +RUBY = $(ruby) +ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h + +RM = rm -f +RM_RF = $(RUBY) -run -e rm -- -rf +RMDIRS = rmdir --ignore-fail-on-non-empty -p +MAKEDIRS = /bin/mkdir -p +INSTALL = /usr/bin/install -c +INSTALL_PROG = $(INSTALL) -m 0755 +INSTALL_DATA = $(INSTALL) -m 644 +COPY = cp +TOUCH = exit > + +#### End of system configuration section. #### + +preload = +CLEANFILES = mkmf.log +DISTCLEANFILES = + +all install static install-so install-rb: Makefile +.PHONY: all install static install-so install-rb +.PHONY: clean clean-so clean-static clean-rb + + +clean-static:: +clean-rb-default:: +clean-rb:: +clean-so:: +clean: clean-so clean-static clean-rb-default clean-rb + -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time + +distclean-rb-default:: +distclean-rb:: +distclean-so:: +distclean-static:: +distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb + -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true + +realclean: distclean diff --git a/jni/ruby/ext/win32ole/depend b/jni/ruby/ext/win32ole/depend new file mode 100644 index 0000000..c8445ad --- /dev/null +++ b/jni/ruby/ext/win32ole/depend @@ -0,0 +1,12 @@ +WIN32OLE_HEADERS = $(HDRS) $(ruby_headers) +win32ole.o : win32ole.c $(WIN32OLE_HEADERS) +win32ole_variant_m.o : win32ole_variant_m.c $(WIN32OLE_HEADERS) +win32ole_typelib.o : win32ole_typelib.c $(WIN32OLE_HEADERS) +win32ole_type.o : win32ole_type.c $(WIN32OLE_HEADERS) +win32ole_variable.o : win32ole_variable.c $(WIN32OLE_HEADERS) +win32ole_method.o : win32ole_method.c $(WIN32OLE_HEADERS) +win32ole_param.o : win32ole_param.c $(WIN32OLE_HEADERS) +win32ole_variant.o : win32ole_variant.c $(WIN32OLE_HEADERS) +win32ole_event.o : win32ole_event.c $(WIN32OLE_HEADERS) +win32ole_record.o : win32ole_record.c $(WIN32OLE_HEADERS) +win32ole_error.o : win32ole_error.c $(WIN32OLE_HEADERS) diff --git a/jni/ruby/ext/win32ole/extconf.rb b/jni/ruby/ext/win32ole/extconf.rb new file mode 100644 index 0000000..59da40b --- /dev/null +++ b/jni/ruby/ext/win32ole/extconf.rb @@ -0,0 +1,44 @@ +#---------------------------------- +# extconf.rb +# $Revision: 38867 $ +#---------------------------------- +require 'mkmf' + +case RUBY_PLATFORM +when /cygwin/ + inc = nil + lib = '/usr/lib/w32api' +end + +dir_config("win32", inc, lib) + +def create_win32ole_makefile + if have_library("ole32") and + have_library("oleaut32") and + have_library("uuid", "&CLSID_CMultiLanguage", "mlang.h") and + have_library("user32") and + have_library("kernel32") and + have_library("advapi32") and + have_header("windows.h") + unless have_type("IMultiLanguage2", "mlang.h") + have_type("IMultiLanguage", "mlang.h") + end + spec = nil + checking_for('thread_specific', '%s') do + spec = %w[__declspec(thread) __thread].find {|th| + try_compile("#{th} int foo;", "", :werror => true) + } + spec or 'no' + end + $defs << "-DRB_THREAD_SPECIFIC=#{spec}" if spec + create_makefile("win32ole") + end +end + + +case RUBY_PLATFORM +when /mswin/ + $CFLAGS.sub!(/((?:\A|\s)[-\/])W\d(?=\z|\s)/, '\1W3') or + $CFLAGS += ' -W3' +end +create_win32ole_makefile diff --git a/jni/ruby/ext/win32ole/lib/win32ole/property.rb b/jni/ruby/ext/win32ole/lib/win32ole/property.rb new file mode 100644 index 0000000..a68bad9 --- /dev/null +++ b/jni/ruby/ext/win32ole/lib/win32ole/property.rb @@ -0,0 +1,16 @@ +# OLEProperty +# helper class of Property with arguments. +class OLEProperty + def initialize(obj, dispid, gettypes, settypes) + @obj = obj + @dispid = dispid + @gettypes = gettypes + @settypes = settypes + end + def [](*args) + @obj._getproperty(@dispid, args, @gettypes) + end + def []=(*args) + @obj._setproperty(@dispid, args, @settypes) + end +end diff --git a/jni/ruby/ext/win32ole/sample/excel1.rb b/jni/ruby/ext/win32ole/sample/excel1.rb new file mode 100644 index 0000000..7136c93 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/excel1.rb @@ -0,0 +1,36 @@ +require 'win32ole' + +application = WIN32OLE.new('Excel.Application') + +application.visible = TRUE +workbook = application.Workbooks.Add(); +worksheet = workbook.Worksheets(1); + +=begin +worksheet.Range("A1:D1").value = ["North","South","East","West"]; +worksheet.Range("A2:B2").value = [5.2, 10]; + +worksheet.Range("C2").value = 8; +worksheet.Range("D2").value = 20; +=end + +worksheet.Range("A1:B2").value = [["North","South"], + [5.2, 10]]; + +vals = WIN32OLE_VARIANT.new([["East","West"], + [8, 20]], + WIN32OLE::VARIANT::VT_ARRAY) +worksheet.Range("C1:D2").value = vals + +range = worksheet.Range("A1:D2"); +range.Select +chart = workbook.Charts.Add; + +workbook.saved = TRUE; + +print "Now quit Excel... Please enter." +gets + +application.ActiveWorkbook.Close(0); +application.Quit(); + diff --git a/jni/ruby/ext/win32ole/sample/excel2.rb b/jni/ruby/ext/win32ole/sample/excel2.rb new file mode 100644 index 0000000..6328826 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/excel2.rb @@ -0,0 +1,30 @@ +require 'win32ole' + +# -4100 is the value for the Excel constant xl3DColumn. +ChartTypeVal = -4100; + +# Creates OLE object to Excel +excel = WIN32OLE.new("excel.application") + +# Create and rotate the chart +excel.visible = TRUE; +excel.Workbooks.Add(); +excel.Range("a1").value = 3; +excel.Range("a2").value = 2; +excel.Range("a3").value = 1; +excel.Range("a1:a3").Select(); +excelchart = excel.Charts.Add(); +excelchart.type = ChartTypeVal; + +i = 0 +i.step(180, 10) do |rot| + excelchart.rotation=rot; + sleep 0.1 +end +# Done, bye + +print "Now quit Excel... Please enter." +gets + +excel.ActiveWorkbook.Close(0); +excel.Quit(); diff --git a/jni/ruby/ext/win32ole/sample/excel3.rb b/jni/ruby/ext/win32ole/sample/excel3.rb new file mode 100644 index 0000000..1ace478 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/excel3.rb @@ -0,0 +1,20 @@ +require 'win32ole' + +#application = WIN32OLE.new('Excel.Application.5') +application = WIN32OLE.new('Excel.Application') + +application.visible = TRUE +workbook = application.Workbooks.Add(); +sheet = workbook.Worksheets(1); +sheetS = workbook.Worksheets +puts "The number of sheets is #{sheetS.count}" +puts "Now add 2 sheets after of `#{sheet.name}`" +sheetS.add({'count'=>2, 'after'=>sheet}) +puts "The number of sheets is #{sheetS.count}" + +print "Now quit Excel... Please enter." +gets + +application.ActiveWorkbook.Close(0); +application.Quit(); + diff --git a/jni/ruby/ext/win32ole/sample/ie.rb b/jni/ruby/ext/win32ole/sample/ie.rb new file mode 100644 index 0000000..11dc861 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/ie.rb @@ -0,0 +1,11 @@ +require 'win32ole' +url = 'http://www.ruby-lang.org/' +ie = WIN32OLE.new('InternetExplorer.Application') +ie.visible = TRUE +ie.gohome +print "Now navigate Ruby home page... Please enter." +gets +ie.navigate(url) +print "Now quit Internet Explorer... Please enter." +gets +ie.Quit() diff --git a/jni/ruby/ext/win32ole/sample/ieconst.rb b/jni/ruby/ext/win32ole/sample/ieconst.rb new file mode 100644 index 0000000..2c6a7a3 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/ieconst.rb @@ -0,0 +1,32 @@ +require 'win32ole' + +ie = WIN32OLE.new('InternetExplorer.Application') +=begin +WIN32OLE.const_load(ie) +WIN32OLE.constants.sort.each do |c| + puts "#{c} = #{WIN32OLE.const_get(c)}" +end +=end + +module IE_CONST +end + +WIN32OLE.const_load(ie, IE_CONST) +IE_CONST.constants.sort.each do |c| + puts "#{c} = #{IE_CONST.const_get(c)}" +end + +#------------------------------------------------------------ +# Remark!!! CONSTANTS has not tested enoughly!!! +# CONSTANTS is alpha release. +# If there are constants which first letter is not [a-zA-Z], +# like a '_Foo', then maybe you can access the value by +# using CONSTANTS['_Foo'] +#------------------------------------------------------------ +IE_CONST::CONSTANTS.each do |k, v| + puts "#{k} = #{v}" +end + +puts WIN32OLE::VERSION +ie.quit + diff --git a/jni/ruby/ext/win32ole/sample/ienavi.rb b/jni/ruby/ext/win32ole/sample/ienavi.rb new file mode 100644 index 0000000..8b279dd --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/ienavi.rb @@ -0,0 +1,40 @@ +require 'win32ole' + +$urls = [] + +def navigate(url) + $urls << url +end + +def stop_msg_loop + puts "Now Stop IE..." + $LOOP = FALSE; +end + +def default_handler(event, *args) + case event + when "BeforeNavigate" + puts "Now Navigate #{args[0]}..." + end +end + +ie = WIN32OLE.new('InternetExplorer.Application') +ie.visible = TRUE +ie.gohome + +ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') + +ev.on_event {|*args| default_handler(*args)} +ev.on_event("NavigateComplete") {|url| navigate(url)} +ev.on_event("Quit") {|*args| stop_msg_loop} + +$LOOP = TRUE +while ($LOOP) + WIN32OLE_EVENT.message_loop +end + +puts "You Navigated the URLs ..." +$urls.each_with_index do |url, i| + puts "(#{i+1}) #{url}" +end + diff --git a/jni/ruby/ext/win32ole/sample/ienavi2.rb b/jni/ruby/ext/win32ole/sample/ienavi2.rb new file mode 100644 index 0000000..67977e2 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/ienavi2.rb @@ -0,0 +1,40 @@ +require 'win32ole' + +class IEHandler + attr_reader :loop + def initialize + @urls = [] + @loop = true + end + def method_missing(event, *args) + case event + when "BeforeNavigate2" + puts "Now Navigate #{args[1]}..." + end + end + def onNavigateComplete2(pdisp, url) + @urls << url + end + def onOnQuit + puts "Now Stop IE..." + @loop = false + end + def put_urls + puts "You Navigated the URLs ..." + @urls.each_with_index do |url, i| + puts "(#{i+1}) #{url}" + end + end +end + +ie = WIN32OLE.new('InternetExplorer.Application') +ie.visible = true +ie.gohome + +ev = WIN32OLE_EVENT.new(ie) +ev.handler = IEHandler.new + +while (ev.handler.loop) + WIN32OLE_EVENT.message_loop +end +ev.handler.put_urls diff --git a/jni/ruby/ext/win32ole/sample/oledirs.rb b/jni/ruby/ext/win32ole/sample/oledirs.rb new file mode 100644 index 0000000..dbacc21 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/oledirs.rb @@ -0,0 +1,23 @@ +# +# You need WSH(Windows Scripting Host) to run this script. +# + +require "win32ole" + +def listup(items) +# items.each do |i| + for i in items + puts i.name + end +end + +fs = WIN32OLE.new("Scripting.FileSystemObject") + +folder = fs.GetFolder(".") + +puts "--- folder of #{folder.path} ---" +listup(folder.SubFolders) + +puts "--- files of #{folder.path} ---" +listup(folder.Files) + diff --git a/jni/ruby/ext/win32ole/sample/olegen.rb b/jni/ruby/ext/win32ole/sample/olegen.rb new file mode 100644 index 0000000..17653e7 --- /dev/null +++ b/jni/ruby/ext/win32ole/sample/olegen.rb @@ -0,0 +1,347 @@ +#----------------------------- +# olegen.rb +# $Revision: 44134 $ +#----------------------------- + +require 'win32ole' + +class WIN32COMGen + def initialize(typelib) + @typelib = typelib + @receiver = "" + end + attr_reader :typelib + + def ole_classes(typelib) + begin + @ole = WIN32OLE.new(typelib) + [@ole.ole_obj_help] + rescue + WIN32OLE_TYPE.ole_classes(typelib) + end + end + + def generate_args(method) + args = [] + if method.size_opt_params >= 0 + size_required_params = method.size_params - method.size_opt_params + else + size_required_params = method.size_params - 1 + end + size_required_params.times do |i| + if method.params[i] && method.params[i].optional? + args.push "arg#{i}=nil" + else + args.push "arg#{i}" + end + end + if method.size_opt_params >= 0 + method.size_opt_params.times do |i| + args.push "arg#{i + size_required_params}=nil" + end + else + args.push "*arg" + end + args.join(", ") + end + + def generate_argtype(typedetails) + ts = '' + typedetails.each do |t| + case t + when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8' +# raise "Sorry type\"" + t + "\" not supported" + ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\"" + when 'USERDEFINED', 'Unknown Type 9' + ts << 'VT_DISPATCH' + break; + when 'SAFEARRAY' + ts << 'VT_ARRAY|' + when 'PTR' + ts << 'VT_BYREF|' + when 'INT' + ts << 'VT_I4' + else + if String === t + ts << 'VT_' + t + end + end + end + if ts.empty? + ts = 'VT_VARIANT' + elsif ts[-1] == ?| + ts += 'VT_VARIANT' + end + ts + end + + def generate_argtypes(method, proptypes) + types = method.params.collect{|param| + generate_argtype(param.ole_type_detail) + }.join(", ") + if proptypes + types += ", " if types.size > 0 + types += generate_argtype(proptypes) + end + types + end + + def generate_method_body(method, disptype, types=nil) + " ret = #{@receiver}#{disptype}(#{method.dispid}, [" + + generate_args(method).gsub("=nil", "") + + "], [" + + generate_argtypes(method, types) + + "])\n" + + " @lastargs = WIN32OLE::ARGV\n" + + " ret" + end + + def generate_method_help(method, type = nil) + str = " # " + if type + str += type + else + str += method.return_type + end + str += " #{method.name}" + if method.event? + str += " EVENT" + str += " in #{method.event_interface}" + end + if method.helpstring && method.helpstring != "" + str += "\n # " + str += method.helpstring + end + args_help = generate_method_args_help(method) + if args_help + str += "\n" + str += args_help + end + str + end + + def generate_method_args_help(method) + args = [] + method.params.each_with_index {|param, i| + h = " # #{param.ole_type} arg#{i} --- #{param.name}" + inout = [] + inout.push "IN" if param.input? + inout.push "OUT" if param.output? + h += " [#{inout.join('/')}]" + h += " ( = #{param.default})" if param.default + args.push h + } + if args.size > 0 + args.join("\n") + else + nil + end + end + + def generate_method(method, disptype, io = STDOUT, types = nil) + io.puts "\n" + io.puts generate_method_help(method) + if method.invoke_kind == 'PROPERTYPUT' + io.print " def #{method.name}=(" + else + io.print " def #{method.name}(" + end + io.print generate_args(method) + io.puts ")" + io.puts generate_method_body(method, disptype, types) + io.puts " end" + end + + def generate_propputref_methods(klass, io = STDOUT) + klass.ole_methods.select {|method| + method.invoke_kind == 'PROPERTYPUTREF' && method.visible? + }.each do |method| + generate_method(method, io) + end + end + + def generate_properties_with_args(klass, io = STDOUT) + klass.ole_methods.select {|method| + method.invoke_kind == 'PROPERTYGET' && + method.visible? && + method.size_params > 0 + }.each do |method| + types = method.return_type_detail + io.puts "\n" + io.puts generate_method_help(method, types[0]) + io.puts " def #{method.name}" + if klass.ole_type == "Class" + io.print " OLEProperty.new(@dispatch, #{method.dispid}, [" + else + io.print " OLEProperty.new(self, #{method.dispid}, [" + end + io.print generate_argtypes(method, nil) + io.print "], [" + io.print generate_argtypes(method, types) + io.puts "])" + io.puts " end" + end + end + + def generate_propput_methods(klass, io = STDOUT) + klass.ole_methods.select {|method| + method.invoke_kind == 'PROPERTYPUT' && method.visible? && + method.size_params == 1 + }.each do |method| + ms = klass.ole_methods.select {|m| + m.invoke_kind == 'PROPERTYGET' && + m.dispid == method.dispid + } + types = [] + if ms.size == 1 + types = ms[0].return_type_detail + end + generate_method(method, '_setproperty', io, types) + end + end + + def generate_propget_methods(klass, io = STDOUT) + klass.ole_methods.select {|method| + method.invoke_kind == 'PROPERTYGET' && method.visible? && + method.size_params == 0 + }.each do |method| + generate_method(method, '_getproperty', io) + end + end + + def generate_func_methods(klass, io = STDOUT) + klass.ole_methods.select {|method| + method.invoke_kind == "FUNC" && method.visible? + }.each do |method| + generate_method(method, '_invoke', io) + end + end + + def generate_methods(klass, io = STDOUT) + generate_propget_methods(klass, io) + generate_propput_methods(klass, io) + generate_properties_with_args(klass, io) + generate_func_methods(klass, io) +# generate_propputref_methods(klass, io) + end + + def generate_constants(klass, io = STDOUT) + klass.variables.select {|v| + v.visible? && v.variable_kind == 'CONSTANT' + }.each do |v| + io.print " " + io.print v.name.sub(/^./){$&.upcase} + io.print " = " + io.puts v.value + end + end + + def class_name(klass) + klass_name = klass.name + if klass.ole_type == "Class" && + klass.guid && + klass.progid + klass_name = klass.progid.gsub(/\./, '_') + end + if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name) + klass_name = 'OLE' + klass_name + end + klass_name + end + + def define_initialize(klass) + < xml.rb +# +require 'win32ole' +require 'win32ole/property' + +# +module IXMLDOMImplementation + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BOOL hasFeature + # BSTR arg0 --- feature [IN] + # BSTR arg1 --- version [IN] + def hasFeature(arg0, arg1) + ret = _invoke(145, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# Core DOM node interface +module IXMLDOMNode + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# Constants that define a node's type +module OLEtagDOMNodeType + include WIN32OLE::VARIANT + attr_reader :lastargs + NODE_INVALID = 0 + NODE_ELEMENT = 1 + NODE_ATTRIBUTE = 2 + NODE_TEXT = 3 + NODE_CDATA_SECTION = 4 + NODE_ENTITY_REFERENCE = 5 + NODE_ENTITY = 6 + NODE_PROCESSING_INSTRUCTION = 7 + NODE_COMMENT = 8 + NODE_DOCUMENT = 9 + NODE_DOCUMENT_TYPE = 10 + NODE_DOCUMENT_FRAGMENT = 11 + NODE_NOTATION = 12 +end + +# +module IXMLDOMNodeList + include WIN32OLE::VARIANT + attr_reader :lastargs + + # I4 length + # number of nodes in the collection + def length() + ret = _getproperty(74, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # PTR item + # collection of nodes + # I4 arg0 --- index [IN] + def item + OLEProperty.new(self, 0, [VT_I4], [VT_I4, VT_BYREF|VT_DISPATCH]) + end + + # IXMLDOMNode nextNode + # get next node from iterator + def nextNode() + ret = _invoke(76, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID reset + # reset the position of iterator + def reset() + ret = _invoke(77, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMNamedNodeMap + include WIN32OLE::VARIANT + attr_reader :lastargs + + # I4 length + # number of nodes in the collection + def length() + ret = _getproperty(74, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # PTR item + # collection of nodes + # I4 arg0 --- index [IN] + def item + OLEProperty.new(self, 0, [VT_I4], [VT_I4, VT_BYREF|VT_DISPATCH]) + end + + # IXMLDOMNode getNamedItem + # lookup item by name + # BSTR arg0 --- name [IN] + def getNamedItem(arg0) + ret = _invoke(83, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode setNamedItem + # set item by name + # IXMLDOMNode arg0 --- newItem [IN] + def setNamedItem(arg0) + ret = _invoke(84, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeNamedItem + # remove item by name + # BSTR arg0 --- name [IN] + def removeNamedItem(arg0) + ret = _invoke(85, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode getQualifiedItem + # lookup the item by name and namespace + # BSTR arg0 --- baseName [IN] + # BSTR arg1 --- namespaceURI [IN] + def getQualifiedItem(arg0, arg1) + ret = _invoke(87, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeQualifiedItem + # remove the item by name and namespace + # BSTR arg0 --- baseName [IN] + # BSTR arg1 --- namespaceURI [IN] + def removeQualifiedItem(arg0, arg1) + ret = _invoke(88, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextNode + # get next node from iterator + def nextNode() + ret = _invoke(89, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID reset + # reset the position of iterator + def reset() + ret = _invoke(90, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMDocument + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentType doctype + # node corresponding to the DOCTYPE + def doctype() + ret = _getproperty(38, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMImplementation implementation + # info on this DOM implementation + def implementation() + ret = _getproperty(39, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement documentElement + # the root of the tree + def documentElement() + ret = _getproperty(40, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + # get the state of the XML document + def readyState() + ret = _getproperty(-525, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMParseError parseError + # get the last parser error + def parseError() + ret = _getproperty(59, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR url + # get the URL for the loaded XML document + def url() + ret = _getproperty(60, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL async + # flag for asynchronous download + def async() + ret = _getproperty(61, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL validateOnParse + # indicates whether the parser performs validation + def validateOnParse() + ret = _getproperty(65, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals() + ret = _getproperty(66, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace() + ret = _getproperty(67, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID async + # flag for asynchronous download + def async=(arg0) + ret = _setproperty(61, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID validateOnParse + # indicates whether the parser performs validation + def validateOnParse=(arg0) + ret = _setproperty(65, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals=(arg0) + ret = _setproperty(66, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace=(arg0) + ret = _setproperty(67, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID onreadystatechange + # register a readystatechange event handler + def onreadystatechange=(arg0) + ret = _setproperty(68, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ondataavailable + # register an ondataavailable event handler + def ondataavailable=(arg0) + ret = _setproperty(69, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ontransformnode + # register an ontransformnode event handler + def ontransformnode=(arg0) + ret = _setproperty(70, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement createElement + # create an Element node + # BSTR arg0 --- tagName [IN] + def createElement(arg0) + ret = _invoke(41, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentFragment createDocumentFragment + # create a DocumentFragment node + def createDocumentFragment() + ret = _invoke(42, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMText createTextNode + # create a text node + # BSTR arg0 --- data [IN] + def createTextNode(arg0) + ret = _invoke(43, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMComment createComment + # create a comment node + # BSTR arg0 --- data [IN] + def createComment(arg0) + ret = _invoke(44, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMCDATASection createCDATASection + # create a CDATA section node + # BSTR arg0 --- data [IN] + def createCDATASection(arg0) + ret = _invoke(45, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMProcessingInstruction createProcessingInstruction + # create a processing instruction node + # BSTR arg0 --- target [IN] + # BSTR arg1 --- data [IN] + def createProcessingInstruction(arg0, arg1) + ret = _invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute createAttribute + # create an attribute node + # BSTR arg0 --- name [IN] + def createAttribute(arg0) + ret = _invoke(47, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMEntityReference createEntityReference + # create an entity reference node + # BSTR arg0 --- name [IN] + def createEntityReference(arg0) + ret = _invoke(49, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList getElementsByTagName + # build a list of elements by name + # BSTR arg0 --- tagName [IN] + def getElementsByTagName(arg0) + ret = _invoke(50, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode createNode + # create a node of the specified node type and name + # VARIANT arg0 --- type [IN] + # BSTR arg1 --- name [IN] + # BSTR arg2 --- namespaceURI [IN] + def createNode(arg0, arg1, arg2) + ret = _invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nodeFromID + # retrieve node from it's ID + # BSTR arg0 --- idString [IN] + def nodeFromID(arg0) + ret = _invoke(56, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL load + # load document from the specified XML source + # VARIANT arg0 --- xmlSource [IN] + def load(arg0) + ret = _invoke(58, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID abort + # abort an asynchronous download + def abort() + ret = _invoke(62, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL loadXML + # load the document from a string + # BSTR arg0 --- bstrXML [IN] + def loadXML(arg0) + ret = _invoke(63, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID save + # save the document to a specified desination + # VARIANT arg0 --- desination [IN] + def save(arg0) + ret = _invoke(64, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMDocumentType + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR name + # name of the document type (root of the tree) + def name() + ret = _getproperty(131, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap entities + # a list of entities in the document + def entities() + ret = _getproperty(132, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap notations + # a list of notations in the document + def notations() + ret = _getproperty(133, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMElement + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR tagName + # get the tagName of the element + def tagName() + ret = _getproperty(97, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT getAttribute + # look up the string value of an attribute by name + # BSTR arg0 --- name [IN] + def getAttribute(arg0) + ret = _invoke(99, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID setAttribute + # set the string value of an attribute by name + # BSTR arg0 --- name [IN] + # VARIANT arg1 --- value [IN] + def setAttribute(arg0, arg1) + ret = _invoke(100, [arg0, arg1], [VT_BSTR, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID removeAttribute + # remove an attribute by name + # BSTR arg0 --- name [IN] + def removeAttribute(arg0) + ret = _invoke(101, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute getAttributeNode + # look up the attribute node by name + # BSTR arg0 --- name [IN] + def getAttributeNode(arg0) + ret = _invoke(102, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute setAttributeNode + # set the specified attribute on the element + # IXMLDOMAttribute arg0 --- DOMAttribute [IN] + def setAttributeNode(arg0) + ret = _invoke(103, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute removeAttributeNode + # remove the specified attribute + # IXMLDOMAttribute arg0 --- DOMAttribute [IN] + def removeAttributeNode(arg0) + ret = _invoke(104, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList getElementsByTagName + # build a list of elements by name + # BSTR arg0 --- tagName [IN] + def getElementsByTagName(arg0) + ret = _invoke(105, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID normalize + # collapse all adjacent text nodes in sub-tree + def normalize() + ret = _invoke(106, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMAttribute + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR name + # get name of the attribute + def name() + ret = _getproperty(118, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT value + # string value of the attribute + def value() + ret = _getproperty(120, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID value + # string value of the attribute + def value=(arg0) + ret = _setproperty(120, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMDocumentFragment + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMText + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR data + # value of the node + def data() + ret = _getproperty(109, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 length + # number of characters in value + def length() + ret = _getproperty(110, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID data + # value of the node + def data=(arg0) + ret = _setproperty(109, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR substringData + # retrieve substring of value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def substringData(arg0, arg1) + ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID appendData + # append string to value + # BSTR arg0 --- data [IN] + def appendData(arg0) + ret = _invoke(112, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID insertData + # insert string into value + # I4 arg0 --- offset [IN] + # BSTR arg1 --- data [IN] + def insertData(arg0, arg1) + ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID deleteData + # delete string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def deleteData(arg0, arg1) + ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID replaceData + # replace string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + # BSTR arg2 --- data [IN] + def replaceData(arg0, arg1, arg2) + ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMText splitText + # split the text node into two text nodes at the position specified + # I4 arg0 --- offset [IN] + def splitText(arg0) + ret = _invoke(123, [arg0], [VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMCharacterData + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR data + # value of the node + def data() + ret = _getproperty(109, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 length + # number of characters in value + def length() + ret = _getproperty(110, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID data + # value of the node + def data=(arg0) + ret = _setproperty(109, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR substringData + # retrieve substring of value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def substringData(arg0, arg1) + ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID appendData + # append string to value + # BSTR arg0 --- data [IN] + def appendData(arg0) + ret = _invoke(112, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID insertData + # insert string into value + # I4 arg0 --- offset [IN] + # BSTR arg1 --- data [IN] + def insertData(arg0, arg1) + ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID deleteData + # delete string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def deleteData(arg0, arg1) + ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID replaceData + # replace string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + # BSTR arg2 --- data [IN] + def replaceData(arg0, arg1, arg2) + ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMComment + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR data + # value of the node + def data() + ret = _getproperty(109, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 length + # number of characters in value + def length() + ret = _getproperty(110, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID data + # value of the node + def data=(arg0) + ret = _setproperty(109, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR substringData + # retrieve substring of value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def substringData(arg0, arg1) + ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID appendData + # append string to value + # BSTR arg0 --- data [IN] + def appendData(arg0) + ret = _invoke(112, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID insertData + # insert string into value + # I4 arg0 --- offset [IN] + # BSTR arg1 --- data [IN] + def insertData(arg0, arg1) + ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID deleteData + # delete string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def deleteData(arg0, arg1) + ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID replaceData + # replace string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + # BSTR arg2 --- data [IN] + def replaceData(arg0, arg1, arg2) + ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMCDATASection + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR data + # value of the node + def data() + ret = _getproperty(109, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 length + # number of characters in value + def length() + ret = _getproperty(110, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID data + # value of the node + def data=(arg0) + ret = _setproperty(109, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR substringData + # retrieve substring of value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def substringData(arg0, arg1) + ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID appendData + # append string to value + # BSTR arg0 --- data [IN] + def appendData(arg0) + ret = _invoke(112, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID insertData + # insert string into value + # I4 arg0 --- offset [IN] + # BSTR arg1 --- data [IN] + def insertData(arg0, arg1) + ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID deleteData + # delete string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + def deleteData(arg0, arg1) + ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID replaceData + # replace string within the value + # I4 arg0 --- offset [IN] + # I4 arg1 --- count [IN] + # BSTR arg2 --- data [IN] + def replaceData(arg0, arg1, arg2) + ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMText splitText + # split the text node into two text nodes at the position specified + # I4 arg0 --- offset [IN] + def splitText(arg0) + ret = _invoke(123, [arg0], [VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMProcessingInstruction + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR target + # the target + def target() + ret = _getproperty(127, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR data + # the data + def data() + ret = _getproperty(128, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID data + # the data + def data=(arg0) + ret = _setproperty(128, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMEntityReference + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# structure for reporting parser errors +module IXMLDOMParseError + include WIN32OLE::VARIANT + attr_reader :lastargs + + # I4 errorCode + # the error code + def errorCode() + ret = _getproperty(0, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR url + # the URL of the XML document containing the error + def url() + ret = _getproperty(179, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR reason + # the cause of the error + def reason() + ret = _getproperty(180, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR srcText + # the data where the error occurred + def srcText() + ret = _getproperty(181, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 line + # the line number in the XML document where the error occurred + def line() + ret = _getproperty(182, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 linepos + # the character position in the line containing the error + def linepos() + ret = _getproperty(183, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 filepos + # the absolute file position in the XML document containing the error + def filepos() + ret = _getproperty(184, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMNotation + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT publicId + # the public ID + def publicId() + ret = _getproperty(136, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT systemId + # the system ID + def systemId() + ret = _getproperty(137, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# +module IXMLDOMEntity + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT publicId + # the public ID + def publicId() + ret = _getproperty(140, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT systemId + # the system ID + def systemId() + ret = _getproperty(141, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR notationName + # the name of the notation + def notationName() + ret = _getproperty(142, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# XTL runtime object +module IXTLRuntime + include WIN32OLE::VARIANT + attr_reader :lastargs + + # BSTR nodeName + # name of the node + def nodeName() + ret = _getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = _getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = _getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = _getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = _getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = _getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = _getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = _getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = _getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = _getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = _getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = _getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = _getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = _getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = _getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = _getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = _setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = _setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = _setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = _setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = _invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = _invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = _invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = _invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 uniqueID + # IXMLDOMNode arg0 --- pNode [IN] + def uniqueID(arg0) + ret = _invoke(187, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 depth + # IXMLDOMNode arg0 --- pNode [IN] + def depth(arg0) + ret = _invoke(188, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 childNumber + # IXMLDOMNode arg0 --- pNode [IN] + def childNumber(arg0) + ret = _invoke(189, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 ancestorChildNumber + # BSTR arg0 --- bstrNodeName [IN] + # IXMLDOMNode arg1 --- pNode [IN] + def ancestorChildNumber(arg0, arg1) + ret = _invoke(190, [arg0, arg1], [VT_BSTR, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 absoluteChildNumber + # IXMLDOMNode arg0 --- pNode [IN] + def absoluteChildNumber(arg0) + ret = _invoke(191, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR formatIndex + # I4 arg0 --- lIndex [IN] + # BSTR arg1 --- bstrFormat [IN] + def formatIndex(arg0, arg1) + ret = _invoke(192, [arg0, arg1], [VT_I4, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR formatNumber + # R8 arg0 --- dblNumber [IN] + # BSTR arg1 --- bstrFormat [IN] + def formatNumber(arg0, arg1) + ret = _invoke(193, [arg0, arg1], [VT_R8, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR formatDate + # VARIANT arg0 --- varDate [IN] + # BSTR arg1 --- bstrFormat [IN] + # VARIANT arg2 --- varDestLocale [IN] + def formatDate(arg0, arg1, arg2=nil) + ret = _invoke(194, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR formatTime + # VARIANT arg0 --- varTime [IN] + # BSTR arg1 --- bstrFormat [IN] + # VARIANT arg2 --- varDestLocale [IN] + def formatTime(arg0, arg1, arg2=nil) + ret = _invoke(195, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# W3C-DOM XML Document +class Microsoft_XMLDOM_1_0 # DOMDocument + include WIN32OLE::VARIANT + attr_reader :lastargs + attr_reader :dispatch + attr_reader :clsid + attr_reader :progid + + def initialize(obj = nil) + @clsid = "{2933BF90-7B36-11D2-B20E-00C04F983E60}" + @progid = "Microsoft.XMLDOM.1.0" + if obj.nil? + @dispatch = WIN32OLE.new(@progid) + else + @dispatch = obj + end + end + + def method_missing(cmd, *arg) + @dispatch.method_missing(cmd, *arg) + end + + # BSTR nodeName + # name of the node + def nodeName() + ret = @dispatch._getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = @dispatch._getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = @dispatch._getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = @dispatch._getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = @dispatch._getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = @dispatch._getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = @dispatch._getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = @dispatch._getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = @dispatch._getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = @dispatch._getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = @dispatch._getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = @dispatch._getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = @dispatch._getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = @dispatch._getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = @dispatch._getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = @dispatch._getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = @dispatch._getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = @dispatch._getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = @dispatch._getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = @dispatch._getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = @dispatch._getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = @dispatch._getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentType doctype + # node corresponding to the DOCTYPE + def doctype() + ret = @dispatch._getproperty(38, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMImplementation implementation + # info on this DOM implementation + def implementation() + ret = @dispatch._getproperty(39, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement documentElement + # the root of the tree + def documentElement() + ret = @dispatch._getproperty(40, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + # get the state of the XML document + def readyState() + ret = @dispatch._getproperty(-525, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMParseError parseError + # get the last parser error + def parseError() + ret = @dispatch._getproperty(59, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR url + # get the URL for the loaded XML document + def url() + ret = @dispatch._getproperty(60, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL async + # flag for asynchronous download + def async() + ret = @dispatch._getproperty(61, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL validateOnParse + # indicates whether the parser performs validation + def validateOnParse() + ret = @dispatch._getproperty(65, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals() + ret = @dispatch._getproperty(66, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace() + ret = @dispatch._getproperty(67, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = @dispatch._setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = @dispatch._setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = @dispatch._setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = @dispatch._setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID async + # flag for asynchronous download + def async=(arg0) + ret = @dispatch._setproperty(61, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID validateOnParse + # indicates whether the parser performs validation + def validateOnParse=(arg0) + ret = @dispatch._setproperty(65, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals=(arg0) + ret = @dispatch._setproperty(66, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace=(arg0) + ret = @dispatch._setproperty(67, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID onreadystatechange + # register a readystatechange event handler + def onreadystatechange=(arg0) + ret = @dispatch._setproperty(68, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ondataavailable + # register an ondataavailable event handler + def ondataavailable=(arg0) + ret = @dispatch._setproperty(69, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ontransformnode + # register an ontransformnode event handler + def ontransformnode=(arg0) + ret = @dispatch._setproperty(70, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = @dispatch._invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = @dispatch._invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = @dispatch._invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = @dispatch._invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = @dispatch._invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = @dispatch._invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = @dispatch._invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = @dispatch._invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = @dispatch._invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = @dispatch._invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement createElement + # create an Element node + # BSTR arg0 --- tagName [IN] + def createElement(arg0) + ret = @dispatch._invoke(41, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentFragment createDocumentFragment + # create a DocumentFragment node + def createDocumentFragment() + ret = @dispatch._invoke(42, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMText createTextNode + # create a text node + # BSTR arg0 --- data [IN] + def createTextNode(arg0) + ret = @dispatch._invoke(43, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMComment createComment + # create a comment node + # BSTR arg0 --- data [IN] + def createComment(arg0) + ret = @dispatch._invoke(44, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMCDATASection createCDATASection + # create a CDATA section node + # BSTR arg0 --- data [IN] + def createCDATASection(arg0) + ret = @dispatch._invoke(45, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMProcessingInstruction createProcessingInstruction + # create a processing instruction node + # BSTR arg0 --- target [IN] + # BSTR arg1 --- data [IN] + def createProcessingInstruction(arg0, arg1) + ret = @dispatch._invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute createAttribute + # create an attribute node + # BSTR arg0 --- name [IN] + def createAttribute(arg0) + ret = @dispatch._invoke(47, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMEntityReference createEntityReference + # create an entity reference node + # BSTR arg0 --- name [IN] + def createEntityReference(arg0) + ret = @dispatch._invoke(49, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList getElementsByTagName + # build a list of elements by name + # BSTR arg0 --- tagName [IN] + def getElementsByTagName(arg0) + ret = @dispatch._invoke(50, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode createNode + # create a node of the specified node type and name + # VARIANT arg0 --- type [IN] + # BSTR arg1 --- name [IN] + # BSTR arg2 --- namespaceURI [IN] + def createNode(arg0, arg1, arg2) + ret = @dispatch._invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nodeFromID + # retrieve node from it's ID + # BSTR arg0 --- idString [IN] + def nodeFromID(arg0) + ret = @dispatch._invoke(56, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL load + # load document from the specified XML source + # VARIANT arg0 --- xmlSource [IN] + def load(arg0) + ret = @dispatch._invoke(58, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID abort + # abort an asynchronous download + def abort() + ret = @dispatch._invoke(62, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL loadXML + # load the document from a string + # BSTR arg0 --- bstrXML [IN] + def loadXML(arg0) + ret = @dispatch._invoke(63, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID save + # save the document to a specified desination + # VARIANT arg0 --- desination [IN] + def save(arg0) + ret = @dispatch._invoke(64, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT ondataavailable EVENT in XMLDOMDocumentEvents + def ondataavailable() + ret = @dispatch._invoke(198, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT onreadystatechange EVENT in XMLDOMDocumentEvents + def onreadystatechange() + ret = @dispatch._invoke(-609, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# W3C-DOM XML Document (Apartment) +class Microsoft_FreeThreadedXMLDOM_1_0 # DOMFreeThreadedDocument + include WIN32OLE::VARIANT + attr_reader :lastargs + attr_reader :dispatch + attr_reader :clsid + attr_reader :progid + + def initialize(obj = nil) + @clsid = "{2933BF91-7B36-11D2-B20E-00C04F983E60}" + @progid = "Microsoft.FreeThreadedXMLDOM.1.0" + if obj.nil? + @dispatch = WIN32OLE.new(@progid) + else + @dispatch = obj + end + end + + def method_missing(cmd, *arg) + @dispatch.method_missing(cmd, *arg) + end + + # BSTR nodeName + # name of the node + def nodeName() + ret = @dispatch._getproperty(2, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeValue + # value stored in the node + def nodeValue() + ret = @dispatch._getproperty(3, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DOMNodeType nodeType + # the node's type + def nodeType() + ret = @dispatch._getproperty(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode parentNode + # parent of the node + def parentNode() + ret = @dispatch._getproperty(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList childNodes + # the collection of the node's children + def childNodes() + ret = @dispatch._getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode firstChild + # first child of the node + def firstChild() + ret = @dispatch._getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode lastChild + # first child of the node + def lastChild() + ret = @dispatch._getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode previousSibling + # left sibling of the node + def previousSibling() + ret = @dispatch._getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nextSibling + # right sibling of the node + def nextSibling() + ret = @dispatch._getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNamedNodeMap attributes + # the collection of the node's attributes + def attributes() + ret = @dispatch._getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocument ownerDocument + # document that contains the node + def ownerDocument() + ret = @dispatch._getproperty(18, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR nodeTypeString + # the type of node in string form + def nodeTypeString() + ret = @dispatch._getproperty(21, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR text + # text content of the node and subtree + def text() + ret = @dispatch._getproperty(24, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL specified + # indicates whether node is a default value + def specified() + ret = @dispatch._getproperty(22, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode definition + # pointer to the definition of the node in the DTD or schema + def definition() + ret = @dispatch._getproperty(23, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue() + ret = @dispatch._getproperty(25, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT dataType + # the data type of the node + def dataType() + ret = @dispatch._getproperty(26, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR xml + # return the XML source for the node and each of its descendants + def xml() + ret = @dispatch._getproperty(27, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL parsed + # has sub-tree been completely parsed + def parsed() + ret = @dispatch._getproperty(31, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR namespaceURI + # the URI for the namespace applying to the node + def namespaceURI() + ret = @dispatch._getproperty(32, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR prefix + # the prefix for the namespace applying to the node + def prefix() + ret = @dispatch._getproperty(33, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR baseName + # the base name of the node (nodename with the prefix stripped off) + def baseName() + ret = @dispatch._getproperty(34, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentType doctype + # node corresponding to the DOCTYPE + def doctype() + ret = @dispatch._getproperty(38, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMImplementation implementation + # info on this DOM implementation + def implementation() + ret = @dispatch._getproperty(39, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement documentElement + # the root of the tree + def documentElement() + ret = @dispatch._getproperty(40, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + # get the state of the XML document + def readyState() + ret = @dispatch._getproperty(-525, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMParseError parseError + # get the last parser error + def parseError() + ret = @dispatch._getproperty(59, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR url + # get the URL for the loaded XML document + def url() + ret = @dispatch._getproperty(60, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL async + # flag for asynchronous download + def async() + ret = @dispatch._getproperty(61, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL validateOnParse + # indicates whether the parser performs validation + def validateOnParse() + ret = @dispatch._getproperty(65, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals() + ret = @dispatch._getproperty(66, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace() + ret = @dispatch._getproperty(67, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeValue + # value stored in the node + def nodeValue=(arg0) + ret = @dispatch._setproperty(3, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID text + # text content of the node and subtree + def text=(arg0) + ret = @dispatch._setproperty(24, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID nodeTypedValue + # get the strongly typed value of the node + def nodeTypedValue=(arg0) + ret = @dispatch._setproperty(25, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID dataType + # the data type of the node + def dataType=(arg0) + ret = @dispatch._setproperty(26, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID async + # flag for asynchronous download + def async=(arg0) + ret = @dispatch._setproperty(61, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID validateOnParse + # indicates whether the parser performs validation + def validateOnParse=(arg0) + ret = @dispatch._setproperty(65, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID resolveExternals + # indicates whether the parser resolves references to external DTD/Entities/Schema + def resolveExternals=(arg0) + ret = @dispatch._setproperty(66, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID preserveWhiteSpace + # indicates whether the parser preserves whitespace + def preserveWhiteSpace=(arg0) + ret = @dispatch._setproperty(67, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID onreadystatechange + # register a readystatechange event handler + def onreadystatechange=(arg0) + ret = @dispatch._setproperty(68, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ondataavailable + # register an ondataavailable event handler + def ondataavailable=(arg0) + ret = @dispatch._setproperty(69, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID ontransformnode + # register an ontransformnode event handler + def ontransformnode=(arg0) + ret = @dispatch._setproperty(70, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode insertBefore + # insert a child node + # IXMLDOMNode arg0 --- newChild [IN] + # VARIANT arg1 --- refChild [IN] + def insertBefore(arg0, arg1) + ret = @dispatch._invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode replaceChild + # replace a child node + # IXMLDOMNode arg0 --- newChild [IN] + # IXMLDOMNode arg1 --- oldChild [IN] + def replaceChild(arg0, arg1) + ret = @dispatch._invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode removeChild + # remove a child node + # IXMLDOMNode arg0 --- childNode [IN] + def removeChild(arg0) + ret = @dispatch._invoke(15, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode appendChild + # append a child node + # IXMLDOMNode arg0 --- newChild [IN] + def appendChild(arg0) + ret = @dispatch._invoke(16, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL hasChildNodes + def hasChildNodes() + ret = @dispatch._invoke(17, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode cloneNode + # BOOL arg0 --- deep [IN] + def cloneNode(arg0) + ret = @dispatch._invoke(19, [arg0], [VT_BOOL]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR transformNode + # apply the stylesheet to the subtree + # IXMLDOMNode arg0 --- stylesheet [IN] + def transformNode(arg0) + ret = @dispatch._invoke(28, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList selectNodes + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectNodes(arg0) + ret = @dispatch._invoke(29, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode selectSingleNode + # execute query on the subtree + # BSTR arg0 --- queryString [IN] + def selectSingleNode(arg0) + ret = @dispatch._invoke(30, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID transformNodeToObject + # apply the stylesheet to the subtree, returning the result through a document or a stream + # IXMLDOMNode arg0 --- stylesheet [IN] + # VARIANT arg1 --- outputObject [IN] + def transformNodeToObject(arg0, arg1) + ret = @dispatch._invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMElement createElement + # create an Element node + # BSTR arg0 --- tagName [IN] + def createElement(arg0) + ret = @dispatch._invoke(41, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMDocumentFragment createDocumentFragment + # create a DocumentFragment node + def createDocumentFragment() + ret = @dispatch._invoke(42, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMText createTextNode + # create a text node + # BSTR arg0 --- data [IN] + def createTextNode(arg0) + ret = @dispatch._invoke(43, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMComment createComment + # create a comment node + # BSTR arg0 --- data [IN] + def createComment(arg0) + ret = @dispatch._invoke(44, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMCDATASection createCDATASection + # create a CDATA section node + # BSTR arg0 --- data [IN] + def createCDATASection(arg0) + ret = @dispatch._invoke(45, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMProcessingInstruction createProcessingInstruction + # create a processing instruction node + # BSTR arg0 --- target [IN] + # BSTR arg1 --- data [IN] + def createProcessingInstruction(arg0, arg1) + ret = @dispatch._invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMAttribute createAttribute + # create an attribute node + # BSTR arg0 --- name [IN] + def createAttribute(arg0) + ret = @dispatch._invoke(47, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMEntityReference createEntityReference + # create an entity reference node + # BSTR arg0 --- name [IN] + def createEntityReference(arg0) + ret = @dispatch._invoke(49, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNodeList getElementsByTagName + # build a list of elements by name + # BSTR arg0 --- tagName [IN] + def getElementsByTagName(arg0) + ret = @dispatch._invoke(50, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode createNode + # create a node of the specified node type and name + # VARIANT arg0 --- type [IN] + # BSTR arg1 --- name [IN] + # BSTR arg2 --- namespaceURI [IN] + def createNode(arg0, arg1, arg2) + ret = @dispatch._invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # IXMLDOMNode nodeFromID + # retrieve node from it's ID + # BSTR arg0 --- idString [IN] + def nodeFromID(arg0) + ret = @dispatch._invoke(56, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL load + # load document from the specified XML source + # VARIANT arg0 --- xmlSource [IN] + def load(arg0) + ret = @dispatch._invoke(58, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID abort + # abort an asynchronous download + def abort() + ret = @dispatch._invoke(62, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BOOL loadXML + # load the document from a string + # BSTR arg0 --- bstrXML [IN] + def loadXML(arg0) + ret = @dispatch._invoke(63, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID save + # save the document to a specified desination + # VARIANT arg0 --- desination [IN] + def save(arg0) + ret = @dispatch._invoke(64, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT ondataavailable EVENT in XMLDOMDocumentEvents + def ondataavailable() + ret = @dispatch._invoke(198, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT onreadystatechange EVENT in XMLDOMDocumentEvents + def onreadystatechange() + ret = @dispatch._invoke(-609, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# IXMLHttpRequest Interface +module IXMLHttpRequest + include WIN32OLE::VARIANT + attr_reader :lastargs + + # I4 status + # Get HTTP status code + def status() + ret = _getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR statusText + # Get HTTP status text + def statusText() + ret = _getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DISPATCH responseXML + # Get response body + def responseXML() + ret = _getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR responseText + # Get response body + def responseText() + ret = _getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT responseBody + # Get response body + def responseBody() + ret = _getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT responseStream + # Get response body + def responseStream() + ret = _getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + # Get ready state + def readyState() + ret = _getproperty(13, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID onreadystatechange + # Register a complete event handler + def onreadystatechange=(arg0) + ret = _setproperty(14, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID open + # Open HTTP connection + # BSTR arg0 --- bstrMethod [IN] + # BSTR arg1 --- bstrUrl [IN] + # VARIANT arg2 --- varAsync [IN] + # VARIANT arg3 --- bstrUser [IN] + # VARIANT arg4 --- bstrPassword [IN] + def open(arg0, arg1, arg2=nil, arg3=nil, arg4=nil) + ret = _invoke(1, [arg0, arg1, arg2, arg3, arg4], [VT_BSTR, VT_BSTR, VT_VARIANT, VT_VARIANT, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID setRequestHeader + # Add HTTP request header + # BSTR arg0 --- bstrHeader [IN] + # BSTR arg1 --- bstrValue [IN] + def setRequestHeader(arg0, arg1) + ret = _invoke(2, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR getResponseHeader + # Get HTTP response header + # BSTR arg0 --- bstrHeader [IN] + def getResponseHeader(arg0) + ret = _invoke(3, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR getAllResponseHeaders + # Get all HTTP response headers + def getAllResponseHeaders() + ret = _invoke(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID send + # Send HTTP request + # VARIANT arg0 --- varBody [IN] + def send(arg0=nil) + ret = _invoke(5, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID abort + # Abort HTTP request + def abort() + ret = _invoke(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# XML HTTP Request class. +class Microsoft_XMLHTTP_1 # XMLHTTPRequest + include WIN32OLE::VARIANT + attr_reader :lastargs + attr_reader :dispatch + attr_reader :clsid + attr_reader :progid + + def initialize(obj = nil) + @clsid = "{ED8C108E-4349-11D2-91A4-00C04F7969E8}" + @progid = "Microsoft.XMLHTTP.1" + if obj.nil? + @dispatch = WIN32OLE.new(@progid) + else + @dispatch = obj + end + end + + def method_missing(cmd, *arg) + @dispatch.method_missing(cmd, *arg) + end + + # I4 status + # Get HTTP status code + def status() + ret = @dispatch._getproperty(7, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR statusText + # Get HTTP status text + def statusText() + ret = @dispatch._getproperty(8, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # DISPATCH responseXML + # Get response body + def responseXML() + ret = @dispatch._getproperty(9, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR responseText + # Get response body + def responseText() + ret = @dispatch._getproperty(10, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT responseBody + # Get response body + def responseBody() + ret = @dispatch._getproperty(11, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VARIANT responseStream + # Get response body + def responseStream() + ret = @dispatch._getproperty(12, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + # Get ready state + def readyState() + ret = @dispatch._getproperty(13, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID onreadystatechange + # Register a complete event handler + def onreadystatechange=(arg0) + ret = @dispatch._setproperty(14, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID open + # Open HTTP connection + # BSTR arg0 --- bstrMethod [IN] + # BSTR arg1 --- bstrUrl [IN] + # VARIANT arg2 --- varAsync [IN] + # VARIANT arg3 --- bstrUser [IN] + # VARIANT arg4 --- bstrPassword [IN] + def open(arg0, arg1, arg2=nil, arg3=nil, arg4=nil) + ret = @dispatch._invoke(1, [arg0, arg1, arg2, arg3, arg4], [VT_BSTR, VT_BSTR, VT_VARIANT, VT_VARIANT, VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID setRequestHeader + # Add HTTP request header + # BSTR arg0 --- bstrHeader [IN] + # BSTR arg1 --- bstrValue [IN] + def setRequestHeader(arg0, arg1) + ret = @dispatch._invoke(2, [arg0, arg1], [VT_BSTR, VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR getResponseHeader + # Get HTTP response header + # BSTR arg0 --- bstrHeader [IN] + def getResponseHeader(arg0) + ret = @dispatch._invoke(3, [arg0], [VT_BSTR]) + @lastargs = WIN32OLE::ARGV + ret + end + + # BSTR getAllResponseHeaders + # Get all HTTP response headers + def getAllResponseHeaders() + ret = @dispatch._invoke(4, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID send + # Send HTTP request + # VARIANT arg0 --- varBody [IN] + def send(arg0=nil) + ret = @dispatch._invoke(5, [arg0], [VT_VARIANT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID abort + # Abort HTTP request + def abort() + ret = @dispatch._invoke(6, [], []) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# XML Data Source Object +class Microsoft_XMLDSO_1_0 # XMLDSOControl + include WIN32OLE::VARIANT + attr_reader :lastargs + attr_reader :dispatch + attr_reader :clsid + attr_reader :progid + + def initialize(obj = nil) + @clsid = "{550DDA30-0541-11D2-9CA9-0060B0EC3D39}" + @progid = "Microsoft.XMLDSO.1.0" + if obj.nil? + @dispatch = WIN32OLE.new(@progid) + else + @dispatch = obj + end + end + + def method_missing(cmd, *arg) + @dispatch.method_missing(cmd, *arg) + end + + # IXMLDOMDocument XMLDocument + def XMLDocument() + ret = @dispatch._getproperty(65537, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 JavaDSOCompatible + def JavaDSOCompatible() + ret = @dispatch._getproperty(65538, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # I4 readyState + def readyState() + ret = @dispatch._getproperty(-525, [], []) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID XMLDocument + def XMLDocument=(arg0) + ret = @dispatch._setproperty(65537, [arg0], [VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end + + # VOID JavaDSOCompatible + def JavaDSOCompatible=(arg0) + ret = @dispatch._setproperty(65538, [arg0], [VT_I4]) + @lastargs = WIN32OLE::ARGV + ret + end +end + +# Constants that define types for IXMLElement. +module OLEtagXMLEMEM_TYPE + include WIN32OLE::VARIANT + attr_reader :lastargs + XMLELEMTYPE_ELEMENT = 0 + XMLELEMTYPE_TEXT = 1 + XMLELEMTYPE_COMMENT = 2 + XMLELEMTYPE_DOCUMENT = 3 + XMLELEMTYPE_DTD = 4 + XMLELEMTYPE_PI = 5 + XMLELEMTYPE_OTHER = 6 +end + +# XMLDocument extends IXML Document. It is obsolete. You should use DOMDocument. This object should not be confused with the XMLDocument property on the XML data island. +class Msxml # XMLDocument + include WIN32OLE::VARIANT + attr_reader :lastargs + attr_reader :dispatch + attr_reader :clsid + attr_reader :progid + + def initialize(obj = nil) + @clsid = "{CFC399AF-D876-11D0-9C10-00C04FC99C8E}" + @progid = "Msxml" + if obj.nil? + @dispatch = WIN32OLE.new(@progid) + else + @dispatch = obj + end + end + + def method_missing(cmd, *arg) + @dispatch.method_missing(cmd, *arg) + end + + # HRESULT url + # set URL to load an XML document from the URL. + # BSTR arg0 --- p [IN] + def url=(arg0) + ret = @dispatch._setproperty(65641, [arg0], [VT_BSTR, VT_HRESULT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT charset + # get encoding. + # BSTR arg0 --- p [IN] + def charset=(arg0) + ret = @dispatch._setproperty(65645, [arg0], [VT_BSTR, VT_HRESULT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT async + # get asynchronous loading flag. + # BOOL arg0 --- pf [IN] + def async=(arg0) + ret = @dispatch._setproperty(65649, [arg0], [VT_BOOL, VT_HRESULT]) + @lastargs = WIN32OLE::ARGV + ret + end + + # HRESULT root + # get root IXMLElement of the XML document. + # IXMLElement2,IXMLElement2 arg0 --- p [OUT] + def root + OLEProperty.new(@dispatch, 65637, [VT_BYREF|VT_BYREF|VT_DISPATCH], [VT_BYREF|VT_BYREF|VT_DISPATCH, VT_HRESULT]) + end + + # HRESULT url + # set URL to load an XML document from the URL. + # BSTR arg0 --- p [OUT] + def url + OLEProperty.new(@dispatch, 65641, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT]) + end + + # HRESULT readyState + # get ready state. + # I4 arg0 --- pl [OUT] + def readyState + OLEProperty.new(@dispatch, 65643, [VT_BYREF|VT_I4], [VT_BYREF|VT_I4, VT_HRESULT]) + end + + # HRESULT charset + # get encoding. + # BSTR arg0 --- p [OUT] + def charset + OLEProperty.new(@dispatch, 65645, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT]) + end + + # HRESULT version + # get XML version number. + # BSTR arg0 --- p [OUT] + def version + OLEProperty.new(@dispatch, 65646, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT]) + end + + # HRESULT doctype + # get document type. + # BSTR arg0 --- p [OUT] + def doctype + OLEProperty.new(@dispatch, 65647, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT]) + end + + # HRESULT async + # get asynchronous loading flag. + # BOOL arg0 --- pf [OUT] + def async + OLEProperty.new(@dispatch, 65649, [VT_BYREF|VT_BOOL], [VT_BYREF|VT_BOOL, VT_HRESULT]) + end + + # HRESULT createElement + # create different types of IXMLElements. + # VARIANT arg0 --- vType [IN] + # VARIANT arg1 --- var1 [IN] + # IXMLElement2,IXMLElement2 arg2 --- ppElem [OUT] + def createElement(arg0, arg1=nil, arg2=nil) + ret = @dispatch._invoke(65644, [arg0, arg1, arg2], [VT_VARIANT, VT_VARIANT, VT_BYREF|VT_BYREF|VT_DISPATCH]) + @lastargs = WIN32OLE::ARGV + ret + end +end diff --git a/jni/ruby/ext/win32ole/win32ole.c b/jni/ruby/ext/win32ole/win32ole.c new file mode 100644 index 0000000..4d664e8 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole.c @@ -0,0 +1,4073 @@ +/* + * (c) 1995 Microsoft Corporation. All rights reserved. + * Developed by ActiveWare Internet Corp., http://www.ActiveWare.com + * + * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy + * and Jan Dubois + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file + * of the Perl distribution. + * + */ + +/* + modified for win32ole (ruby) by Masaki.Suketa + */ + +#include "win32ole.h" + +/* + * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a + * in Cygwin(mingw32). + */ +#if defined(__CYGWIN__) || defined(__MINGW32__) +#undef IID_IMultiLanguage2 +const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}}; +#endif + +#define WIN32OLE_VERSION "1.8.3" + +typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) + (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); + +typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile, + UINT uCommand, DWORD dwData); +typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD); +VALUE cWIN32OLE; + +#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__)) +static RB_THREAD_SPECIFIC BOOL g_ole_initialized; +# define g_ole_initialized_init() ((void)0) +# define g_ole_initialized_set(val) (g_ole_initialized = (val)) +#else +static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES; +# define g_ole_initialized (BOOL)TlsGetValue(g_ole_initialized_key) +# define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc()) +# define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val)) +#endif + +static BOOL g_uninitialize_hooked = FALSE; +static BOOL g_cp_installed = FALSE; +static BOOL g_lcid_installed = FALSE; +static HINSTANCE ghhctrl = NULL; +static HINSTANCE gole32 = NULL; +static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL; +static VALUE com_hash; +static IDispatchVtbl com_vtbl; +static UINT cWIN32OLE_cp = CP_ACP; +static rb_encoding *cWIN32OLE_enc; +static UINT g_cp_to_check = CP_ACP; +static char g_lcid_to_check[8 + 1]; +static VARTYPE g_nil_to = VT_ERROR; +static st_table *enc2cp_table; +static IMessageFilterVtbl message_filter; +static IMessageFilter imessage_filter = { &message_filter }; +static IMessageFilter* previous_filter; + +#if defined(HAVE_TYPE_IMULTILANGUAGE2) +static IMultiLanguage2 *pIMultiLanguage = NULL; +#elif defined(HAVE_TYPE_IMULTILANGUAGE) +static IMultiLanguage *pIMultiLanguage = NULL; +#else +#define pIMultiLanguage NULL /* dummy */ +#endif + +struct oleparam { + DISPPARAMS dp; + OLECHAR** pNamedArgs; +}; + +static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject); +static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This); +static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This); +static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo); +static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo); +static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId); +static HRESULT ( STDMETHODCALLTYPE Invoke )( IDispatch __RPC_FAR * This, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr); +static IDispatch* val2dispatch(VALUE val); +static double rbtime2vtdate(VALUE tmobj); +static VALUE vtdate2rbtime(double date); +static rb_encoding *ole_cp2encoding(UINT cp); +static UINT ole_encoding2cp(rb_encoding *enc); +NORETURN(static void failed_load_conv51932(void)); +#ifndef pIMultiLanguage +static void load_conv_function51932(void); +#endif +static UINT ole_init_cp(void); +static void ole_freeexceptinfo(EXCEPINFO *pExInfo); +static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo); +static void ole_free(void *ptr); +static size_t ole_size(const void *ptr); +static LPWSTR ole_mb2wc(char *pm, int len); +static VALUE ole_ary_m_entry(VALUE val, LONG *pid); +static VALUE is_all_index_under(LONG *pid, long *pub, long dim); +static void * get_ptr_of_variant(VARIANT *pvar); +static void ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt); +static long dimension(VALUE val); +static long ary_len_of_dim(VALUE ary, long dim); +static VALUE ole_set_member(VALUE self, IDispatch *dispatch); +static VALUE fole_s_allocate(VALUE klass); +static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv); +static VALUE ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim); +static void ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val); +static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self); +static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid); +static VALUE ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others); +static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self); +static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self); +static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self); +static ULONG reference_count(struct oledata * pole); +static VALUE fole_s_reference_count(VALUE self, VALUE obj); +static VALUE fole_s_free(VALUE self, VALUE obj); +static HWND ole_show_help(VALUE helpfile, VALUE helpcontext); +static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self); +static VALUE fole_s_get_code_page(VALUE self); +static BOOL CALLBACK installed_code_page_proc(LPTSTR str); +static BOOL code_page_installed(UINT cp); +static VALUE fole_s_set_code_page(VALUE self, VALUE vcp); +static VALUE fole_s_get_locale(VALUE self); +static BOOL CALLBACK installed_lcid_proc(LPTSTR str); +static BOOL lcid_installed(LCID lcid); +static VALUE fole_s_set_locale(VALUE self, VALUE vlcid); +static VALUE fole_s_create_guid(VALUE self); +static VALUE fole_s_ole_initialize(VALUE self); +static VALUE fole_s_ole_uninitialize(VALUE self); +static VALUE fole_initialize(int argc, VALUE *argv, VALUE self); +static int hash2named_arg(VALUE key, VALUE val, VALUE pop); +static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end); +static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket); +static VALUE fole_invoke(int argc, VALUE *argv, VALUE self); +static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind); +static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types); +static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); +static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types); +static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self); +static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self); +static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self); +static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value); +static VALUE fole_free(VALUE self); +static VALUE ole_each_sub(VALUE pEnumV); +static VALUE ole_ienum_free(VALUE pEnumV); +static VALUE fole_each(VALUE self); +static VALUE fole_missing(int argc, VALUE *argv, VALUE self); +static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti); +static VALUE ole_methods(VALUE self, int mask); +static VALUE fole_methods(VALUE self); +static VALUE fole_get_methods(VALUE self); +static VALUE fole_put_methods(VALUE self); +static VALUE fole_func_methods(VALUE self); +static VALUE fole_type(VALUE self); +static VALUE fole_typelib(VALUE self); +static VALUE fole_query_interface(VALUE self, VALUE str_iid); +static VALUE fole_respond_to(VALUE self, VALUE method); +static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); +static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); +static VALUE fole_method_help(VALUE self, VALUE cmdname); +static VALUE fole_activex_initialize(VALUE self); + +static void init_enc2cp(void); +static void free_enc2cp(void); + +static void com_hash_free(void *ptr); +static void com_hash_mark(void *ptr); +static size_t com_hash_size(const void *ptr); + +static const rb_data_type_t ole_datatype = { + "win32ole", + {NULL, ole_free, ole_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static const rb_data_type_t com_hash_datatype = { + "com_hash", + {com_hash_mark, com_hash_free, com_hash_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)( + IMessageFilter __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) +{ + if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 + || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0) + { + *ppvObject = &message_filter; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG (STDMETHODCALLTYPE mf_AddRef)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static ULONG (STDMETHODCALLTYPE mf_Release)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)( + IMessageFilter __RPC_FAR * pThis, + DWORD dwCallType, //Type of incoming call + HTASK threadIDCaller, //Task handle calling this task + DWORD dwTickCount, //Elapsed tick count + LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure + ) +{ +#ifdef DEBUG_MESSAGEFILTER + printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount); + fflush(stdout); +#endif + switch (dwCallType) + { + case CALLTYPE_ASYNC: + case CALLTYPE_TOPLEVEL_CALLPENDING: + case CALLTYPE_ASYNC_CALLPENDING: + if (rb_during_gc()) { + return SERVERCALL_RETRYLATER; + } + break; + default: + break; + } + if (previous_filter) { + return previous_filter->lpVtbl->HandleInComingCall(previous_filter, + dwCallType, + threadIDCaller, + dwTickCount, + lpInterfaceInfo); + } + return SERVERCALL_ISHANDLED; +} + +static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Server task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwRejectType //Returned rejection message + ) +{ + if (previous_filter) { + return previous_filter->lpVtbl->RetryRejectedCall(previous_filter, + threadIDCallee, + dwTickCount, + dwRejectType); + } + return 1000; +} + +static DWORD (STDMETHODCALLTYPE mf_MessagePending)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Called applications task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwPendingType //Call type + ) +{ + if (rb_during_gc()) { + return PENDINGMSG_WAITNOPROCESS; + } + if (previous_filter) { + return previous_filter->lpVtbl->MessagePending(previous_filter, + threadIDCallee, + dwTickCount, + dwPendingType); + } + return PENDINGMSG_WAITNOPROCESS; +} + +typedef struct _Win32OLEIDispatch +{ + IDispatch dispatch; + ULONG refcount; + VALUE obj; +} Win32OLEIDispatch; + +static HRESULT ( STDMETHODCALLTYPE QueryInterface )( + IDispatch __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) +{ + if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 + || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0) + { + Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + p->refcount++; + *ppvObject = This; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG ( STDMETHODCALLTYPE AddRef )( + IDispatch __RPC_FAR * This) +{ + Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + return ++(p->refcount); +} + +static ULONG ( STDMETHODCALLTYPE Release )( + IDispatch __RPC_FAR * This) +{ + Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + ULONG u = --(p->refcount); + if (u == 0) { + st_data_t key = p->obj; + st_delete(DATA_PTR(com_hash), &key, 0); + free(p); + } + return u; +} + +static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )( + IDispatch __RPC_FAR * This, + /* [out] */ UINT __RPC_FAR *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )( + IDispatch __RPC_FAR * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo) +{ + return E_NOTIMPL; +} + + +static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )( + IDispatch __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) +{ + /* + Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + */ + char* psz = ole_wc2mb(*rgszNames); // support only one method + ID nameid = rb_intern(psz); + free(psz); + if ((ID)(DISPID)nameid != nameid) return E_NOINTERFACE; + *rgDispId = (DISPID)nameid; + return S_OK; +} + +static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )( + IDispatch __RPC_FAR * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams, + /* [out] */ VARIANT __RPC_FAR *pVarResult, + /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo, + /* [out] */ UINT __RPC_FAR *puArgErr) +{ + VALUE v; + int i; + int args = pDispParams->cArgs; + Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + VALUE* parg = ALLOCA_N(VALUE, args); + ID mid = (ID)dispIdMember; + for (i = 0; i < args; i++) { + *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]); + } + if (dispIdMember == DISPID_VALUE) { + if (wFlags == DISPATCH_METHOD) { + mid = rb_intern("call"); + } else if (wFlags & DISPATCH_PROPERTYGET) { + mid = rb_intern("value"); + } + } + v = rb_funcall2(p->obj, mid, args, parg); + ole_val2variant(v, pVarResult); + return S_OK; +} + +BOOL +ole_initialized(void) +{ + return g_ole_initialized; +} + +static IDispatch* +val2dispatch(VALUE val) +{ + struct st_table *tbl = DATA_PTR(com_hash); + Win32OLEIDispatch* pdisp; + st_data_t data; + if (st_lookup(tbl, val, &data)) { + pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG); + pdisp->refcount++; + } + else { + pdisp = ALLOC(Win32OLEIDispatch); + pdisp->dispatch.lpVtbl = &com_vtbl; + pdisp->refcount = 1; + pdisp->obj = val; + st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG); + } + return &pdisp->dispatch; +} + +static double +rbtime2vtdate(VALUE tmobj) +{ + SYSTEMTIME st; + double t; + double nsec; + + st.wYear = FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0)); + st.wMonth = FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0)); + st.wDay = FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0)); + st.wHour = FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0)); + st.wMinute = FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0)); + st.wSecond = FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0)); + st.wMilliseconds = 0; + SystemTimeToVariantTime(&st, &t); + + /* + * Unfortunately SystemTimeToVariantTime function always ignores the + * wMilliseconds of SYSTEMTIME struct. + * So, we need to calculate milliseconds by ourselves. + */ + nsec = FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0)); + nsec /= 1000000.0; + nsec /= (24.0 * 3600.0); + nsec /= 1000; + return t + nsec; +} + +static VALUE +vtdate2rbtime(double date) +{ + SYSTEMTIME st; + VALUE v; + double msec; + double sec; + VariantTimeToSystemTime(date, &st); + v = rb_funcall(rb_cTime, rb_intern("new"), 6, + INT2FIX(st.wYear), + INT2FIX(st.wMonth), + INT2FIX(st.wDay), + INT2FIX(st.wHour), + INT2FIX(st.wMinute), + INT2FIX(st.wSecond)); + st.wYear = FIX2INT(rb_funcall(v, rb_intern("year"), 0)); + st.wMonth = FIX2INT(rb_funcall(v, rb_intern("month"), 0)); + st.wDay = FIX2INT(rb_funcall(v, rb_intern("mday"), 0)); + st.wHour = FIX2INT(rb_funcall(v, rb_intern("hour"), 0)); + st.wMinute = FIX2INT(rb_funcall(v, rb_intern("min"), 0)); + st.wSecond = FIX2INT(rb_funcall(v, rb_intern("sec"), 0)); + st.wMilliseconds = 0; + SystemTimeToVariantTime(&st, &sec); + /* + * Unfortunately VariantTimeToSystemTime always ignores the + * wMilliseconds of SYSTEMTIME struct(The wMilliseconds is 0). + * So, we need to calculate milliseconds by ourselves. + */ + msec = date - sec; + msec *= 24 * 60; + msec -= floor(msec); + msec *= 60; + if (msec >= 59) { + msec -= 60; + } + if (msec != 0) { + return rb_funcall(v, rb_intern("+"), 1, rb_float_new(msec)); + } + return v; +} + +#define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp + +static UINT ole_encoding2cp(rb_encoding *enc) +{ + /* + * Is there any better solution to convert + * Ruby encoding to Windows codepage??? + */ + ENC_MACHING_CP(enc, "Big5", 950); + ENC_MACHING_CP(enc, "CP51932", 51932); + ENC_MACHING_CP(enc, "CP850", 850); + ENC_MACHING_CP(enc, "CP852", 852); + ENC_MACHING_CP(enc, "CP855", 855); + ENC_MACHING_CP(enc, "CP949", 949); + ENC_MACHING_CP(enc, "EUC-JP", 20932); + ENC_MACHING_CP(enc, "EUC-KR", 51949); + ENC_MACHING_CP(enc, "EUC-TW", 51950); + ENC_MACHING_CP(enc, "GB18030", 54936); + ENC_MACHING_CP(enc, "GB2312", 20936); + ENC_MACHING_CP(enc, "GBK", 936); + ENC_MACHING_CP(enc, "IBM437", 437); + ENC_MACHING_CP(enc, "IBM737", 737); + ENC_MACHING_CP(enc, "IBM775", 775); + ENC_MACHING_CP(enc, "IBM852", 852); + ENC_MACHING_CP(enc, "IBM855", 855); + ENC_MACHING_CP(enc, "IBM857", 857); + ENC_MACHING_CP(enc, "IBM860", 860); + ENC_MACHING_CP(enc, "IBM861", 861); + ENC_MACHING_CP(enc, "IBM862", 862); + ENC_MACHING_CP(enc, "IBM863", 863); + ENC_MACHING_CP(enc, "IBM864", 864); + ENC_MACHING_CP(enc, "IBM865", 865); + ENC_MACHING_CP(enc, "IBM866", 866); + ENC_MACHING_CP(enc, "IBM869", 869); + ENC_MACHING_CP(enc, "ISO-2022-JP", 50220); + ENC_MACHING_CP(enc, "ISO-8859-1", 28591); + ENC_MACHING_CP(enc, "ISO-8859-15", 28605); + ENC_MACHING_CP(enc, "ISO-8859-2", 28592); + ENC_MACHING_CP(enc, "ISO-8859-3", 28593); + ENC_MACHING_CP(enc, "ISO-8859-4", 28594); + ENC_MACHING_CP(enc, "ISO-8859-5", 28595); + ENC_MACHING_CP(enc, "ISO-8859-6", 28596); + ENC_MACHING_CP(enc, "ISO-8859-7", 28597); + ENC_MACHING_CP(enc, "ISO-8859-8", 28598); + ENC_MACHING_CP(enc, "ISO-8859-9", 28599); + ENC_MACHING_CP(enc, "KOI8-R", 20866); + ENC_MACHING_CP(enc, "KOI8-U", 21866); + ENC_MACHING_CP(enc, "Shift_JIS", 932); + ENC_MACHING_CP(enc, "UTF-16BE", 1201); + ENC_MACHING_CP(enc, "UTF-16LE", 1200); + ENC_MACHING_CP(enc, "UTF-7", 65000); + ENC_MACHING_CP(enc, "UTF-8", 65001); + ENC_MACHING_CP(enc, "Windows-1250", 1250); + ENC_MACHING_CP(enc, "Windows-1251", 1251); + ENC_MACHING_CP(enc, "Windows-1252", 1252); + ENC_MACHING_CP(enc, "Windows-1253", 1253); + ENC_MACHING_CP(enc, "Windows-1254", 1254); + ENC_MACHING_CP(enc, "Windows-1255", 1255); + ENC_MACHING_CP(enc, "Windows-1256", 1256); + ENC_MACHING_CP(enc, "Windows-1257", 1257); + ENC_MACHING_CP(enc, "Windows-1258", 1258); + ENC_MACHING_CP(enc, "Windows-31J", 932); + ENC_MACHING_CP(enc, "Windows-874", 874); + ENC_MACHING_CP(enc, "eucJP-ms", 20932); + return CP_ACP; +} + +static void +failed_load_conv51932(void) +{ + rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932"); +} + +#ifndef pIMultiLanguage +static void +load_conv_function51932(void) +{ + HRESULT hr = E_NOINTERFACE; + void *p; + if (!pIMultiLanguage) { +#if defined(HAVE_TYPE_IMULTILANGUAGE2) + hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, + &IID_IMultiLanguage2, &p); +#elif defined(HAVE_TYPE_IMULTILANGUAGE) + hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, + &IID_IMultiLanguage, &p); +#endif + if (FAILED(hr)) { + failed_load_conv51932(); + } + pIMultiLanguage = p; + } +} +#else +#define load_conv_function51932() failed_load_conv51932() +#endif + +#define conv_51932(cp) ((cp) == 51932 && (load_conv_function51932(), 1)) + +static void +set_ole_codepage(UINT cp) +{ + if (code_page_installed(cp)) { + cWIN32OLE_cp = cp; + } else { + switch(cp) { + case CP_ACP: + case CP_OEMCP: + case CP_MACCP: + case CP_THREAD_ACP: + case CP_SYMBOL: + case CP_UTF7: + case CP_UTF8: + cWIN32OLE_cp = cp; + break; + case 51932: + cWIN32OLE_cp = cp; + load_conv_function51932(); + break; + default: + rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage."); + break; + } + } + cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp); +} + + +static UINT +ole_init_cp(void) +{ + UINT cp; + rb_encoding *encdef; + encdef = rb_default_internal_encoding(); + if (!encdef) { + encdef = rb_default_external_encoding(); + } + cp = ole_encoding2cp(encdef); + set_ole_codepage(cp); + return cp; +} + +struct myCPINFOEX { + UINT MaxCharSize; + BYTE DefaultChar[2]; + BYTE LeadByte[12]; + WCHAR UnicodeDefaultChar; + UINT CodePage; + char CodePageName[MAX_PATH]; +}; + +static rb_encoding * +ole_cp2encoding(UINT cp) +{ + static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL; + struct myCPINFOEX* buf; + VALUE enc_name; + char *enc_cstr; + int idx; + + if (!code_page_installed(cp)) { + switch(cp) { + case CP_ACP: + cp = GetACP(); + break; + case CP_OEMCP: + cp = GetOEMCP(); + break; + case CP_MACCP: + case CP_THREAD_ACP: + if (!pGetCPInfoEx) { + pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *)) + GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx"); + if (!pGetCPInfoEx) { + pGetCPInfoEx = (void*)-1; + } + } + buf = ALLOCA_N(struct myCPINFOEX, 1); + ZeroMemory(buf, sizeof(struct myCPINFOEX)); + if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) { + rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding."); + break; /* never reach here */ + } + cp = buf->CodePage; + break; + case CP_SYMBOL: + case CP_UTF7: + case CP_UTF8: + break; + case 51932: + load_conv_function51932(); + break; + default: + rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage."); + break; + } + } + + enc_name = rb_sprintf("CP%d", cp); + idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name)); + if (idx < 0) + idx = rb_define_dummy_encoding(enc_cstr); + return rb_enc_from_index(idx); +} + +static char * +ole_wc2mb_alloc(LPWSTR pw, char *(alloc)(UINT size, void *arg), void *arg) +{ + LPSTR pm; + UINT size = 0; + if (conv_51932(cWIN32OLE_cp)) { +#ifndef pIMultiLanguage + DWORD dw = 0; + HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, + &dw, cWIN32OLE_cp, pw, NULL, NULL, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); + } + pm = alloc(size, arg); + hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage, + &dw, cWIN32OLE_cp, pw, NULL, pm, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); + } + pm[size] = '\0'; +#endif + return pm; + } + size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL); + if (size) { + pm = alloc(size, arg); + WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, pm, size, NULL, NULL); + pm[size] = '\0'; + } + else { + pm = alloc(0, arg); + *pm = '\0'; + } + return pm; +} + +static char * +ole_alloc_str(UINT size, void *arg) +{ + return ALLOC_N(char, size + 1); +} + +char * +ole_wc2mb(LPWSTR pw) +{ + return ole_wc2mb_alloc(pw, ole_alloc_str, NULL); +} + +static void +ole_freeexceptinfo(EXCEPINFO *pExInfo) +{ + SysFreeString(pExInfo->bstrDescription); + SysFreeString(pExInfo->bstrSource); + SysFreeString(pExInfo->bstrHelpFile); +} + +static VALUE +ole_excepinfo2msg(EXCEPINFO *pExInfo) +{ + char error_code[40]; + char *pSource = NULL; + char *pDescription = NULL; + VALUE error_msg; + if(pExInfo->pfnDeferredFillIn != NULL) { + (*pExInfo->pfnDeferredFillIn)(pExInfo); + } + if (pExInfo->bstrSource != NULL) { + pSource = ole_wc2mb(pExInfo->bstrSource); + } + if (pExInfo->bstrDescription != NULL) { + pDescription = ole_wc2mb(pExInfo->bstrDescription); + } + if(pExInfo->wCode == 0) { + sprintf(error_code, "\n OLE error code:%lX in ", (unsigned long)pExInfo->scode); + } + else{ + sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode); + } + error_msg = rb_str_new2(error_code); + if(pSource != NULL) { + rb_str_cat2(error_msg, pSource); + } + else { + rb_str_cat(error_msg, "", 9); + } + rb_str_cat2(error_msg, "\n "); + if(pDescription != NULL) { + rb_str_cat2(error_msg, pDescription); + } + else { + rb_str_cat2(error_msg, ""); + } + if(pSource) free(pSource); + if(pDescription) free(pDescription); + ole_freeexceptinfo(pExInfo); + return error_msg; +} + +void +ole_uninitialize(void) +{ + if (!g_ole_initialized) return; + OleUninitialize(); + g_ole_initialized_set(FALSE); +} + +static void +ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) +{ + ole_uninitialize(); +} + +void +ole_initialize(void) +{ + HRESULT hr; + + if(!g_uninitialize_hooked) { + rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil); + g_uninitialize_hooked = TRUE; + } + + if(g_ole_initialized == FALSE) { + hr = OleInitialize(NULL); + if(FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize"); + } + g_ole_initialized_set(TRUE); + + hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter); + if(FAILED(hr)) { + previous_filter = NULL; + ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter"); + } + } +} + +static void +ole_free(void *ptr) +{ + struct oledata *pole = ptr; + OLE_FREE(pole->pDispatch); + free(pole); +} + +static size_t ole_size(const void *ptr) +{ + return ptr ? sizeof(struct oledata) : 0; +} + +struct oledata * +oledata_get_struct(VALUE ole) +{ + struct oledata *pole; + TypedData_Get_Struct(ole, struct oledata, &ole_datatype, pole); + return pole; +} + +LPWSTR +ole_vstr2wc(VALUE vstr) +{ + rb_encoding *enc; + int cp; + UINT size = 0; + LPWSTR pw; + st_data_t data; + enc = rb_enc_get(vstr); + + if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) { + cp = (int)data; + } else { + cp = ole_encoding2cp(enc); + if (code_page_installed(cp) || + cp == CP_ACP || + cp == CP_OEMCP || + cp == CP_MACCP || + cp == CP_THREAD_ACP || + cp == CP_SYMBOL || + cp == CP_UTF7 || + cp == CP_UTF8 || + cp == 51932) { + st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp); + } else { + rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc)); + } + } + if (conv_51932(cp)) { +#ifndef pIMultiLanguage + DWORD dw = 0; + UINT len = RSTRING_LENINT(vstr); + HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, + &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); + } + pw = SysAllocStringLen(NULL, size); + len = RSTRING_LEN(vstr); + hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, + &dw, cp, RSTRING_PTR(vstr), &len, pw, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp); + } +#endif + return pw; + } + size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0); + pw = SysAllocStringLen(NULL, size); + MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size); + return pw; +} + +static LPWSTR +ole_mb2wc(char *pm, int len) +{ + UINT size = 0; + LPWSTR pw; + + if (conv_51932(cWIN32OLE_cp)) { +#ifndef pIMultiLanguage + DWORD dw = 0; + UINT n = len; + HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, + &dw, cWIN32OLE_cp, pm, &n, NULL, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); + } + pw = SysAllocStringLen(NULL, size); + hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage, + &dw, cWIN32OLE_cp, pm, &n, pw, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp); + } +#endif + return pw; + } + size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0); + pw = SysAllocStringLen(NULL, size - 1); + MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size); + return pw; +} + +static char * +ole_alloc_vstr(UINT size, void *arg) +{ + VALUE str = rb_enc_str_new(NULL, size, cWIN32OLE_enc); + *(VALUE *)arg = str; + return RSTRING_PTR(str); +} + +VALUE +ole_wc2vstr(LPWSTR pw, BOOL isfree) +{ + VALUE vstr; + ole_wc2mb_alloc(pw, ole_alloc_vstr, &vstr); + rb_str_set_len(vstr, (long)strlen(RSTRING_PTR(vstr))); + if(isfree) + SysFreeString(pw); + return vstr; +} + +static VALUE +ole_ary_m_entry(VALUE val, LONG *pid) +{ + VALUE obj = Qnil; + int i = 0; + obj = val; + while(RB_TYPE_P(obj, T_ARRAY)) { + obj = rb_ary_entry(obj, pid[i]); + i++; + } + return obj; +} + +static VALUE +is_all_index_under(LONG *pid, long *pub, long dim) +{ + long i = 0; + for (i = 0; i < dim; i++) { + if (pid[i] > pub[i]) { + return Qfalse; + } + } + return Qtrue; +} + +void +ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt) +{ + if (val == Qnil) { + if (vt == VT_VARIANT) { + ole_val2variant2(val, var); + } else { + V_VT(var) = (vt & ~VT_BYREF); + if (V_VT(var) == VT_DISPATCH) { + V_DISPATCH(var) = NULL; + } else if (V_VT(var) == VT_UNKNOWN) { + V_UNKNOWN(var) = NULL; + } + } + return; + } +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + switch(vt & ~VT_BYREF) { + case VT_I8: + V_VT(var) = VT_I8; + V_I8(var) = NUM2I8 (val); + break; + case VT_UI8: + V_VT(var) = VT_UI8; + V_UI8(var) = NUM2UI8(val); + break; + default: + ole_val2variant2(val, var); + break; + } +#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ + ole_val2variant2(val, var); +#endif +} + +VOID * +val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt) +{ + VOID *p = NULL; + HRESULT hr = S_OK; + ole_val2variant_ex(val, var, vt); + if ((vt & ~VT_BYREF) == VT_VARIANT) { + p = var; + } else { + if ( (vt & ~VT_BYREF) != V_VT(var)) { + hr = VariantChangeTypeEx(var, var, + cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to change type"); + } + } + p = get_ptr_of_variant(var); + } + if (p == NULL) { + rb_raise(rb_eRuntimeError, "failed to get pointer of variant"); + } + return p; +} + +static void * +get_ptr_of_variant(VARIANT *pvar) +{ + switch(V_VT(pvar)) { + case VT_UI1: + return &V_UI1(pvar); + break; + case VT_I2: + return &V_I2(pvar); + break; + case VT_UI2: + return &V_UI2(pvar); + break; + case VT_I4: + return &V_I4(pvar); + break; + case VT_UI4: + return &V_UI4(pvar); + break; + case VT_R4: + return &V_R4(pvar); + break; + case VT_R8: + return &V_R8(pvar); + break; +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + case VT_I8: + return &V_I8(pvar); + break; + case VT_UI8: + return &V_UI8(pvar); + break; +#endif + case VT_INT: + return &V_INT(pvar); + break; + case VT_UINT: + return &V_UINT(pvar); + break; + case VT_CY: + return &V_CY(pvar); + break; + case VT_DATE: + return &V_DATE(pvar); + break; + case VT_BSTR: + return V_BSTR(pvar); + break; + case VT_DISPATCH: + return V_DISPATCH(pvar); + break; + case VT_ERROR: + return &V_ERROR(pvar); + break; + case VT_BOOL: + return &V_BOOL(pvar); + break; + case VT_UNKNOWN: + return V_UNKNOWN(pvar); + break; + case VT_ARRAY: + return &V_ARRAY(pvar); + break; + default: + return NULL; + break; + } +} + +static void +ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt) +{ + VALUE val1; + HRESULT hr = S_OK; + VARIANT var; + VOID *p = NULL; + long i = n; + while(i >= 0) { + val1 = ole_ary_m_entry(val, pid); + VariantInit(&var); + p = val2variant_ptr(val1, &var, vt); + if (is_all_index_under(pid, pub, dim) == Qtrue) { + if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || + (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { + rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface"); + } + hr = SafeArrayPutElement(psa, pid, p); + } + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement"); + } + pid[i] += 1; + if (pid[i] > pub[i]) { + pid[i] = 0; + i -= 1; + } else { + i = dim - 1; + } + } +} + +static long +dimension(VALUE val) { + long dim = 0; + long dim1 = 0; + long len = 0; + long i = 0; + if (RB_TYPE_P(val, T_ARRAY)) { + len = RARRAY_LEN(val); + for (i = 0; i < len; i++) { + dim1 = dimension(rb_ary_entry(val, i)); + if (dim < dim1) { + dim = dim1; + } + } + dim += 1; + } + return dim; +} + +static long +ary_len_of_dim(VALUE ary, long dim) { + long ary_len = 0; + long ary_len1 = 0; + long len = 0; + long i = 0; + VALUE val; + if (dim == 0) { + if (RB_TYPE_P(ary, T_ARRAY)) { + ary_len = RARRAY_LEN(ary); + } + } else { + if (RB_TYPE_P(ary, T_ARRAY)) { + len = RARRAY_LEN(ary); + for (i = 0; i < len; i++) { + val = rb_ary_entry(ary, i); + ary_len1 = ary_len_of_dim(val, dim-1); + if (ary_len < ary_len1) { + ary_len = ary_len1; + } + } + } + } + return ary_len; +} + +HRESULT +ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt) +{ + long dim = 0; + int i = 0; + HRESULT hr = S_OK; + + SAFEARRAYBOUND *psab = NULL; + SAFEARRAY *psa = NULL; + long *pub; + LONG *pid; + + Check_Type(val, T_ARRAY); + + dim = dimension(val); + + psab = ALLOC_N(SAFEARRAYBOUND, dim); + pub = ALLOC_N(long, dim); + pid = ALLOC_N(LONG, dim); + + if(!psab || !pub || !pid) { + if(pub) free(pub); + if(psab) free(psab); + if(pid) free(pid); + rb_raise(rb_eRuntimeError, "memory allocation error"); + } + + for (i = 0; i < dim; i++) { + psab[i].cElements = ary_len_of_dim(val, i); + psab[i].lLbound = 0; + pub[i] = psab[i].cElements - 1; + pid[i] = 0; + } + /* Create and fill VARIANT array */ + if ((vt & ~VT_BYREF) == VT_ARRAY) { + vt = (vt | VT_VARIANT); + } + psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); + if (psa == NULL) + hr = E_OUTOFMEMORY; + else + hr = SafeArrayLock(psa); + if (SUCCEEDED(hr)) { + ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK)); + hr = SafeArrayUnlock(psa); + } + + if(pub) free(pub); + if(psab) free(psab); + if(pid) free(pid); + + if (SUCCEEDED(hr)) { + V_VT(var) = vt; + V_ARRAY(var) = psa; + } + else { + if (psa != NULL) + SafeArrayDestroy(psa); + } + return hr; +} + +void +ole_val2variant(VALUE val, VARIANT *var) +{ + struct oledata *pole = NULL; + if(rb_obj_is_kind_of(val, cWIN32OLE)) { + pole = oledata_get_struct(val); + OLE_ADDREF(pole->pDispatch); + V_VT(var) = VT_DISPATCH; + V_DISPATCH(var) = pole->pDispatch; + return; + } + if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) { + ole_variant2variant(val, var); + return; + } + if (rb_obj_is_kind_of(val, cWIN32OLE_RECORD)) { + ole_rec2variant(val, var); + return; + } + if (rb_obj_is_kind_of(val, rb_cTime)) { + V_VT(var) = VT_DATE; + V_DATE(var) = rbtime2vtdate(val); + return; + } + switch (TYPE(val)) { + case T_ARRAY: + ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY); + break; + case T_STRING: + V_VT(var) = VT_BSTR; + V_BSTR(var) = ole_vstr2wc(val); + break; + case T_FIXNUM: + V_VT(var) = VT_I4; + V_I4(var) = NUM2INT(val); + break; + case T_BIGNUM: + V_VT(var) = VT_R8; + V_R8(var) = rb_big2dbl(val); + break; + case T_FLOAT: + V_VT(var) = VT_R8; + V_R8(var) = NUM2DBL(val); + break; + case T_TRUE: + V_VT(var) = VT_BOOL; + V_BOOL(var) = VARIANT_TRUE; + break; + case T_FALSE: + V_VT(var) = VT_BOOL; + V_BOOL(var) = VARIANT_FALSE; + break; + case T_NIL: + if (g_nil_to == VT_ERROR) { + V_VT(var) = VT_ERROR; + V_ERROR(var) = DISP_E_PARAMNOTFOUND; + }else { + V_VT(var) = VT_EMPTY; + } + break; + default: + V_VT(var) = VT_DISPATCH; + V_DISPATCH(var) = val2dispatch(val); + break; + } +} + +void +ole_val2variant2(VALUE val, VARIANT *var) +{ + g_nil_to = VT_EMPTY; + ole_val2variant(val, var); + g_nil_to = VT_ERROR; +} + +VALUE +make_inspect(const char *class_name, VALUE detail) +{ + VALUE str; + str = rb_str_new2("#<"); + rb_str_cat2(str, class_name); + rb_str_cat2(str, ":"); + rb_str_concat(str, detail); + rb_str_cat2(str, ">"); + return str; +} + +VALUE +default_inspect(VALUE self, const char *class_name) +{ + VALUE detail = rb_funcall(self, rb_intern("to_s"), 0); + return make_inspect(class_name, detail); +} + +static VALUE +ole_set_member(VALUE self, IDispatch *dispatch) +{ + struct oledata *pole = NULL; + pole = oledata_get_struct(self); + if (pole->pDispatch) { + OLE_RELEASE(pole->pDispatch); + pole->pDispatch = NULL; + } + pole->pDispatch = dispatch; + return self; +} + + +static VALUE +fole_s_allocate(VALUE klass) +{ + struct oledata *pole; + VALUE obj; + ole_initialize(); + obj = TypedData_Make_Struct(klass, struct oledata, &ole_datatype, pole); + pole->pDispatch = NULL; + return obj; +} + +static VALUE +create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv) +{ + VALUE obj = fole_s_allocate(klass); + ole_set_member(obj, pDispatch); + return obj; +} + +static VALUE +ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim) { + long i; + VALUE obj = Qnil; + VALUE pobj = Qnil; + long *ids = ALLOC_N(long, dim); + if (!ids) { + rb_raise(rb_eRuntimeError, "memory allocation error"); + } + for(i = 0; i < dim; i++) { + ids[i] = pid[i] - plb[i]; + } + obj = myary; + pobj = myary; + for(i = 0; i < dim-1; i++) { + obj = rb_ary_entry(pobj, ids[i]); + if (obj == Qnil) { + rb_ary_store(pobj, ids[i], rb_ary_new()); + } + obj = rb_ary_entry(pobj, ids[i]); + pobj = obj; + } + if (ids) free(ids); + return obj; +} + +static void +ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val) { + long id = pid[dim - 1] - plb[dim - 1]; + VALUE obj = ary_new_dim(myary, pid, plb, dim); + rb_ary_store(obj, id, val); +} + +VALUE +ole_variant2val(VARIANT *pvar) +{ + VALUE obj = Qnil; + VARTYPE vt = V_VT(pvar); + HRESULT hr; + while ( vt == (VT_BYREF | VT_VARIANT) ) { + pvar = V_VARIANTREF(pvar); + vt = V_VT(pvar); + } + + if(V_ISARRAY(pvar)) { + VARTYPE vt_base = vt & VT_TYPEMASK; + SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar); + UINT i = 0; + LONG *pid, *plb, *pub; + VARIANT variant; + VALUE val; + UINT dim = 0; + if (!psa) { + return obj; + } + dim = SafeArrayGetDim(psa); + pid = ALLOC_N(LONG, dim); + plb = ALLOC_N(LONG, dim); + pub = ALLOC_N(LONG, dim); + + if(!pid || !plb || !pub) { + if(pid) free(pid); + if(plb) free(plb); + if(pub) free(pub); + rb_raise(rb_eRuntimeError, "memory allocation error"); + } + + for(i = 0; i < dim; ++i) { + SafeArrayGetLBound(psa, i+1, &plb[i]); + SafeArrayGetLBound(psa, i+1, &pid[i]); + SafeArrayGetUBound(psa, i+1, &pub[i]); + } + hr = SafeArrayLock(psa); + if (SUCCEEDED(hr)) { + obj = rb_ary_new(); + i = 0; + VariantInit(&variant); + V_VT(&variant) = vt_base | VT_BYREF; + if (vt_base == VT_RECORD) { + hr = SafeArrayGetRecordInfo(psa, &V_RECORDINFO(&variant)); + if (SUCCEEDED(hr)) { + V_VT(&variant) = VT_RECORD; + } + } + while (i < dim) { + ary_new_dim(obj, pid, plb, dim); + if (vt_base == VT_RECORD) + hr = SafeArrayPtrOfIndex(psa, pid, &V_RECORD(&variant)); + else + hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); + if (SUCCEEDED(hr)) { + val = ole_variant2val(&variant); + ary_store_dim(obj, pid, plb, dim, val); + } + for (i = 0; i < dim; ++i) { + if (++pid[i] <= pub[i]) + break; + pid[i] = plb[i]; + } + } + SafeArrayUnlock(psa); + } + if(pid) free(pid); + if(plb) free(plb); + if(pub) free(pub); + return obj; + } + switch(V_VT(pvar) & ~VT_BYREF){ + case VT_EMPTY: + break; + case VT_NULL: + break; + case VT_I1: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_I1REF(pvar)); + else + obj = INT2NUM((long)V_I1(pvar)); + break; + + case VT_UI1: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_UI1REF(pvar)); + else + obj = INT2NUM((long)V_UI1(pvar)); + break; + + case VT_I2: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_I2REF(pvar)); + else + obj = INT2NUM((long)V_I2(pvar)); + break; + + case VT_UI2: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_UI2REF(pvar)); + else + obj = INT2NUM((long)V_UI2(pvar)); + break; + + case VT_I4: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_I4REF(pvar)); + else + obj = INT2NUM((long)V_I4(pvar)); + break; + + case VT_UI4: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_UI4REF(pvar)); + else + obj = INT2NUM((long)V_UI4(pvar)); + break; + + case VT_INT: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_INTREF(pvar)); + else + obj = INT2NUM((long)V_INT(pvar)); + break; + + case VT_UINT: + if(V_ISBYREF(pvar)) + obj = INT2NUM((long)*V_UINTREF(pvar)); + else + obj = INT2NUM((long)V_UINT(pvar)); + break; + +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + case VT_I8: + if(V_ISBYREF(pvar)) +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#ifdef V_I8REF + obj = I8_2_NUM(*V_I8REF(pvar)); +#endif +#else + obj = Qnil; +#endif + else + obj = I8_2_NUM(V_I8(pvar)); + break; + case VT_UI8: + if(V_ISBYREF(pvar)) +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#ifdef V_UI8REF + obj = UI8_2_NUM(*V_UI8REF(pvar)); +#endif +#else + obj = Qnil; +#endif + else + obj = UI8_2_NUM(V_UI8(pvar)); + break; +#endif /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */ + + case VT_R4: + if(V_ISBYREF(pvar)) + obj = rb_float_new(*V_R4REF(pvar)); + else + obj = rb_float_new(V_R4(pvar)); + break; + + case VT_R8: + if(V_ISBYREF(pvar)) + obj = rb_float_new(*V_R8REF(pvar)); + else + obj = rb_float_new(V_R8(pvar)); + break; + + case VT_BSTR: + { + if(V_ISBYREF(pvar)) + obj = ole_wc2vstr(*V_BSTRREF(pvar), FALSE); + else + obj = ole_wc2vstr(V_BSTR(pvar), FALSE); + break; + } + + case VT_ERROR: + if(V_ISBYREF(pvar)) + obj = INT2NUM(*V_ERRORREF(pvar)); + else + obj = INT2NUM(V_ERROR(pvar)); + break; + + case VT_BOOL: + if (V_ISBYREF(pvar)) + obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse); + else + obj = (V_BOOL(pvar) ? Qtrue : Qfalse); + break; + + case VT_DISPATCH: + { + IDispatch *pDispatch; + + if (V_ISBYREF(pvar)) + pDispatch = *V_DISPATCHREF(pvar); + else + pDispatch = V_DISPATCH(pvar); + + if (pDispatch != NULL ) { + OLE_ADDREF(pDispatch); + obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); + } + break; + } + + case VT_UNKNOWN: + { + /* get IDispatch interface from IUnknown interface */ + IUnknown *punk; + IDispatch *pDispatch; + void *p; + HRESULT hr; + + if (V_ISBYREF(pvar)) + punk = *V_UNKNOWNREF(pvar); + else + punk = V_UNKNOWN(pvar); + + if(punk != NULL) { + hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p); + if(SUCCEEDED(hr)) { + pDispatch = p; + obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); + } + } + break; + } + + case VT_DATE: + { + DATE date; + if(V_ISBYREF(pvar)) + date = *V_DATEREF(pvar); + else + date = V_DATE(pvar); + + obj = vtdate2rbtime(date); + break; + } + + case VT_RECORD: + { + IRecordInfo *pri = V_RECORDINFO(pvar); + void *prec = V_RECORD(pvar); + obj = create_win32ole_record(pri, prec); + break; + } + + case VT_CY: + default: + { + HRESULT hr; + VARIANT variant; + VariantInit(&variant); + hr = VariantChangeTypeEx(&variant, pvar, + cWIN32OLE_lcid, 0, VT_BSTR); + if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) { + obj = ole_wc2vstr(V_BSTR(&variant), FALSE); + } + VariantClear(&variant); + break; + } + } + return obj; +} + +LONG +reg_open_key(HKEY hkey, const char *name, HKEY *phkey) +{ + return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey); +} + +LONG +reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey) +{ + return reg_open_key(hkey, StringValuePtr(key), phkey); +} + +VALUE +reg_enum_key(HKEY hkey, DWORD i) +{ + char buf[BUFSIZ + 1]; + DWORD size_buf = sizeof(buf); + FILETIME ft; + LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf, + NULL, NULL, NULL, &ft); + if(err == ERROR_SUCCESS) { + buf[BUFSIZ] = '\0'; + return rb_str_new2(buf); + } + return Qnil; +} + +VALUE +reg_get_val(HKEY hkey, const char *subkey) +{ + char *pbuf; + DWORD dwtype = 0; + DWORD size = 0; + VALUE val = Qnil; + LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size); + + if (err == ERROR_SUCCESS) { + pbuf = ALLOC_N(char, size + 1); + err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size); + if (err == ERROR_SUCCESS) { + pbuf[size] = '\0'; + if (dwtype == REG_EXPAND_SZ) { + char* pbuf2 = (char *)pbuf; + DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0); + pbuf = ALLOC_N(char, len + 1); + ExpandEnvironmentStrings(pbuf2, pbuf, len + 1); + free(pbuf2); + } + val = rb_str_new2((char *)pbuf); + } + free(pbuf); + } + return val; +} + +VALUE +reg_get_val2(HKEY hkey, const char *subkey) +{ + HKEY hsubkey; + LONG err; + VALUE val = Qnil; + err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey); + if (err == ERROR_SUCCESS) { + val = reg_get_val(hsubkey, NULL); + RegCloseKey(hsubkey); + } + if (val == Qnil) { + val = reg_get_val(hkey, subkey); + } + return val; +} + +static void +ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self) +{ + unsigned int count; + unsigned int index; + int iVar; + ITypeInfo *pTypeInfo; + TYPEATTR *pTypeAttr; + VARDESC *pVarDesc; + HRESULT hr; + unsigned int len; + BSTR bstr; + char *pName = NULL; + VALUE val; + VALUE constant; + ID id; + constant = rb_hash_new(); + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (index = 0; index < count; index++) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo); + if (FAILED(hr)) + continue; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if(FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + continue; + } + for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) { + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc); + if(FAILED(hr)) + continue; + if(pVarDesc->varkind == VAR_CONST && + !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | + VARFLAG_FRESTRICTED | + VARFLAG_FNONBROWSABLE))) { + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, + 1, &len); + if(FAILED(hr) || len == 0 || !bstr) + continue; + pName = ole_wc2mb(bstr); + val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); + *pName = toupper((int)*pName); + id = rb_intern(pName); + if (rb_is_const_id(id)) { + rb_define_const(klass, pName, val); + } + else { + rb_hash_aset(constant, rb_str_new2(pName), val); + } + SysFreeString(bstr); + if(pName) { + free(pName); + pName = NULL; + } + } + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + } + pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); + OLE_RELEASE(pTypeInfo); + } + rb_define_const(klass, "CONSTANTS", constant); +} + +static HRESULT +clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid) +{ + HKEY hlm; + HKEY hpid; + VALUE subkey; + LONG err; + char clsid[100]; + OLECHAR *pbuf; + DWORD len; + DWORD dwtype; + HRESULT hr = S_OK; + err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm); + if (err != ERROR_SUCCESS) + return HRESULT_FROM_WIN32(err); + subkey = rb_str_new2("SOFTWARE\\Classes\\"); + rb_str_concat(subkey, com); + rb_str_cat2(subkey, "\\CLSID"); + err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid); + if (err != ERROR_SUCCESS) + hr = HRESULT_FROM_WIN32(err); + else { + len = sizeof(clsid); + err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len); + if (err == ERROR_SUCCESS && dwtype == REG_SZ) { + pbuf = ole_mb2wc(clsid, -1); + hr = CLSIDFromString(pbuf, pclsid); + SysFreeString(pbuf); + } + else { + hr = HRESULT_FROM_WIN32(err); + } + RegCloseKey(hpid); + } + RegCloseKey(hlm); + return hr; +} + +static VALUE +ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others) +{ + HRESULT hr; + CLSID clsid; + OLECHAR *pbuf; + + COSERVERINFO serverinfo; + MULTI_QI multi_qi; + DWORD clsctx = CLSCTX_REMOTE_SERVER; + + if (!gole32) + gole32 = LoadLibrary("OLE32"); + if (!gole32) + rb_raise(rb_eRuntimeError, "failed to load OLE32"); + if (!gCoCreateInstanceEx) + gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*) + GetProcAddress(gole32, "CoCreateInstanceEx"); + if (!gCoCreateInstanceEx) + rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment"); + + pbuf = ole_vstr2wc(ole); + hr = CLSIDFromProgID(pbuf, &clsid); + if (FAILED(hr)) + hr = clsid_from_remote(host, ole, &clsid); + if (FAILED(hr)) + hr = CLSIDFromString(pbuf, &clsid); + SysFreeString(pbuf); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, + "unknown OLE server: `%s'", + StringValuePtr(ole)); + memset(&serverinfo, 0, sizeof(COSERVERINFO)); + serverinfo.pwszName = ole_vstr2wc(host); + memset(&multi_qi, 0, sizeof(MULTI_QI)); + multi_qi.pIID = &IID_IDispatch; + hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi); + SysFreeString(serverinfo.pwszName); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, + "failed to create DCOM server `%s' in `%s'", + StringValuePtr(ole), + StringValuePtr(host)); + + ole_set_member(self, (IDispatch*)multi_qi.pItf); + return self; +} + +static VALUE +ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) +{ + IBindCtx *pBindCtx; + IMoniker *pMoniker; + IDispatch *pDispatch; + void *p; + HRESULT hr; + OLECHAR *pbuf; + ULONG eaten = 0; + + ole_initialize(); + + hr = CreateBindCtx(0, &pBindCtx); + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "failed to create bind context"); + } + + pbuf = ole_vstr2wc(moniker); + hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker); + SysFreeString(pbuf); + if(FAILED(hr)) { + OLE_RELEASE(pBindCtx); + ole_raise(hr, eWIN32OLERuntimeError, + "failed to parse display name of moniker `%s'", + StringValuePtr(moniker)); + } + hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, + &IID_IDispatch, &p); + pDispatch = p; + OLE_RELEASE(pMoniker); + OLE_RELEASE(pBindCtx); + + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "failed to bind moniker `%s'", + StringValuePtr(moniker)); + } + return create_win32ole_object(self, pDispatch, argc, argv); +} + +/* + * call-seq: + * WIN32OLE.connect( ole ) --> aWIN32OLE + * + * Returns running OLE Automation object or WIN32OLE object from moniker. + * 1st argument should be OLE program id or class id or moniker. + * + * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel. + */ +static VALUE +fole_s_connect(int argc, VALUE *argv, VALUE self) +{ + VALUE svr_name; + VALUE others; + HRESULT hr; + CLSID clsid; + OLECHAR *pBuf; + IDispatch *pDispatch; + void *p; + IUnknown *pUnknown; + + /* initialize to use OLE */ + ole_initialize(); + + rb_scan_args(argc, argv, "1*", &svr_name, &others); + StringValue(svr_name); + if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { + rb_raise(rb_eSecurityError, "insecure connection - `%s'", + StringValuePtr(svr_name)); + } + + /* get CLSID from OLE server name */ + pBuf = ole_vstr2wc(svr_name); + hr = CLSIDFromProgID(pBuf, &clsid); + if(FAILED(hr)) { + hr = CLSIDFromString(pBuf, &clsid); + } + SysFreeString(pBuf); + if(FAILED(hr)) { + return ole_bind_obj(svr_name, argc, argv, self); + } + + hr = GetActiveObject(&clsid, 0, &pUnknown); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "OLE server `%s' not running", StringValuePtr(svr_name)); + } + hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p); + pDispatch = p; + if(FAILED(hr)) { + OLE_RELEASE(pUnknown); + ole_raise(hr, eWIN32OLERuntimeError, + "failed to create WIN32OLE server `%s'", + StringValuePtr(svr_name)); + } + + OLE_RELEASE(pUnknown); + + return create_win32ole_object(self, pDispatch, argc, argv); +} + +/* + * call-seq: + * WIN32OLE.const_load( ole, mod = WIN32OLE) + * + * Defines the constants of OLE Automation server as mod's constants. + * The first argument is WIN32OLE object or type library name. + * If 2nd argument is omitted, the default is WIN32OLE. + * The first letter of Ruby's constant variable name is upper case, + * so constant variable name of WIN32OLE object is capitalized. + * For example, the 'xlTop' constant of Excel is changed to 'XlTop' + * in WIN32OLE. + * If the first letter of constant variable is not [A-Z], then + * the constant is defined as CONSTANTS hash element. + * + * module EXCEL_CONST + * end + * excel = WIN32OLE.new('Excel.Application') + * WIN32OLE.const_load(excel, EXCEL_CONST) + * puts EXCEL_CONST::XlTop # => -4160 + * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541 + * + * WIN32OLE.const_load(excel) + * puts WIN32OLE::XlTop # => -4160 + * + * module MSO + * end + * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO) + * puts MSO::MsoLineSingle # => 1 + */ +static VALUE +fole_s_const_load(int argc, VALUE *argv, VALUE self) +{ + VALUE ole; + VALUE klass; + struct oledata *pole = NULL; + ITypeInfo *pTypeInfo; + ITypeLib *pTypeLib; + unsigned int index; + HRESULT hr; + OLECHAR *pBuf; + VALUE file; + LCID lcid = cWIN32OLE_lcid; + + rb_scan_args(argc, argv, "11", &ole, &klass); + if (!RB_TYPE_P(klass, T_CLASS) && + !RB_TYPE_P(klass, T_MODULE) && + !RB_TYPE_P(klass, T_NIL)) { + rb_raise(rb_eTypeError, "2nd parameter must be Class or Module"); + } + if (rb_obj_is_kind_of(ole, cWIN32OLE)) { + pole = oledata_get_struct(ole); + hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, + 0, lcid, &pTypeInfo); + if(FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); + } + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); + if(FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); + } + OLE_RELEASE(pTypeInfo); + if(!RB_TYPE_P(klass, T_NIL)) { + ole_const_load(pTypeLib, klass, self); + } + else { + ole_const_load(pTypeLib, cWIN32OLE, self); + } + OLE_RELEASE(pTypeLib); + } + else if(RB_TYPE_P(ole, T_STRING)) { + file = typelib_file(ole); + if (file == Qnil) { + file = ole; + } + pBuf = ole_vstr2wc(file); + hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib); + SysFreeString(pBuf); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); + if(!RB_TYPE_P(klass, T_NIL)) { + ole_const_load(pTypeLib, klass, self); + } + else { + ole_const_load(pTypeLib, cWIN32OLE, self); + } + OLE_RELEASE(pTypeLib); + } + else { + rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance"); + } + return Qnil; +} + +static ULONG +reference_count(struct oledata * pole) +{ + ULONG n = 0; + if(pole->pDispatch) { + OLE_ADDREF(pole->pDispatch); + n = OLE_RELEASE(pole->pDispatch); + } + return n; +} + +/* + * call-seq: + * WIN32OLE.ole_reference_count(aWIN32OLE) --> number + * + * Returns reference counter of Dispatch interface of WIN32OLE object. + * You should not use this method because this method + * exists only for debugging WIN32OLE. + */ +static VALUE +fole_s_reference_count(VALUE self, VALUE obj) +{ + struct oledata * pole = NULL; + pole = oledata_get_struct(obj); + return INT2NUM(reference_count(pole)); +} + +/* + * call-seq: + * WIN32OLE.ole_free(aWIN32OLE) --> number + * + * Invokes Release method of Dispatch interface of WIN32OLE object. + * You should not use this method because this method + * exists only for debugging WIN32OLE. + * The return value is reference counter of OLE object. + */ +static VALUE +fole_s_free(VALUE self, VALUE obj) +{ + ULONG n = 0; + struct oledata * pole = NULL; + pole = oledata_get_struct(obj); + if(pole->pDispatch) { + if (reference_count(pole) > 0) { + n = OLE_RELEASE(pole->pDispatch); + } + } + return INT2NUM(n); +} + +static HWND +ole_show_help(VALUE helpfile, VALUE helpcontext) +{ + FNHTMLHELP *pfnHtmlHelp; + HWND hwnd = 0; + + if(!ghhctrl) + ghhctrl = LoadLibrary("HHCTRL.OCX"); + if (!ghhctrl) + return hwnd; + pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA"); + if (!pfnHtmlHelp) + return hwnd; + hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), + 0x0f, NUM2INT(helpcontext)); + if (hwnd == 0) + hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile), + 0, NUM2INT(helpcontext)); + return hwnd; +} + +/* + * call-seq: + * WIN32OLE.ole_show_help(obj [,helpcontext]) + * + * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE + * object or WIN32OLE_METHOD object or helpfile. + * + * excel = WIN32OLE.new('Excel.Application') + * typeobj = excel.ole_type + * WIN32OLE.ole_show_help(typeobj) + */ +static VALUE +fole_s_show_help(int argc, VALUE *argv, VALUE self) +{ + VALUE target; + VALUE helpcontext; + VALUE helpfile; + VALUE name; + HWND hwnd; + rb_scan_args(argc, argv, "11", &target, &helpcontext); + if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) || + rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) { + helpfile = rb_funcall(target, rb_intern("helpfile"), 0); + if(strlen(StringValuePtr(helpfile)) == 0) { + name = rb_ivar_get(target, rb_intern("name")); + rb_raise(rb_eRuntimeError, "no helpfile of `%s'", + StringValuePtr(name)); + } + helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0); + } else { + helpfile = target; + } + if (!RB_TYPE_P(helpfile, T_STRING)) { + rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)"); + } + hwnd = ole_show_help(helpfile, helpcontext); + if(hwnd == 0) { + rb_raise(rb_eRuntimeError, "failed to open help file `%s'", + StringValuePtr(helpfile)); + } + return Qnil; +} + +/* + * call-seq: + * WIN32OLE.codepage + * + * Returns current codepage. + * WIN32OLE.codepage # => WIN32OLE::CP_ACP + */ +static VALUE +fole_s_get_code_page(VALUE self) +{ + return INT2FIX(cWIN32OLE_cp); +} + +static BOOL CALLBACK +installed_code_page_proc(LPTSTR str) { + if (strtoul(str, NULL, 10) == g_cp_to_check) { + g_cp_installed = TRUE; + return FALSE; + } + return TRUE; +} + +static BOOL +code_page_installed(UINT cp) +{ + g_cp_installed = FALSE; + g_cp_to_check = cp; + EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED); + return g_cp_installed; +} + +/* + * call-seq: + * WIN32OLE.codepage = CP + * + * Sets current codepage. + * The WIN32OLE.codepage is initialized according to + * Encoding.default_internal. + * If Encoding.default_internal is nil then WIN32OLE.codepage + * is initialized according to Encoding.default_external. + * + * WIN32OLE.codepage = WIN32OLE::CP_UTF8 + * WIN32OLE.codepage = 65001 + */ +static VALUE +fole_s_set_code_page(VALUE self, VALUE vcp) +{ + UINT cp = FIX2INT(vcp); + set_ole_codepage(cp); + /* + * Should this method return old codepage? + */ + return Qnil; +} + +/* + * call-seq: + * WIN32OLE.locale -> locale id. + * + * Returns current locale id (lcid). The default locale is + * WIN32OLE::LOCALE_SYSTEM_DEFAULT. + * + * lcid = WIN32OLE.locale + */ +static VALUE +fole_s_get_locale(VALUE self) +{ + return INT2FIX(cWIN32OLE_lcid); +} + +static BOOL +CALLBACK installed_lcid_proc(LPTSTR str) +{ + if (strcmp(str, g_lcid_to_check) == 0) { + g_lcid_installed = TRUE; + return FALSE; + } + return TRUE; +} + +static BOOL +lcid_installed(LCID lcid) +{ + g_lcid_installed = FALSE; + snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", (unsigned long)lcid); + EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED); + return g_lcid_installed; +} + +/* + * call-seq: + * WIN32OLE.locale = lcid + * + * Sets current locale id (lcid). + * + * WIN32OLE.locale = 1033 # set locale English(U.S) + * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) + * + */ +static VALUE +fole_s_set_locale(VALUE self, VALUE vlcid) +{ + LCID lcid = FIX2INT(vlcid); + if (lcid_installed(lcid)) { + cWIN32OLE_lcid = lcid; + } else { + switch (lcid) { + case LOCALE_SYSTEM_DEFAULT: + case LOCALE_USER_DEFAULT: + cWIN32OLE_lcid = lcid; + break; + default: + rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid); + } + } + return Qnil; +} + +/* + * call-seq: + * WIN32OLE.create_guid + * + * Creates GUID. + * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8} + */ +static VALUE +fole_s_create_guid(VALUE self) +{ + GUID guid; + HRESULT hr; + OLECHAR bstr[80]; + int len = 0; + hr = CoCreateGuid(&guid); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID"); + } + len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); + if (len == 0) { + rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)"); + } + return ole_wc2vstr(bstr, FALSE); +} + +/* + * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize + * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634). + * You must not use these method. + */ + +/* :nodoc: */ +static VALUE +fole_s_ole_initialize(VALUE self) +{ + ole_initialize(); + return Qnil; +} + +/* :nodoc: */ +static VALUE +fole_s_ole_uninitialize(VALUE self) +{ + ole_uninitialize(); + return Qnil; +} + +/* + * Document-class: WIN32OLE + * + * WIN32OLE objects represent OLE Automation object in Ruby. + * + * By using WIN32OLE, you can access OLE server like VBScript. + * + * Here is sample script. + * + * require 'win32ole' + * + * excel = WIN32OLE.new('Excel.Application') + * excel.visible = true + * workbook = excel.Workbooks.Add(); + * worksheet = workbook.Worksheets(1); + * worksheet.Range("A1:D1").value = ["North","South","East","West"]; + * worksheet.Range("A2:B2").value = [5.2, 10]; + * worksheet.Range("C2").value = 8; + * worksheet.Range("D2").value = 20; + * + * range = worksheet.Range("A1:D2"); + * range.select + * chart = workbook.Charts.Add; + * + * workbook.saved = true; + * + * excel.ActiveWorkbook.Close(0); + * excel.Quit(); + * + * Unfortunately, Win32OLE doesn't support the argument passed by + * reference directly. + * Instead, Win32OLE provides WIN32OLE::ARGV or WIN32OLE_VARIANT object. + * If you want to get the result value of argument passed by reference, + * you can use WIN32OLE::ARGV or WIN32OLE_VARIANT. + * + * oleobj.method(arg1, arg2, refargv3) + * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method + * + * or + * + * refargv3 = WIN32OLE_VARIANT.new(XXX, + * WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX) + * oleobj.method(arg1, arg2, refargv3) + * p refargv3.value # the value of refargv3 after called oleobj.method. + * + */ + +/* + * call-seq: + * WIN32OLE.new(server, [host]) -> WIN32OLE object + * + * Returns a new WIN32OLE object(OLE Automation object). + * The first argument server specifies OLE Automation server. + * The first argument should be CLSID or PROGID. + * If second argument host specified, then returns OLE Automation + * object on host. + * + * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object. + * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object. + */ +static VALUE +fole_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE svr_name; + VALUE host; + VALUE others; + HRESULT hr; + CLSID clsid; + OLECHAR *pBuf; + IDispatch *pDispatch; + void *p; + rb_call_super(0, 0); + rb_scan_args(argc, argv, "11*", &svr_name, &host, &others); + + StringValue(svr_name); + if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) { + rb_raise(rb_eSecurityError, "insecure object creation - `%s'", + StringValuePtr(svr_name)); + } + if (!NIL_P(host)) { + StringValue(host); + if (rb_safe_level() > 0 && OBJ_TAINTED(host)) { + rb_raise(rb_eSecurityError, "insecure object creation - `%s'", + StringValuePtr(host)); + } + return ole_create_dcom(self, svr_name, host, others); + } + + /* get CLSID from OLE server name */ + pBuf = ole_vstr2wc(svr_name); + hr = CLSIDFromProgID(pBuf, &clsid); + if(FAILED(hr)) { + hr = CLSIDFromString(pBuf, &clsid); + } + SysFreeString(pBuf); + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "unknown OLE server: `%s'", + StringValuePtr(svr_name)); + } + + /* get IDispatch interface */ + hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, + &IID_IDispatch, &p); + pDispatch = p; + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "failed to create WIN32OLE object from `%s'", + StringValuePtr(svr_name)); + } + + ole_set_member(self, pDispatch); + return self; +} + +static int +hash2named_arg(VALUE key, VALUE val, VALUE pop) +{ + struct oleparam* pOp = (struct oleparam *)pop; + unsigned int index, i; + index = pOp->dp.cNamedArgs; + /*--------------------------------------------- + the data-type of key must be String or Symbol + -----------------------------------------------*/ + if(!RB_TYPE_P(key, T_STRING) && !RB_TYPE_P(key, T_SYMBOL)) { + /* clear name of dispatch parameters */ + for(i = 1; i < index + 1; i++) { + SysFreeString(pOp->pNamedArgs[i]); + } + /* clear dispatch parameters */ + for(i = 0; i < index; i++ ) { + VariantClear(&(pOp->dp.rgvarg[i])); + } + /* raise an exception */ + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + if (RB_TYPE_P(key, T_SYMBOL)) { + key = rb_sym_to_s(key); + } + + /* pNamedArgs[0] is , so "index + 1" */ + pOp->pNamedArgs[index + 1] = ole_vstr2wc(key); + + VariantInit(&(pOp->dp.rgvarg[index])); + ole_val2variant(val, &(pOp->dp.rgvarg[index])); + + pOp->dp.cNamedArgs += 1; + return ST_CONTINUE; +} + +static VALUE +set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end) +{ + VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV")); + + Check_Type(argv, T_ARRAY); + rb_ary_clear(argv); + while (end-- > beg) { + rb_ary_push(argv, ole_variant2val(&realargs[end])); + if (V_VT(&realargs[end]) != VT_RECORD) { + VariantClear(&realargs[end]); + } + } + return argv; +} + +static VALUE +ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) +{ + LCID lcid = cWIN32OLE_lcid; + struct oledata *pole = NULL; + HRESULT hr; + VALUE cmd; + VALUE paramS; + VALUE param; + VALUE obj; + VALUE v; + + BSTR wcmdname; + + DISPID DispID; + DISPID* pDispID; + EXCEPINFO excepinfo; + VARIANT result; + VARIANTARG* realargs = NULL; + unsigned int argErr = 0; + unsigned int i; + unsigned int cNamedArgs; + int n; + struct oleparam op; + memset(&excepinfo, 0, sizeof(EXCEPINFO)); + + VariantInit(&result); + + op.dp.rgvarg = NULL; + op.dp.rgdispidNamedArgs = NULL; + op.dp.cNamedArgs = 0; + op.dp.cArgs = 0; + + rb_scan_args(argc, argv, "1*", &cmd, ¶mS); + if(!RB_TYPE_P(cmd, T_STRING) && !RB_TYPE_P(cmd, T_SYMBOL) && !is_bracket) { + rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)"); + } + if (RB_TYPE_P(cmd, T_SYMBOL)) { + cmd = rb_sym_to_s(cmd); + } + pole = oledata_get_struct(self); + if(!pole->pDispatch) { + rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); + } + if (is_bracket) { + DispID = DISPID_VALUE; + argc += 1; + rb_ary_unshift(paramS, cmd); + } else { + wcmdname = ole_vstr2wc(cmd); + hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, + &wcmdname, 1, lcid, &DispID); + SysFreeString(wcmdname); + if(FAILED(hr)) { + ole_raise(hr, rb_eNoMethodError, + "unknown property or method: `%s'", + StringValuePtr(cmd)); + } + } + + /* pick up last argument of method */ + param = rb_ary_entry(paramS, argc-2); + + op.dp.cNamedArgs = 0; + + /* if last arg is hash object */ + if(RB_TYPE_P(param, T_HASH)) { + /*------------------------------------------ + hash object ==> named dispatch parameters + --------------------------------------------*/ + cNamedArgs = rb_long2int(RHASH_SIZE(param)); + op.dp.cArgs = cNamedArgs + argc - 2; + op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); + op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); + + rb_hash_foreach(param, hash2named_arg, (VALUE)&op); + + pDispID = ALLOCA_N(DISPID, cNamedArgs + 1); + op.pNamedArgs[0] = ole_vstr2wc(cmd); + hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, + &IID_NULL, + op.pNamedArgs, + op.dp.cNamedArgs + 1, + lcid, pDispID); + for(i = 0; i < op.dp.cNamedArgs + 1; i++) { + SysFreeString(op.pNamedArgs[i]); + op.pNamedArgs[i] = NULL; + } + if(FAILED(hr)) { + /* clear dispatch parameters */ + for(i = 0; i < op.dp.cArgs; i++ ) { + VariantClear(&op.dp.rgvarg[i]); + } + ole_raise(hr, eWIN32OLERuntimeError, + "failed to get named argument info: `%s'", + StringValuePtr(cmd)); + } + op.dp.rgdispidNamedArgs = &(pDispID[1]); + } + else { + cNamedArgs = 0; + op.dp.cArgs = argc - 1; + op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1); + if (op.dp.cArgs > 0) { + op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs); + } + } + /*-------------------------------------- + non hash args ==> dispatch parameters + ----------------------------------------*/ + if(op.dp.cArgs > cNamedArgs) { + realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1); + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + VariantInit(&realargs[n]); + VariantInit(&op.dp.rgvarg[n]); + param = rb_ary_entry(paramS, i-cNamedArgs); + if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { + ole_variant2variant(param, &op.dp.rgvarg[n]); + } else if (rb_obj_is_kind_of(param, cWIN32OLE_RECORD)) { + ole_val2variant(param, &realargs[n]); + op.dp.rgvarg[n] = realargs[n]; + V_VT(&op.dp.rgvarg[n]) = VT_RECORD | VT_BYREF; + } else { + ole_val2variant(param, &realargs[n]); + V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; + V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; + } + } + } + /* apparent you need to call propput, you need this */ + if (wFlags & DISPATCH_PROPERTYPUT) { + if (op.dp.cArgs == 0) + ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error"); + + op.dp.cNamedArgs = 1; + op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); + op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; + } + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, + &IID_NULL, lcid, wFlags, &op.dp, + &result, &excepinfo, &argErr); + + if (FAILED(hr)) { + /* retry to call args by value */ + if(op.dp.cArgs >= cNamedArgs) { + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + param = rb_ary_entry(paramS, i-cNamedArgs); + ole_val2variant(param, &op.dp.rgvarg[n]); + } + if (hr == DISP_E_EXCEPTION) { + ole_freeexceptinfo(&excepinfo); + } + memset(&excepinfo, 0, sizeof(EXCEPINFO)); + VariantInit(&result); + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, + &IID_NULL, lcid, wFlags, + &op.dp, &result, + &excepinfo, &argErr); + + /* mega kludge. if a method in WORD is called and we ask + * for a result when one is not returned then + * hResult == DISP_E_EXCEPTION. this only happens on + * functions whose DISPID > 0x8000 */ + if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) { + if (hr == DISP_E_EXCEPTION) { + ole_freeexceptinfo(&excepinfo); + } + memset(&excepinfo, 0, sizeof(EXCEPINFO)); + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, + &IID_NULL, lcid, wFlags, + &op.dp, NULL, + &excepinfo, &argErr); + + } + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) { + VariantClear(&op.dp.rgvarg[n]); + } + } + } + + if (FAILED(hr)) { + /* retry after converting nil to VT_EMPTY */ + if (op.dp.cArgs > cNamedArgs) { + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + param = rb_ary_entry(paramS, i-cNamedArgs); + ole_val2variant2(param, &op.dp.rgvarg[n]); + } + if (hr == DISP_E_EXCEPTION) { + ole_freeexceptinfo(&excepinfo); + } + memset(&excepinfo, 0, sizeof(EXCEPINFO)); + VariantInit(&result); + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID, + &IID_NULL, lcid, wFlags, + &op.dp, &result, + &excepinfo, &argErr); + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) { + VariantClear(&op.dp.rgvarg[n]); + } + } + } + } + + } + /* clear dispatch parameter */ + if(op.dp.cArgs > cNamedArgs) { + for(i = cNamedArgs; i < op.dp.cArgs; i++) { + n = op.dp.cArgs - i + cNamedArgs - 1; + param = rb_ary_entry(paramS, i-cNamedArgs); + if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { + ole_val2variant(param, &realargs[n]); + } else if ( rb_obj_is_kind_of(param, cWIN32OLE_RECORD) && + V_VT(&realargs[n]) == VT_RECORD ) { + olerecord_set_ivar(param, V_RECORDINFO(&realargs[n]), V_RECORD(&realargs[n])); + } + } + set_argv(realargs, cNamedArgs, op.dp.cArgs); + } + else { + for(i = 0; i < op.dp.cArgs; i++) { + VariantClear(&op.dp.rgvarg[i]); + } + } + + if (FAILED(hr)) { + v = ole_excepinfo2msg(&excepinfo); + ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s", + StringValuePtr(cmd), + StringValuePtr(v)); + } + obj = ole_variant2val(&result); + VariantClear(&result); + return obj; +} + +/* + * call-seq: + * WIN32OLE#invoke(method, [arg1,...]) => return value of method. + * + * Runs OLE method. + * The first argument specifies the method name of OLE Automation object. + * The others specify argument of the method. + * If you can not execute method directly, then use this method instead. + * + * excel = WIN32OLE.new('Excel.Application') + * excel.invoke('Quit') # => same as excel.Quit + * + */ +static VALUE +fole_invoke(int argc, VALUE *argv, VALUE self) +{ + return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); +} + +static VALUE +ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind) +{ + HRESULT hr; + struct oledata *pole = NULL; + unsigned int argErr = 0; + EXCEPINFO excepinfo; + VARIANT result; + DISPPARAMS dispParams; + VARIANTARG* realargs = NULL; + int i, j; + VALUE obj = Qnil; + VALUE tp, param; + VALUE v; + VARTYPE vt; + + Check_Type(args, T_ARRAY); + Check_Type(types, T_ARRAY); + + memset(&excepinfo, 0, sizeof(EXCEPINFO)); + memset(&dispParams, 0, sizeof(DISPPARAMS)); + VariantInit(&result); + pole = oledata_get_struct(self); + + dispParams.cArgs = RARRAY_LEN(args); + dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs); + realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs); + for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--) + { + VariantInit(&realargs[i]); + VariantInit(&dispParams.rgvarg[i]); + tp = rb_ary_entry(types, j); + vt = (VARTYPE)FIX2INT(tp); + V_VT(&dispParams.rgvarg[i]) = vt; + param = rb_ary_entry(args, j); + if (param == Qnil) + { + + V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR; + V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND; + } + else + { + if (vt & VT_ARRAY) + { + int ent; + LPBYTE pb; + short* ps; + LPLONG pl; + VARIANT* pv; + CY *py; + VARTYPE v; + SAFEARRAYBOUND rgsabound[1]; + Check_Type(param, T_ARRAY); + rgsabound[0].lLbound = 0; + rgsabound[0].cElements = RARRAY_LEN(param); + v = vt & ~(VT_ARRAY | VT_BYREF); + V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound); + V_VT(&realargs[i]) = VT_ARRAY | v; + SafeArrayLock(V_ARRAY(&realargs[i])); + pb = V_ARRAY(&realargs[i])->pvData; + ps = V_ARRAY(&realargs[i])->pvData; + pl = V_ARRAY(&realargs[i])->pvData; + py = V_ARRAY(&realargs[i])->pvData; + pv = V_ARRAY(&realargs[i])->pvData; + for (ent = 0; ent < (int)rgsabound[0].cElements; ent++) + { + VARIANT velem; + VALUE elem = rb_ary_entry(param, ent); + ole_val2variant(elem, &velem); + if (v != VT_VARIANT) + { + VariantChangeTypeEx(&velem, &velem, + cWIN32OLE_lcid, 0, v); + } + switch (v) + { + /* 128 bits */ + case VT_VARIANT: + *pv++ = velem; + break; + /* 64 bits */ + case VT_R8: + case VT_CY: + case VT_DATE: + *py++ = V_CY(&velem); + break; + /* 16 bits */ + case VT_BOOL: + case VT_I2: + case VT_UI2: + *ps++ = V_I2(&velem); + break; + /* 8 bites */ + case VT_UI1: + case VT_I1: + *pb++ = V_UI1(&velem); + break; + /* 32 bits */ + default: + *pl++ = V_I4(&velem); + break; + } + } + SafeArrayUnlock(V_ARRAY(&realargs[i])); + } + else + { + ole_val2variant(param, &realargs[i]); + if ((vt & (~VT_BYREF)) != VT_VARIANT) + { + hr = VariantChangeTypeEx(&realargs[i], &realargs[i], + cWIN32OLE_lcid, 0, + (VARTYPE)(vt & (~VT_BYREF))); + if (hr != S_OK) + { + rb_raise(rb_eTypeError, "not valid value"); + } + } + } + if ((vt & VT_BYREF) || vt == VT_VARIANT) + { + if (vt == VT_VARIANT) + V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF; + switch (vt & (~VT_BYREF)) + { + /* 128 bits */ + case VT_VARIANT: + V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i]; + break; + /* 64 bits */ + case VT_R8: + case VT_CY: + case VT_DATE: + V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]); + break; + /* 16 bits */ + case VT_BOOL: + case VT_I2: + case VT_UI2: + V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]); + break; + /* 8 bites */ + case VT_UI1: + case VT_I1: + V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]); + break; + /* 32 bits */ + default: + V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]); + break; + } + } + else + { + /* copy 64 bits of data */ + V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]); + } + } + } + + if (dispkind & DISPATCH_PROPERTYPUT) { + dispParams.cNamedArgs = 1; + dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 ); + dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT; + } + + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, NUM2INT(dispid), + &IID_NULL, cWIN32OLE_lcid, + dispkind, + &dispParams, &result, + &excepinfo, &argErr); + + if (FAILED(hr)) { + v = ole_excepinfo2msg(&excepinfo); + ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `': )%s", + NUM2INT(dispid), + StringValuePtr(v)); + } + + /* clear dispatch parameter */ + if(dispParams.cArgs > 0) { + set_argv(realargs, 0, dispParams.cArgs); + } + + obj = ole_variant2val(&result); + VariantClear(&result); + return obj; +} + +/* + * call-seq: + * WIN32OLE#_invoke(dispid, args, types) + * + * Runs the early binding method. + * The 1st argument specifies dispatch ID, + * the 2nd argument specifies the array of arguments, + * the 3rd argument specifies the array of the type of arguments. + * + * excel = WIN32OLE.new('Excel.Application') + * excel._invoke(302, [], []) # same effect as excel.Quit + */ +static VALUE +fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types) +{ + return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD); +} + +/* + * call-seq: + * WIN32OLE#_getproperty(dispid, args, types) + * + * Runs the early binding method to get property. + * The 1st argument specifies dispatch ID, + * the 2nd argument specifies the array of arguments, + * the 3rd argument specifies the array of the type of arguments. + * + * excel = WIN32OLE.new('Excel.Application') + * puts excel._getproperty(558, [], []) # same effect as puts excel.visible + */ +static VALUE +fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) +{ + return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET); +} + +/* + * call-seq: + * WIN32OLE#_setproperty(dispid, args, types) + * + * Runs the early binding method to set property. + * The 1st argument specifies dispatch ID, + * the 2nd argument specifies the array of arguments, + * the 3rd argument specifies the array of the type of arguments. + * + * excel = WIN32OLE.new('Excel.Application') + * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true + */ +static VALUE +fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) +{ + return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT); +} + +/* + * call-seq: + * WIN32OLE[a1, a2, ...]=val + * + * Sets the value to WIN32OLE object specified by a1, a2, ... + * + * dict = WIN32OLE.new('Scripting.Dictionary') + * dict.add('ruby', 'RUBY') + * dict['ruby'] = 'Ruby' + * puts dict['ruby'] # => 'Ruby' + * + * Remark: You can not use this method to set the property value. + * + * excel = WIN32OLE.new('Excel.Application') + * # excel['Visible'] = true # This is error !!! + * excel.Visible = true # You should to use this style to set the property. + * + */ +static VALUE +fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self) +{ + return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE); +} + +/* + * call-seq: + * WIN32OLE.setproperty('property', [arg1, arg2,...] val) + * + * Sets property of OLE object. + * When you want to set property with argument, you can use this method. + * + * excel = WIN32OLE.new('Excel.Application') + * excel.Visible = true + * book = excel.workbooks.add + * sheet = book.worksheets(1) + * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10. + */ +static VALUE +fole_setproperty(int argc, VALUE *argv, VALUE self) +{ + return ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE); +} + +/* + * call-seq: + * WIN32OLE[a1,a2,...] + * + * Returns the value of Collection specified by a1, a2,.... + * + * dict = WIN32OLE.new('Scripting.Dictionary') + * dict.add('ruby', 'Ruby') + * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')') + * + * Remark: You can not use this method to get the property. + * excel = WIN32OLE.new('Excel.Application') + * # puts excel['Visible'] This is error !!! + * puts excel.Visible # You should to use this style to get the property. + * + */ +static VALUE +fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self) +{ + return ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE); +} + +static VALUE +ole_propertyput(VALUE self, VALUE property, VALUE value) +{ + struct oledata *pole = NULL; + unsigned argErr; + unsigned int index; + HRESULT hr; + EXCEPINFO excepinfo; + DISPID dispID = DISPID_VALUE; + DISPID dispIDParam = DISPID_PROPERTYPUT; + USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF; + DISPPARAMS dispParams; + VARIANTARG propertyValue[2]; + OLECHAR* pBuf[1]; + VALUE v; + LCID lcid = cWIN32OLE_lcid; + dispParams.rgdispidNamedArgs = &dispIDParam; + dispParams.rgvarg = propertyValue; + dispParams.cNamedArgs = 1; + dispParams.cArgs = 1; + + VariantInit(&propertyValue[0]); + VariantInit(&propertyValue[1]); + memset(&excepinfo, 0, sizeof(excepinfo)); + + pole = oledata_get_struct(self); + + /* get ID from property name */ + pBuf[0] = ole_vstr2wc(property); + hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, + pBuf, 1, lcid, &dispID); + SysFreeString(pBuf[0]); + pBuf[0] = NULL; + + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "unknown property or method: `%s'", + StringValuePtr(property)); + } + /* set property value */ + ole_val2variant(value, &propertyValue[0]); + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL, + lcid, wFlags, &dispParams, + NULL, &excepinfo, &argErr); + + for(index = 0; index < dispParams.cArgs; ++index) { + VariantClear(&propertyValue[index]); + } + if (FAILED(hr)) { + v = ole_excepinfo2msg(&excepinfo); + ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s", + StringValuePtr(property), + StringValuePtr(v)); + } + return Qnil; +} + +/* + * call-seq: + * WIN32OLE#ole_free + * + * invokes Release method of Dispatch interface of WIN32OLE object. + * Usually, you do not need to call this method because Release method + * called automatically when WIN32OLE object garbaged. + * + */ +static VALUE +fole_free(VALUE self) +{ + struct oledata *pole = NULL; + pole = oledata_get_struct(self); + OLE_FREE(pole->pDispatch); + pole->pDispatch = NULL; + return Qnil; +} + +static VALUE +ole_each_sub(VALUE pEnumV) +{ + VARIANT variant; + VALUE obj = Qnil; + IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; + VariantInit(&variant); + while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) { + obj = ole_variant2val(&variant); + VariantClear(&variant); + VariantInit(&variant); + rb_yield(obj); + } + return Qnil; +} + +static VALUE +ole_ienum_free(VALUE pEnumV) +{ + IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV; + OLE_RELEASE(pEnum); + return Qnil; +} + +/* + * call-seq: + * WIN32OLE#each {|i|...} + * + * Iterates over each item of OLE collection which has IEnumVARIANT interface. + * + * excel = WIN32OLE.new('Excel.Application') + * book = excel.workbooks.add + * sheets = book.worksheets(1) + * cells = sheets.cells("A1:A5") + * cells.each do |cell| + * cell.value = 10 + * end + */ +static VALUE +fole_each(VALUE self) +{ + LCID lcid = cWIN32OLE_lcid; + + struct oledata *pole = NULL; + + unsigned int argErr; + EXCEPINFO excepinfo; + DISPPARAMS dispParams; + VARIANT result; + HRESULT hr; + IEnumVARIANT *pEnum = NULL; + void *p; + + RETURN_ENUMERATOR(self, 0, 0); + + VariantInit(&result); + dispParams.rgvarg = NULL; + dispParams.rgdispidNamedArgs = NULL; + dispParams.cNamedArgs = 0; + dispParams.cArgs = 0; + memset(&excepinfo, 0, sizeof(excepinfo)); + + pole = oledata_get_struct(self); + hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM, + &IID_NULL, lcid, + DISPATCH_METHOD | DISPATCH_PROPERTYGET, + &dispParams, &result, + &excepinfo, &argErr); + + if (FAILED(hr)) { + VariantClear(&result); + ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface"); + } + + if (V_VT(&result) == VT_UNKNOWN) { + hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result), + &IID_IEnumVARIANT, + &p); + pEnum = p; + } else if (V_VT(&result) == VT_DISPATCH) { + hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result), + &IID_IEnumVARIANT, + &p); + pEnum = p; + } + if (FAILED(hr) || !pEnum) { + VariantClear(&result); + ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface"); + } + + VariantClear(&result); + rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum); + return Qnil; +} + +/* + * call-seq: + * WIN32OLE#method_missing(id [,arg1, arg2, ...]) + * + * Calls WIN32OLE#invoke method. + */ +static VALUE +fole_missing(int argc, VALUE *argv, VALUE self) +{ + ID id; + const char* mname; + size_t n; + rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); + id = rb_to_id(argv[0]); + mname = rb_id2name(id); + if(!mname) { + rb_raise(rb_eRuntimeError, "fail: unknown method or property"); + } + n = strlen(mname); +#if SIZEOF_SIZE_T > SIZEOF_LONG + if (n >= LONG_MAX) { + rb_raise(rb_eRuntimeError, "too long method or property name"); + } +#endif + if(mname[n-1] == '=') { + rb_check_arity(argc, 2, 2); + argv[0] = rb_enc_str_new(mname, (long)(n-1), cWIN32OLE_enc); + + return ole_propertyput(self, argv[0], argv[1]); + } + else { + argv[0] = rb_enc_str_new(mname, (long)n, cWIN32OLE_enc); + return ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE); + } +} + +static HRESULT +typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti) +{ + ITypeInfo *pTypeInfo; + ITypeLib *pTypeLib; + BSTR bstr; + VALUE type; + UINT i; + UINT count; + LCID lcid = cWIN32OLE_lcid; + HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, + 0, lcid, &pTypeInfo); + if(FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); + } + hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, + -1, + &bstr, + NULL, NULL, NULL); + type = WC2VSTR(bstr); + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); + OLE_RELEASE(pTypeInfo); + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to GetContainingTypeLib"); + } + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (i = 0; i < count; i++) { + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, + &bstr, NULL, NULL, NULL); + if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); + if (SUCCEEDED(hr)) { + *ppti = pTypeInfo; + break; + } + } + } + OLE_RELEASE(pTypeLib); + return hr; +} + +static VALUE +ole_methods(VALUE self, int mask) +{ + ITypeInfo *pTypeInfo; + HRESULT hr; + VALUE methods; + struct oledata *pole = NULL; + + pole = oledata_get_struct(self); + methods = rb_ary_new(); + + hr = typeinfo_from_ole(pole, &pTypeInfo); + if(FAILED(hr)) + return methods; + rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask)); + OLE_RELEASE(pTypeInfo); + return methods; +} + +/* + * call-seq: + * WIN32OLE#ole_methods + * + * Returns the array of WIN32OLE_METHOD object. + * The element is OLE method of WIN32OLE object. + * + * excel = WIN32OLE.new('Excel.Application') + * methods = excel.ole_methods + * + */ +static VALUE +fole_methods(VALUE self) +{ + return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); +} + +/* + * call-seq: + * WIN32OLE#ole_get_methods + * + * Returns the array of WIN32OLE_METHOD object . + * The element of the array is property (gettable) of WIN32OLE object. + * + * excel = WIN32OLE.new('Excel.Application') + * properties = excel.ole_get_methods + */ +static VALUE +fole_get_methods(VALUE self) +{ + return ole_methods( self, INVOKE_PROPERTYGET); +} + +/* + * call-seq: + * WIN32OLE#ole_put_methods + * + * Returns the array of WIN32OLE_METHOD object . + * The element of the array is property (settable) of WIN32OLE object. + * + * excel = WIN32OLE.new('Excel.Application') + * properties = excel.ole_put_methods + */ +static VALUE +fole_put_methods(VALUE self) +{ + return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF); +} + +/* + * call-seq: + * WIN32OLE#ole_func_methods + * + * Returns the array of WIN32OLE_METHOD object . + * The element of the array is property (settable) of WIN32OLE object. + * + * excel = WIN32OLE.new('Excel.Application') + * properties = excel.ole_func_methods + * + */ +static VALUE +fole_func_methods(VALUE self) +{ + return ole_methods( self, INVOKE_FUNC); +} + +/* + * call-seq: + * WIN32OLE#ole_type + * + * Returns WIN32OLE_TYPE object. + * + * excel = WIN32OLE.new('Excel.Application') + * tobj = excel.ole_type + */ +static VALUE +fole_type(VALUE self) +{ + ITypeInfo *pTypeInfo; + HRESULT hr; + struct oledata *pole = NULL; + LCID lcid = cWIN32OLE_lcid; + VALUE type = Qnil; + + pole = oledata_get_struct(self); + + hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo ); + if(FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); + } + type = ole_type_from_itypeinfo(pTypeInfo); + OLE_RELEASE(pTypeInfo); + if (type == Qnil) { + rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo"); + } + return type; +} + +/* + * call-seq: + * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object + * + * Returns the WIN32OLE_TYPELIB object. The object represents the + * type library which contains the WIN32OLE object. + * + * excel = WIN32OLE.new('Excel.Application') + * tlib = excel.ole_typelib + * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library' + */ +static VALUE +fole_typelib(VALUE self) +{ + struct oledata *pole = NULL; + HRESULT hr; + ITypeInfo *pTypeInfo; + LCID lcid = cWIN32OLE_lcid; + VALUE vtlib = Qnil; + + pole = oledata_get_struct(self); + hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, + 0, lcid, &pTypeInfo); + if(FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to GetTypeInfo"); + } + vtlib = ole_typelib_from_itypeinfo(pTypeInfo); + OLE_RELEASE(pTypeInfo); + if (vtlib == Qnil) { + rb_raise(rb_eRuntimeError, "failed to get type library info."); + } + return vtlib; +} + +/* + * call-seq: + * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object + * + * Returns WIN32OLE object for a specific dispatch or dual + * interface specified by iid. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp + */ +static VALUE +fole_query_interface(VALUE self, VALUE str_iid) +{ + HRESULT hr; + OLECHAR *pBuf; + IID iid; + struct oledata *pole = NULL; + IDispatch *pDispatch; + void *p; + + pBuf = ole_vstr2wc(str_iid); + hr = CLSIDFromString(pBuf, &iid); + SysFreeString(pBuf); + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "invalid iid: `%s'", + StringValuePtr(str_iid)); + } + + pole = oledata_get_struct(self); + if(!pole->pDispatch) { + rb_raise(rb_eRuntimeError, "failed to get dispatch interface"); + } + + hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid, + &p); + if(FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "failed to get interface `%s'", + StringValuePtr(str_iid)); + } + + pDispatch = p; + return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); +} + +/* + * call-seq: + * WIN32OLE#ole_respond_to?(method) -> true or false + * + * Returns true when OLE object has OLE method, otherwise returns false. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ie.ole_respond_to?("gohome") => true + */ +static VALUE +fole_respond_to(VALUE self, VALUE method) +{ + struct oledata *pole = NULL; + BSTR wcmdname; + DISPID DispID; + HRESULT hr; + if(!RB_TYPE_P(method, T_STRING) && !RB_TYPE_P(method, T_SYMBOL)) { + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + if (RB_TYPE_P(method, T_SYMBOL)) { + method = rb_sym_to_s(method); + } + pole = oledata_get_struct(self); + wcmdname = ole_vstr2wc(method); + hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, + &wcmdname, 1, cWIN32OLE_lcid, &DispID); + SysFreeString(wcmdname); + return SUCCEEDED(hr) ? Qtrue : Qfalse; +} + +HRESULT +ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile) +{ + HRESULT hr; + ITypeLib *pTypeLib; + UINT i; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i); + if (FAILED(hr)) { + return hr; + } + + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, + name, helpstr, + helpcontext, helpfile); + if (FAILED(hr)) { + OLE_RELEASE(pTypeLib); + return hr; + } + OLE_RELEASE(pTypeLib); + return hr; +} + +static VALUE +ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) +{ + HRESULT hr; + BSTR bstr; + ITypeInfo *pRefTypeInfo; + VALUE type = Qnil; + + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, + V_UNION1(pTypeDesc, hreftype), + &pRefTypeInfo); + if(FAILED(hr)) + return Qnil; + hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL); + if(FAILED(hr)) { + OLE_RELEASE(pRefTypeInfo); + return Qnil; + } + OLE_RELEASE(pRefTypeInfo); + type = WC2VSTR(bstr); + if(typedetails != Qnil) + rb_ary_push(typedetails, type); + return type; +} + +static VALUE +ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) +{ + TYPEDESC *p = pTypeDesc; + VALUE type = rb_str_new2(""); + + if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) { + p = V_UNION1(p, lptdesc); + type = ole_typedesc2val(pTypeInfo, p, typedetails); + } + return type; +} + +VALUE +ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) +{ + VALUE str; + VALUE typestr = Qnil; + switch(pTypeDesc->vt) { + case VT_I2: + typestr = rb_str_new2("I2"); + break; + case VT_I4: + typestr = rb_str_new2("I4"); + break; + case VT_R4: + typestr = rb_str_new2("R4"); + break; + case VT_R8: + typestr = rb_str_new2("R8"); + break; + case VT_CY: + typestr = rb_str_new2("CY"); + break; + case VT_DATE: + typestr = rb_str_new2("DATE"); + break; + case VT_BSTR: + typestr = rb_str_new2("BSTR"); + break; + case VT_BOOL: + typestr = rb_str_new2("BOOL"); + break; + case VT_VARIANT: + typestr = rb_str_new2("VARIANT"); + break; + case VT_DECIMAL: + typestr = rb_str_new2("DECIMAL"); + break; + case VT_I1: + typestr = rb_str_new2("I1"); + break; + case VT_UI1: + typestr = rb_str_new2("UI1"); + break; + case VT_UI2: + typestr = rb_str_new2("UI2"); + break; + case VT_UI4: + typestr = rb_str_new2("UI4"); + break; +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + case VT_I8: + typestr = rb_str_new2("I8"); + break; + case VT_UI8: + typestr = rb_str_new2("UI8"); + break; +#endif + case VT_INT: + typestr = rb_str_new2("INT"); + break; + case VT_UINT: + typestr = rb_str_new2("UINT"); + break; + case VT_VOID: + typestr = rb_str_new2("VOID"); + break; + case VT_HRESULT: + typestr = rb_str_new2("HRESULT"); + break; + case VT_PTR: + typestr = rb_str_new2("PTR"); + if(typedetails != Qnil) + rb_ary_push(typedetails, typestr); + return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); + case VT_SAFEARRAY: + typestr = rb_str_new2("SAFEARRAY"); + if(typedetails != Qnil) + rb_ary_push(typedetails, typestr); + return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails); + case VT_CARRAY: + typestr = rb_str_new2("CARRAY"); + break; + case VT_USERDEFINED: + typestr = rb_str_new2("USERDEFINED"); + if (typedetails != Qnil) + rb_ary_push(typedetails, typestr); + str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails); + if (str != Qnil) { + return str; + } + return typestr; + case VT_UNKNOWN: + typestr = rb_str_new2("UNKNOWN"); + break; + case VT_DISPATCH: + typestr = rb_str_new2("DISPATCH"); + break; + case VT_ERROR: + typestr = rb_str_new2("ERROR"); + break; + case VT_LPWSTR: + typestr = rb_str_new2("LPWSTR"); + break; + case VT_LPSTR: + typestr = rb_str_new2("LPSTR"); + break; + case VT_RECORD: + typestr = rb_str_new2("RECORD"); + break; + default: + typestr = rb_str_new2("Unknown Type "); + rb_str_concat(typestr, rb_fix2str(INT2FIX(pTypeDesc->vt), 10)); + break; + } + if (typedetails != Qnil) + rb_ary_push(typedetails, typestr); + return typestr; +} + +/* + * call-seq: + * WIN32OLE#ole_method_help(method) + * + * Returns WIN32OLE_METHOD object corresponding with method + * specified by 1st argument. + * + * excel = WIN32OLE.new('Excel.Application') + * method = excel.ole_method_help('Quit') + * + */ +static VALUE +fole_method_help(VALUE self, VALUE cmdname) +{ + ITypeInfo *pTypeInfo; + HRESULT hr; + struct oledata *pole = NULL; + VALUE obj; + + SafeStringValue(cmdname); + pole = oledata_get_struct(self); + hr = typeinfo_from_ole(pole, &pTypeInfo); + if(FAILED(hr)) + ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo"); + + obj = create_win32ole_method(pTypeInfo, cmdname); + + OLE_RELEASE(pTypeInfo); + if (obj == Qnil) + rb_raise(eWIN32OLERuntimeError, "not found %s", + StringValuePtr(cmdname)); + return obj; +} + +/* + * call-seq: + * WIN32OLE#ole_activex_initialize() -> Qnil + * + * Initialize WIN32OLE object(ActiveX Control) by calling + * IPersistMemory::InitNew. + * + * Before calling OLE method, some kind of the ActiveX controls + * created with MFC should be initialized by calling + * IPersistXXX::InitNew. + * + * If and only if you received the exception "HRESULT error code: + * 0x8000ffff catastrophic failure", try this method before + * invoking any ole_method. + * + * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control") + * obj.ole_activex_initialize + * obj.method(...) + * + */ +static VALUE +fole_activex_initialize(VALUE self) +{ + struct oledata *pole = NULL; + IPersistMemory *pPersistMemory; + void *p; + + HRESULT hr = S_OK; + + pole = oledata_get_struct(self); + + hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p); + pPersistMemory = p; + if (SUCCEEDED(hr)) { + hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory); + OLE_RELEASE(pPersistMemory); + if (SUCCEEDED(hr)) { + return Qnil; + } + } + + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control"); + } + + return Qnil; +} + +HRESULT +typelib_from_val(VALUE obj, ITypeLib **pTypeLib) +{ + LCID lcid = cWIN32OLE_lcid; + HRESULT hr; + struct oledata *pole = NULL; + unsigned int index; + ITypeInfo *pTypeInfo; + pole = oledata_get_struct(obj); + hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch, + 0, lcid, &pTypeInfo); + if (FAILED(hr)) { + return hr; + } + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, pTypeLib, &index); + OLE_RELEASE(pTypeInfo); + return hr; +} + +static void +init_enc2cp(void) +{ + enc2cp_table = st_init_numtable(); +} + +static void +free_enc2cp(void) +{ + st_free_table(enc2cp_table); +} + +static void +com_hash_free(void *ptr) +{ + st_table *tbl = ptr; + st_free_table(tbl); +} + +static void +com_hash_mark(void *ptr) +{ + st_table *tbl = ptr; + rb_mark_hash(tbl); +} + +static size_t +com_hash_size(const void *ptr) +{ + const st_table *tbl = ptr; + return tbl ? st_memsize(tbl) : 0; +} + +void +Init_win32ole(void) +{ + cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT; + g_ole_initialized_init(); + + com_vtbl.QueryInterface = QueryInterface; + com_vtbl.AddRef = AddRef; + com_vtbl.Release = Release; + com_vtbl.GetTypeInfoCount = GetTypeInfoCount; + com_vtbl.GetTypeInfo = GetTypeInfo; + com_vtbl.GetIDsOfNames = GetIDsOfNames; + com_vtbl.Invoke = Invoke; + + message_filter.QueryInterface = mf_QueryInterface; + message_filter.AddRef = mf_AddRef; + message_filter.Release = mf_Release; + message_filter.HandleInComingCall = mf_HandleInComingCall; + message_filter.RetryRejectedCall = mf_RetryRejectedCall; + message_filter.MessagePending = mf_MessagePending; + + com_hash = TypedData_Wrap_Struct(rb_cData, &com_hash_datatype, st_init_numtable()); + rb_gc_register_mark_object(com_hash); + + cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); + + rb_define_alloc_func(cWIN32OLE, fole_s_allocate); + + rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1); + + rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1); + rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1); + + rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1); + rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1); + rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1); + rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0); + rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1); + rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0); + rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1); + rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0); + rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0); + rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0); + + rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1); + rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1); + rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3); + rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3); + rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3); + + /* support propput method that takes an argument */ + rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1); + + rb_define_method(cWIN32OLE, "ole_free", fole_free, 0); + + rb_define_method(cWIN32OLE, "each", fole_each, 0); + rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1); + + /* support setproperty method much like Perl ;-) */ + rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1); + + rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0); + rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0); + rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0); + rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0); + + rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1); + rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method"); + rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0); + rb_define_method(cWIN32OLE, "ole_type", fole_type, 0); + rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type"); + rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0); + rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1); + rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1); + + /* Constants definition */ + + /* + * Version string of WIN32OLE. + */ + rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION)); + + /* + * After invoking OLE methods with reference arguments, you can access + * the value of arguments by using ARGV. + * + * If the method of OLE(COM) server written by C#.NET is following: + * + * void calcsum(int a, int b, out int c) { + * c = a + b; + * } + * + * then, the Ruby OLE(COM) client script to retrieve the value of + * argument c after invoking calcsum method is following: + * + * a = 10 + * b = 20 + * c = 0 + * comserver.calcsum(a, b, c) + * p c # => 0 + * p WIN32OLE::ARGV # => [10, 20, 30] + * + * You can use WIN32OLE_VARIANT object to retrieve the value of reference + * arguments instead of refering WIN32OLE::ARGV. + * + */ + rb_define_const(cWIN32OLE, "ARGV", rb_ary_new()); + + /* + * 0: ANSI code page. See WIN32OLE.codepage and WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_ACP", INT2FIX(CP_ACP)); + + /* + * 1: OEM code page. See WIN32OLE.codepage and WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_OEMCP", INT2FIX(CP_OEMCP)); + + /* + * 2 + */ + rb_define_const(cWIN32OLE, "CP_MACCP", INT2FIX(CP_MACCP)); + + /* + * 3: current thread ANSI code page. See WIN32OLE.codepage and + * WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_THREAD_ACP", INT2FIX(CP_THREAD_ACP)); + + /* + * 42: symbol code page. See WIN32OLE.codepage and WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_SYMBOL", INT2FIX(CP_SYMBOL)); + + /* + * 65000: UTF-7 code page. See WIN32OLE.codepage and WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_UTF7", INT2FIX(CP_UTF7)); + + /* + * 65001: UTF-8 code page. See WIN32OLE.codepage and WIN32OLE.codepage=. + */ + rb_define_const(cWIN32OLE, "CP_UTF8", INT2FIX(CP_UTF8)); + + /* + * 0x0800: default locale for the operating system. See WIN32OLE.locale + * and WIN32OLE.locale=. + */ + rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", INT2FIX(LOCALE_SYSTEM_DEFAULT)); + + /* + * 0x0400: default locale for the user or process. See WIN32OLE.locale + * and WIN32OLE.locale=. + */ + rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", INT2FIX(LOCALE_USER_DEFAULT)); + + Init_win32ole_variant_m(); + Init_win32ole_typelib(); + Init_win32ole_type(); + Init_win32ole_variable(); + Init_win32ole_method(); + Init_win32ole_param(); + Init_win32ole_event(); + Init_win32ole_variant(); + Init_win32ole_record(); + Init_win32ole_error(); + + init_enc2cp(); + atexit((void (*)(void))free_enc2cp); + ole_init_cp(); +} diff --git a/jni/ruby/ext/win32ole/win32ole.h b/jni/ruby/ext/win32ole/win32ole.h new file mode 100644 index 0000000..d61f5e2 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole.h @@ -0,0 +1,155 @@ +#ifndef WIN32OLE_H +#define WIN32OLE_H 1 +#include "ruby/ruby.h" +#include "ruby/st.h" +#include "ruby/encoding.h" + +#define GNUC_OLDER_3_4_4 \ + ((__GNUC__ < 3) || \ + ((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \ + ((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4))) + +#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) +#ifndef NONAMELESSUNION +#define NONAMELESSUNION 1 +#endif +#endif + +#include + +#include +#include +#include +#include +#if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE) +#include +#endif +#include +#include +#ifdef HAVE_STDARG_PROTOTYPES +#include +#define va_init_list(a,b) va_start(a,b) +#else +#include +#define va_init_list(a,b) va_start(a) +#endif +#include + +#define DOUT fprintf(stderr,"%s(%d)\n", __FILE__, __LINE__) +#define DOUTS(x) fprintf(stderr,"%s(%d):" #x "=%s\n",__FILE__, __LINE__,x) +#define DOUTMSG(x) fprintf(stderr, "%s(%d):" #x "\n",__FILE__, __LINE__) +#define DOUTI(x) fprintf(stderr, "%s(%d):" #x "=%d\n",__FILE__, __LINE__,x) +#define DOUTD(x) fprintf(stderr, "%s(%d):" #x "=%f\n",__FILE__, __LINE__,x) + +#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) +#define V_UNION1(X, Y) ((X)->u.Y) +#else +#define V_UNION1(X, Y) ((X)->Y) +#endif + +#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4) +#undef V_UNION +#define V_UNION(X,Y) ((X)->n1.n2.n3.Y) + +#undef V_VT +#define V_VT(X) ((X)->n1.n2.vt) + +#undef V_BOOL +#define V_BOOL(X) V_UNION(X,boolVal) +#endif + +#ifndef V_I1REF +#define V_I1REF(X) V_UNION(X, pcVal) +#endif + +#ifndef V_UI2REF +#define V_UI2REF(X) V_UNION(X, puiVal) +#endif + +#ifndef V_INT +#define V_INT(X) V_UNION(X, intVal) +#endif + +#ifndef V_INTREF +#define V_INTREF(X) V_UNION(X, pintVal) +#endif + +#ifndef V_UINT +#define V_UINT(X) V_UNION(X, uintVal) +#endif + +#ifndef V_UINTREF +#define V_UINTREF(X) V_UNION(X, puintVal) +#endif + +#ifdef HAVE_LONG_LONG +#define I8_2_NUM LL2NUM +#define UI8_2_NUM ULL2NUM +#define NUM2I8 NUM2LL +#define NUM2UI8 NUM2ULL +#else +#define I8_2_NUM INT2NUM +#define UI8_2_NUM UINT2NUM +#define NUM2I8 NUM2INT +#define NUM2UI8 NUM2UINT +#endif + +#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0 +#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0 +#define OLE_FREE(x) {\ + if(ole_initialized() == TRUE) {\ + if(x) {\ + OLE_RELEASE(x);\ + (x) = 0;\ + }\ + }\ +} + +#define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y))) +#define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y))) + +struct oledata { + IDispatch *pDispatch; +}; + +VALUE cWIN32OLE; +LCID cWIN32OLE_lcid; + +struct oledata *oledata_get_struct(VALUE obj); +LPWSTR ole_vstr2wc(VALUE vstr); +LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey); +LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey); +VALUE reg_enum_key(HKEY hkey, DWORD i); +VALUE reg_get_val(HKEY hkey, const char *subkey); +VALUE reg_get_val2(HKEY hkey, const char *subkey); +void ole_initialize(void); +VALUE default_inspect(VALUE self, const char *class_name); +char *ole_wc2mb(LPWSTR pw); +VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree); + +#define WC2VSTR(x) ole_wc2vstr((x), TRUE) + +BOOL ole_initialized(void); +HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); +VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); +VALUE make_inspect(const char *class_name, VALUE detail); +void ole_val2variant(VALUE val, VARIANT *var); +void ole_val2variant2(VALUE val, VARIANT *var); +void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt); +VALUE ole_variant2val(VARIANT *pvar); +HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt); +VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt); +HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib); + +#include "win32ole_variant_m.h" +#include "win32ole_typelib.h" +#include "win32ole_type.h" +#include "win32ole_variable.h" +#include "win32ole_method.h" +#include "win32ole_param.h" +#include "win32ole_event.h" +#include "win32ole_variant.h" +#include "win32ole_record.h" +#include "win32ole_error.h" + +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_error.c b/jni/ruby/ext/win32ole/win32ole_error.c new file mode 100644 index 0000000..62e69b1 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_error.c @@ -0,0 +1,83 @@ +#include "win32ole.h" + +static VALUE ole_hresult2msg(HRESULT hr); + +static VALUE +ole_hresult2msg(HRESULT hr) +{ + VALUE msg = Qnil; + char *p_msg = NULL; + char *term = NULL; + DWORD dwCount; + + char strhr[100]; + sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr); + msg = rb_str_new2(strhr); + dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, hr, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPTSTR)&p_msg, 0, NULL); + if (dwCount == 0) { + dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, hr, cWIN32OLE_lcid, + (LPTSTR)&p_msg, 0, NULL); + } + if (dwCount > 0) { + term = p_msg + strlen(p_msg); + while (p_msg < term) { + term--; + if (*term == '\r' || *term == '\n') + *term = '\0'; + else break; + } + if (p_msg[0] != '\0') { + rb_str_cat2(msg, p_msg); + } + } + LocalFree(p_msg); + return msg; +} + +void +ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...) +{ + va_list args; + VALUE msg; + VALUE err_msg; + va_init_list(args, fmt); + msg = rb_vsprintf(fmt, args); + va_end(args); + + err_msg = ole_hresult2msg(hr); + if(err_msg != Qnil) { + rb_str_cat2(msg, "\n"); + rb_str_append(msg, err_msg); + } + rb_exc_raise(rb_exc_new_str(ecs, msg)); +} + +void +Init_win32ole_error(void) +{ + /* + * Document-class: WIN32OLERuntimeError + * + * Raised when OLE processing failed. + * + * EX: + * + * obj = WIN32OLE.new("NonExistProgID") + * + * raises the exception: + * + * WIN32OLERuntimeError: unknown OLE server: `NonExistProgID' + * HRESULT error code:0x800401f3 + * Invalid class string + * + */ + eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); +} diff --git a/jni/ruby/ext/win32ole/win32ole_error.h b/jni/ruby/ext/win32ole/win32ole_error.h new file mode 100644 index 0000000..5359646 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_error.h @@ -0,0 +1,8 @@ +#ifndef WIN32OLE_ERROR_H +#define WIN32OLE_ERROR_H 1 + +VALUE eWIN32OLERuntimeError; +void ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...); +void Init_win32ole_error(void); + +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_event.c b/jni/ruby/ext/win32ole/win32ole_event.c new file mode 100644 index 0000000..105308a --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_event.c @@ -0,0 +1,1275 @@ +#include "win32ole.h" + +/* + * Document-class: WIN32OLE_EVENT + * + * WIN32OLE_EVENT objects controls OLE event. + */ + +typedef struct { + struct IEventSinkVtbl * lpVtbl; +} IEventSink, *PEVENTSINK; + +typedef struct IEventSinkVtbl IEventSinkVtbl; + +struct IEventSinkVtbl { + STDMETHOD(QueryInterface)( + PEVENTSINK, + REFIID, + LPVOID *); + STDMETHOD_(ULONG, AddRef)(PEVENTSINK); + STDMETHOD_(ULONG, Release)(PEVENTSINK); + + STDMETHOD(GetTypeInfoCount)( + PEVENTSINK, + UINT *); + STDMETHOD(GetTypeInfo)( + PEVENTSINK, + UINT, + LCID, + ITypeInfo **); + STDMETHOD(GetIDsOfNames)( + PEVENTSINK, + REFIID, + OLECHAR **, + UINT, + LCID, + DISPID *); + STDMETHOD(Invoke)( + PEVENTSINK, + DISPID, + REFIID, + LCID, + WORD, + DISPPARAMS *, + VARIANT *, + EXCEPINFO *, + UINT *); +}; + +typedef struct tagIEVENTSINKOBJ { + IEventSinkVtbl *lpVtbl; + DWORD m_cRef; + IID m_iid; + long m_event_id; + ITypeInfo *pTypeInfo; +}IEVENTSINKOBJ, *PIEVENTSINKOBJ; + +struct oleeventdata { + DWORD dwCookie; + IConnectionPoint *pConnectionPoint; + IDispatch *pDispatch; + long event_id; +}; + +static VALUE ary_ole_event; +static ID id_events; + +VALUE cWIN32OLE_EVENT; + +static BOOL g_IsEventSinkVtblInitialized = FALSE; + +static IEventSinkVtbl vtEventSink; + +void EVENTSINK_Destructor(PIEVENTSINKOBJ); +static void ole_val2ptr_variant(VALUE val, VARIANT *var); +static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams); +static VALUE hash2result(VALUE hash); +static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams); +static VALUE exec_callback(VALUE arg); +static VALUE rescue_callback(VALUE arg); +static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo); +static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2); +static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo); +static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo); +static long ole_search_event_at(VALUE ary, VALUE ev); +static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default); +static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler); +static void ole_delete_event(VALUE ary, VALUE ev); +static void oleevent_free(void *ptr); +static size_t oleevent_size(const void *ptr); +static VALUE fev_s_allocate(VALUE klass); +static VALUE ev_advise(int argc, VALUE *argv, VALUE self); +static VALUE fev_initialize(int argc, VALUE *argv, VALUE self); +static void ole_msg_loop(void); +static VALUE fev_s_msg_loop(VALUE klass); +static void add_event_call_back(VALUE obj, VALUE event, VALUE data); +static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg); +static VALUE fev_on_event(int argc, VALUE *argv, VALUE self); +static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self); +static VALUE fev_off_event(int argc, VALUE *argv, VALUE self); +static VALUE fev_unadvise(VALUE self); +static VALUE fev_set_handler(VALUE self, VALUE val); +static VALUE fev_get_handler(VALUE self); +static VALUE evs_push(VALUE ev); +static VALUE evs_delete(long i); +static VALUE evs_entry(long i); +static long evs_length(void); + + +static const rb_data_type_t oleevent_datatype = { + "win32ole_event", + {NULL, oleevent_free, oleevent_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +STDMETHODIMP EVENTSINK_Invoke( + PEVENTSINK pEventSink, + DISPID dispid, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pdispparams, + VARIANT *pvarResult, + EXCEPINFO *pexcepinfo, + UINT *puArgErr + ) { + + HRESULT hr; + BSTR bstr; + unsigned int count; + unsigned int i; + ITypeInfo *pTypeInfo; + VARIANT *pvar; + VALUE ary, obj, event, args, outargv, ev, result; + VALUE handler = Qnil; + VALUE arg[3]; + VALUE mid; + VALUE is_outarg = Qfalse; + BOOL is_default_handler = FALSE; + int state; + + PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; + pTypeInfo = pEV->pTypeInfo; + obj = evs_entry(pEV->m_event_id); + if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) { + return NOERROR; + } + + ary = rb_ivar_get(obj, id_events); + if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) { + return NOERROR; + } + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, + &bstr, 1, &count); + if (FAILED(hr)) { + return NOERROR; + } + ev = WC2VSTR(bstr); + event = ole_search_event(ary, ev, &is_default_handler); + if (RB_TYPE_P(event, T_ARRAY)) { + handler = rb_ary_entry(event, 0); + mid = rb_intern("call"); + is_outarg = rb_ary_entry(event, 3); + } else { + handler = rb_ivar_get(obj, rb_intern("handler")); + if (handler == Qnil) { + return NOERROR; + } + mid = ole_search_handler_method(handler, ev, &is_default_handler); + } + if (handler == Qnil || mid == Qnil) { + return NOERROR; + } + + args = rb_ary_new(); + if (is_default_handler) { + rb_ary_push(args, ev); + } + + /* make argument of event handler */ + for (i = 0; i < pdispparams->cArgs; ++i) { + pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; + rb_ary_push(args, ole_variant2val(pvar)); + } + outargv = Qnil; + if (is_outarg == Qtrue) { + outargv = rb_ary_new(); + rb_ary_push(args, outargv); + } + + /* + * if exception raised in event callback, + * then you receive cfp consistency error. + * to avoid this error we use begin rescue end. + * and the exception raised then error message print + * and exit ruby process by Win32OLE itself. + */ + arg[0] = handler; + arg[1] = mid; + arg[2] = args; + result = rb_protect(exec_callback, (VALUE)arg, &state); + if (state != 0) { + rescue_callback(Qnil); + } + if(RB_TYPE_P(result, T_HASH)) { + hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); + result = hash2result(result); + }else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) { + ary2ptr_dispparams(outargv, pdispparams); + } + + if (pvarResult) { + VariantInit(pvarResult); + ole_val2variant(result, pvarResult); + } + + return NOERROR; +} + +STDMETHODIMP +EVENTSINK_QueryInterface( + PEVENTSINK pEV, + REFIID iid, + LPVOID* ppv + ) { + if (IsEqualIID(iid, &IID_IUnknown) || + IsEqualIID(iid, &IID_IDispatch) || + IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) { + *ppv = pEV; + } + else { + *ppv = NULL; + return E_NOINTERFACE; + } + ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv); + return NOERROR; +} + +STDMETHODIMP_(ULONG) +EVENTSINK_AddRef( + PEVENTSINK pEV + ){ + PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; + return ++pEVObj->m_cRef; +} + +STDMETHODIMP_(ULONG) EVENTSINK_Release( + PEVENTSINK pEV + ) { + PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV; + --pEVObj->m_cRef; + if(pEVObj->m_cRef != 0) + return pEVObj->m_cRef; + EVENTSINK_Destructor(pEVObj); + return 0; +} + +STDMETHODIMP EVENTSINK_GetTypeInfoCount( + PEVENTSINK pEV, + UINT *pct + ) { + *pct = 0; + return NOERROR; +} + +STDMETHODIMP EVENTSINK_GetTypeInfo( + PEVENTSINK pEV, + UINT info, + LCID lcid, + ITypeInfo **pInfo + ) { + *pInfo = NULL; + return DISP_E_BADINDEX; +} + +STDMETHODIMP EVENTSINK_GetIDsOfNames( + PEVENTSINK pEventSink, + REFIID riid, + OLECHAR **szNames, + UINT cNames, + LCID lcid, + DISPID *pDispID + ) { + ITypeInfo *pTypeInfo; + PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; + pTypeInfo = pEV->pTypeInfo; + if (pTypeInfo) { + return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID); + } + return DISP_E_UNKNOWNNAME; +} + +PIEVENTSINKOBJ +EVENTSINK_Constructor(void) +{ + PIEVENTSINKOBJ pEv; + if (!g_IsEventSinkVtblInitialized) { + vtEventSink.QueryInterface=EVENTSINK_QueryInterface; + vtEventSink.AddRef = EVENTSINK_AddRef; + vtEventSink.Release = EVENTSINK_Release; + vtEventSink.Invoke = EVENTSINK_Invoke; + vtEventSink.GetIDsOfNames = EVENTSINK_GetIDsOfNames; + vtEventSink.GetTypeInfoCount = EVENTSINK_GetTypeInfoCount; + vtEventSink.GetTypeInfo = EVENTSINK_GetTypeInfo; + + g_IsEventSinkVtblInitialized = TRUE; + } + pEv = ALLOC_N(IEVENTSINKOBJ, 1); + if(pEv == NULL) return NULL; + pEv->lpVtbl = &vtEventSink; + pEv->m_cRef = 0; + pEv->m_event_id = 0; + pEv->pTypeInfo = NULL; + return pEv; +} + +void +EVENTSINK_Destructor( + PIEVENTSINKOBJ pEVObj + ) { + if(pEVObj != NULL) { + OLE_RELEASE(pEVObj->pTypeInfo); + free(pEVObj); + pEVObj = NULL; + } +} + +static void +ole_val2ptr_variant(VALUE val, VARIANT *var) +{ + switch (TYPE(val)) { + case T_STRING: + if (V_VT(var) == (VT_BSTR | VT_BYREF)) { + *V_BSTRREF(var) = ole_vstr2wc(val); + } + break; + case T_FIXNUM: + switch(V_VT(var)) { + case (VT_UI1 | VT_BYREF) : + *V_UI1REF(var) = NUM2CHR(val); + break; + case (VT_I2 | VT_BYREF) : + *V_I2REF(var) = (short)NUM2INT(val); + break; + case (VT_I4 | VT_BYREF) : + *V_I4REF(var) = NUM2INT(val); + break; + case (VT_R4 | VT_BYREF) : + *V_R4REF(var) = (float)NUM2INT(val); + break; + case (VT_R8 | VT_BYREF) : + *V_R8REF(var) = NUM2INT(val); + break; + default: + break; + } + break; + case T_FLOAT: + switch(V_VT(var)) { + case (VT_I2 | VT_BYREF) : + *V_I2REF(var) = (short)NUM2INT(val); + break; + case (VT_I4 | VT_BYREF) : + *V_I4REF(var) = NUM2INT(val); + break; + case (VT_R4 | VT_BYREF) : + *V_R4REF(var) = (float)NUM2DBL(val); + break; + case (VT_R8 | VT_BYREF) : + *V_R8REF(var) = NUM2DBL(val); + break; + default: + break; + } + break; + case T_BIGNUM: + if (V_VT(var) == (VT_R8 | VT_BYREF)) { + *V_R8REF(var) = rb_big2dbl(val); + } + break; + case T_TRUE: + if (V_VT(var) == (VT_BOOL | VT_BYREF)) { + *V_BOOLREF(var) = VARIANT_TRUE; + } + break; + case T_FALSE: + if (V_VT(var) == (VT_BOOL | VT_BYREF)) { + *V_BOOLREF(var) = VARIANT_FALSE; + } + break; + default: + break; + } +} + +static void +hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) +{ + BSTR *bstrs; + HRESULT hr; + UINT len, i; + VARIANT *pvar; + VALUE val; + VALUE key; + len = 0; + bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, + bstrs, pdispparams->cArgs + 1, + &len); + if (FAILED(hr)) + return; + + for (i = 0; i < len - 1; i++) { + key = WC2VSTR(bstrs[i + 1]); + val = rb_hash_aref(hash, INT2FIX(i)); + if (val == Qnil) + val = rb_hash_aref(hash, key); + if (val == Qnil) + val = rb_hash_aref(hash, rb_str_intern(key)); + pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; + ole_val2ptr_variant(val, pvar); + } +} + +static VALUE +hash2result(VALUE hash) +{ + VALUE ret = Qnil; + ret = rb_hash_aref(hash, rb_str_new2("return")); + if (ret == Qnil) + ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return"))); + return ret; +} + +static void +ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams) +{ + int i; + VALUE v; + VARIANT *pvar; + for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) { + v = rb_ary_entry(ary, i); + pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; + ole_val2ptr_variant(v, pvar); + } +} + +static VALUE +exec_callback(VALUE arg) +{ + VALUE *parg = (VALUE *)arg; + VALUE handler = parg[0]; + VALUE mid = parg[1]; + VALUE args = parg[2]; + return rb_apply(handler, mid, args); +} + +static VALUE +rescue_callback(VALUE arg) +{ + + VALUE error; + VALUE e = rb_errinfo(); + VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0); + VALUE msg = rb_funcall(e, rb_intern("message"), 0); + bt = rb_ary_entry(bt, 0); + error = rb_sprintf("%"PRIsVALUE": %"PRIsVALUE" (%s)\n", bt, msg, rb_obj_classname(e)); + rb_write_error(StringValuePtr(error)); + rb_backtrace(); + ruby_finalize(); + exit(-1); + + return Qnil; +} + +static HRESULT +find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) +{ + HRESULT hr; + IDispatch *pDispatch; + ITypeInfo *pTypeInfo; + ITypeLib *pTypeLib; + TYPEATTR *pTypeAttr; + HREFTYPE RefType; + ITypeInfo *pImplTypeInfo; + TYPEATTR *pImplTypeAttr; + + struct oledata *pole = NULL; + unsigned int index; + unsigned int count; + int type; + BSTR bstr; + char *pstr; + + BOOL is_found = FALSE; + LCID lcid = cWIN32OLE_lcid; + + pole = oledata_get_struct(ole); + + pDispatch = pole->pDispatch; + + hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); + if (FAILED(hr)) + return hr; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, + &pTypeLib, + &index); + OLE_RELEASE(pTypeInfo); + if (FAILED(hr)) + return hr; + + if (!pitf) { + hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, + piid, + ppTypeInfo); + OLE_RELEASE(pTypeLib); + return hr; + } + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (index = 0; index < count; index++) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, + index, + &pTypeInfo); + if (FAILED(hr)) + break; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + + if(FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + break; + } + if(pTypeAttr->typekind == TKIND_COCLASS) { + for (type = 0; type < pTypeAttr->cImplTypes; type++) { + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, + type, + &RefType); + if (FAILED(hr)) + break; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, + RefType, + &pImplTypeInfo); + if (FAILED(hr)) + break; + + hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, + -1, + &bstr, + NULL, NULL, NULL); + if (FAILED(hr)) { + OLE_RELEASE(pImplTypeInfo); + break; + } + pstr = ole_wc2mb(bstr); + if (strcmp(pitf, pstr) == 0) { + hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, + &pImplTypeAttr); + if (SUCCEEDED(hr)) { + is_found = TRUE; + *piid = pImplTypeAttr->guid; + if (ppTypeInfo) { + *ppTypeInfo = pImplTypeInfo; + (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); + } + pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, + pImplTypeAttr); + } + } + free(pstr); + OLE_RELEASE(pImplTypeInfo); + if (is_found || FAILED(hr)) + break; + } + } + + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + OLE_RELEASE(pTypeInfo); + if (is_found || FAILED(hr)) + break; + } + OLE_RELEASE(pTypeLib); + if(!is_found) + return E_NOINTERFACE; + return hr; +} + +static HRESULT +find_coclass( + ITypeInfo *pTypeInfo, + TYPEATTR *pTypeAttr, + ITypeInfo **pCOTypeInfo, + TYPEATTR **pCOTypeAttr) +{ + HRESULT hr = E_NOINTERFACE; + ITypeLib *pTypeLib; + int count; + BOOL found = FALSE; + ITypeInfo *pTypeInfo2; + TYPEATTR *pTypeAttr2; + int flags; + int i,j; + HREFTYPE href; + ITypeInfo *pRefTypeInfo; + TYPEATTR *pRefTypeAttr; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); + if (FAILED(hr)) { + return hr; + } + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (i = 0; i < count && !found; i++) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); + if (FAILED(hr)) + continue; + hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); + if (FAILED(hr)) { + OLE_RELEASE(pTypeInfo2); + continue; + } + if (pTypeAttr2->typekind != TKIND_COCLASS) { + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + continue; + } + for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { + hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); + if (FAILED(hr)) + continue; + if (!(flags & IMPLTYPEFLAG_FDEFAULT)) + continue; + hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); + if (FAILED(hr)) + continue; + hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); + if (FAILED(hr)) { + OLE_RELEASE(pRefTypeInfo); + continue; + } + if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { + found = TRUE; + } + } + if (!found) { + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + } + } + OLE_RELEASE(pTypeLib); + if (found) { + *pCOTypeInfo = pTypeInfo2; + *pCOTypeAttr = pTypeAttr2; + hr = S_OK; + } else { + hr = E_NOINTERFACE; + } + return hr; +} + +static HRESULT +find_default_source_from_typeinfo( + ITypeInfo *pTypeInfo, + TYPEATTR *pTypeAttr, + ITypeInfo **ppTypeInfo) +{ + int i = 0; + HRESULT hr = E_NOINTERFACE; + int flags; + HREFTYPE hRefType; + /* Enumerate all implemented types of the COCLASS */ + for (i = 0; i < pTypeAttr->cImplTypes; i++) { + hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); + if (FAILED(hr)) + continue; + + /* + looking for the [default] [source] + we just hope that it is a dispinterface :-) + */ + if ((flags & IMPLTYPEFLAG_FDEFAULT) && + (flags & IMPLTYPEFLAG_FSOURCE)) { + + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, + i, &hRefType); + if (FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, + hRefType, ppTypeInfo); + if (SUCCEEDED(hr)) + break; + } + } + return hr; +} + +static HRESULT +find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) +{ + HRESULT hr; + IProvideClassInfo2 *pProvideClassInfo2; + IProvideClassInfo *pProvideClassInfo; + void *p; + + IDispatch *pDispatch; + ITypeInfo *pTypeInfo; + ITypeInfo *pTypeInfo2 = NULL; + TYPEATTR *pTypeAttr; + TYPEATTR *pTypeAttr2 = NULL; + + struct oledata *pole = NULL; + + pole = oledata_get_struct(ole); + pDispatch = pole->pDispatch; + hr = pDispatch->lpVtbl->QueryInterface(pDispatch, + &IID_IProvideClassInfo2, + &p); + if (SUCCEEDED(hr)) { + pProvideClassInfo2 = p; + hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, + GUIDKIND_DEFAULT_SOURCE_DISP_IID, + piid); + OLE_RELEASE(pProvideClassInfo2); + if (SUCCEEDED(hr)) { + hr = find_iid(ole, NULL, piid, ppTypeInfo); + } + } + if (SUCCEEDED(hr)) { + return hr; + } + hr = pDispatch->lpVtbl->QueryInterface(pDispatch, + &IID_IProvideClassInfo, + &p); + if (SUCCEEDED(hr)) { + pProvideClassInfo = p; + hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, + &pTypeInfo); + OLE_RELEASE(pProvideClassInfo); + } + if (FAILED(hr)) { + hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); + } + if (FAILED(hr)) + return hr; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + return hr; + } + + *ppTypeInfo = 0; + hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); + if (!*ppTypeInfo) { + hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); + if (SUCCEEDED(hr)) { + hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); + OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); + OLE_RELEASE(pTypeInfo2); + } + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + OLE_RELEASE(pTypeInfo); + /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ + if (!*ppTypeInfo) { + if (SUCCEEDED(hr)) + hr = E_UNEXPECTED; + return hr; + } + + /* Determine IID of default source interface */ + hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); + if (SUCCEEDED(hr)) { + *piid = pTypeAttr->guid; + (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); + } + else + OLE_RELEASE(*ppTypeInfo); + + return hr; +} + +static long +ole_search_event_at(VALUE ary, VALUE ev) +{ + VALUE event; + VALUE event_name; + long i, len; + long ret = -1; + len = RARRAY_LEN(ary); + for(i = 0; i < len; i++) { + event = rb_ary_entry(ary, i); + event_name = rb_ary_entry(event, 1); + if(NIL_P(event_name) && NIL_P(ev)) { + ret = i; + break; + } + else if (RB_TYPE_P(ev, T_STRING) && + RB_TYPE_P(event_name, T_STRING) && + rb_str_cmp(ev, event_name) == 0) { + ret = i; + break; + } + } + return ret; +} + +static VALUE +ole_search_event(VALUE ary, VALUE ev, BOOL *is_default) +{ + VALUE event; + VALUE def_event; + VALUE event_name; + int i, len; + *is_default = FALSE; + def_event = Qnil; + len = RARRAY_LEN(ary); + for(i = 0; i < len; i++) { + event = rb_ary_entry(ary, i); + event_name = rb_ary_entry(event, 1); + if(NIL_P(event_name)) { + *is_default = TRUE; + def_event = event; + } + else if (rb_str_cmp(ev, event_name) == 0) { + *is_default = FALSE; + return event; + } + } + return def_event; +} + +static VALUE +ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler) +{ + VALUE mid; + + *is_default_handler = FALSE; + mid = rb_to_id(rb_sprintf("on%"PRIsVALUE, ev)); + if (rb_respond_to(handler, mid)) { + return mid; + } + mid = rb_intern("method_missing"); + if (rb_respond_to(handler, mid)) { + *is_default_handler = TRUE; + return mid; + } + return Qnil; +} + +static void +ole_delete_event(VALUE ary, VALUE ev) +{ + long at = -1; + at = ole_search_event_at(ary, ev); + if (at >= 0) { + rb_ary_delete_at(ary, at); + } +} + + +static void +oleevent_free(void *ptr) +{ + struct oleeventdata *poleev = ptr; + if (poleev->pConnectionPoint) { + poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); + OLE_RELEASE(poleev->pConnectionPoint); + poleev->pConnectionPoint = NULL; + } + OLE_RELEASE(poleev->pDispatch); + free(poleev); +} + +static size_t +oleevent_size(const void *ptr) +{ + return ptr ? sizeof(struct oleeventdata) : 0; +} + +static VALUE +fev_s_allocate(VALUE klass) +{ + VALUE obj; + struct oleeventdata *poleev; + obj = TypedData_Make_Struct(klass, struct oleeventdata, &oleevent_datatype, poleev); + poleev->dwCookie = 0; + poleev->pConnectionPoint = NULL; + poleev->event_id = 0; + poleev->pDispatch = NULL; + return obj; +} + +static VALUE +ev_advise(int argc, VALUE *argv, VALUE self) +{ + + VALUE ole, itf; + struct oledata *pole = NULL; + char *pitf; + HRESULT hr; + IID iid; + ITypeInfo *pTypeInfo = 0; + IDispatch *pDispatch; + IConnectionPointContainer *pContainer; + IConnectionPoint *pConnectionPoint; + IEVENTSINKOBJ *pIEV; + DWORD dwCookie; + struct oleeventdata *poleev; + void *p; + + rb_scan_args(argc, argv, "11", &ole, &itf); + + if (!rb_obj_is_kind_of(ole, cWIN32OLE)) { + rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object"); + } + + if(!RB_TYPE_P(itf, T_NIL)) { + pitf = StringValuePtr(itf); + if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) { + rb_raise(rb_eSecurityError, "insecure event creation - `%s'", + StringValuePtr(itf)); + } + hr = find_iid(ole, pitf, &iid, &pTypeInfo); + } + else { + hr = find_default_source(ole, &iid, &pTypeInfo); + } + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "interface not found"); + } + + pole = oledata_get_struct(ole); + pDispatch = pole->pDispatch; + hr = pDispatch->lpVtbl->QueryInterface(pDispatch, + &IID_IConnectionPointContainer, + &p); + if (FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + ole_raise(hr, rb_eRuntimeError, + "failed to query IConnectionPointContainer"); + } + pContainer = p; + + hr = pContainer->lpVtbl->FindConnectionPoint(pContainer, + &iid, + &pConnectionPoint); + OLE_RELEASE(pContainer); + if (FAILED(hr)) { + OLE_RELEASE(pTypeInfo); + ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint"); + } + pIEV = EVENTSINK_Constructor(); + pIEV->m_iid = iid; + hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint, + (IUnknown*)pIEV, + &dwCookie); + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "Advise Error"); + } + + TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev); + pIEV->m_event_id = evs_length(); + pIEV->pTypeInfo = pTypeInfo; + poleev->dwCookie = dwCookie; + poleev->pConnectionPoint = pConnectionPoint; + poleev->event_id = pIEV->m_event_id; + poleev->pDispatch = pDispatch; + OLE_ADDREF(pDispatch); + + return self; +} + +/* + * call-seq: + * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object. + * + * Returns OLE event object. + * The first argument specifies WIN32OLE object. + * The second argument specifies OLE event name. + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') + */ +static VALUE +fev_initialize(int argc, VALUE *argv, VALUE self) +{ + ev_advise(argc, argv, self); + evs_push(self); + rb_ivar_set(self, id_events, rb_ary_new()); + fev_set_handler(self, Qnil); + return self; +} + +static void +ole_msg_loop(void) +{ + MSG msg; + while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +/* + * call-seq: + * WIN32OLE_EVENT.message_loop + * + * Translates and dispatches Windows message. + */ +static VALUE +fev_s_msg_loop(VALUE klass) +{ + ole_msg_loop(); + return Qnil; +} + +static void +add_event_call_back(VALUE obj, VALUE event, VALUE data) +{ + VALUE events = rb_ivar_get(obj, id_events); + if (NIL_P(events) || !RB_TYPE_P(events, T_ARRAY)) { + events = rb_ary_new(); + rb_ivar_set(obj, id_events, events); + } + ole_delete_event(events, event); + rb_ary_push(events, data); +} + +static VALUE +ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) +{ + struct oleeventdata *poleev; + VALUE event, args, data; + TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev); + if (poleev->pConnectionPoint == NULL) { + rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first."); + } + rb_scan_args(argc, argv, "01*", &event, &args); + if(!NIL_P(event)) { + if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) { + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + if (RB_TYPE_P(event, T_SYMBOL)) { + event = rb_sym_to_s(event); + } + } + data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg); + add_event_call_back(self, event, data); + return Qnil; +} + +/* + * call-seq: + * WIN32OLE_EVENT#on_event([event]){...} + * + * Defines the callback event. + * If argument is omitted, this method defines the callback of all events. + * If you want to modify reference argument in callback, return hash in + * callback. If you want to return value to OLE server as result of callback + * use `return' or :return. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event("NavigateComplete") {|url| puts url} + * ev.on_event() {|ev, *args| puts "#{ev} fired"} + * + * ev.on_event("BeforeNavigate2") {|*args| + * ... + * # set true to BeforeNavigate reference argument `Cancel'. + * # Cancel is 7-th argument of BeforeNavigate, + * # so you can use 6 as key of hash instead of 'Cancel'. + * # The argument is counted from 0. + * # The hash key of 0 means first argument.) + * {:Cancel => true} # or {'Cancel' => true} or {6 => true} + * } + * + * ev.on_event(...) {|*args| + * {:return => 1, :xxx => yyy} + * } + */ +static VALUE +fev_on_event(int argc, VALUE *argv, VALUE self) +{ + return ev_on_event(argc, argv, self, Qfalse); +} + +/* + * call-seq: + * WIN32OLE_EVENT#on_event_with_outargs([event]){...} + * + * Defines the callback of event. + * If you want modify argument in callback, + * you could use this method instead of WIN32OLE_EVENT#on_event. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event_with_outargs('BeforeNavigate2') {|*args| + * args.last[6] = true + * } + */ +static VALUE +fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) +{ + return ev_on_event(argc, argv, self, Qtrue); +} + +/* + * call-seq: + * WIN32OLE_EVENT#off_event([event]) + * + * removes the callback of event. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event('BeforeNavigate2') {|*args| + * args.last[6] = true + * } + * ... + * ev.off_event('BeforeNavigate2') + * ... + */ +static VALUE +fev_off_event(int argc, VALUE *argv, VALUE self) +{ + VALUE event = Qnil; + VALUE events; + + rb_scan_args(argc, argv, "01", &event); + if(!NIL_P(event)) { + if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) { + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + if (RB_TYPE_P(event, T_SYMBOL)) { + event = rb_sym_to_s(event); + } + } + events = rb_ivar_get(self, id_events); + if (NIL_P(events)) { + return Qnil; + } + ole_delete_event(events, event); + return Qnil; +} + +/* + * call-seq: + * WIN32OLE_EVENT#unadvise -> nil + * + * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object + * does not receive the OLE server event any more. + * This method is trial implementation. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event() {...} + * ... + * ev.unadvise + * + */ +static VALUE +fev_unadvise(VALUE self) +{ + struct oleeventdata *poleev; + TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev); + if (poleev->pConnectionPoint) { + ole_msg_loop(); + evs_delete(poleev->event_id); + poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); + OLE_RELEASE(poleev->pConnectionPoint); + poleev->pConnectionPoint = NULL; + } + OLE_FREE(poleev->pDispatch); + return Qnil; +} + +static VALUE +evs_push(VALUE ev) +{ + return rb_ary_push(ary_ole_event, ev); +} + +static VALUE +evs_delete(long i) +{ + rb_ary_store(ary_ole_event, i, Qnil); + return Qnil; +} + +static VALUE +evs_entry(long i) +{ + return rb_ary_entry(ary_ole_event, i); +} + +static long +evs_length(void) +{ + return RARRAY_LEN(ary_ole_event); +} + +/* + * call-seq: + * WIN32OLE_EVENT#handler= + * + * sets event handler object. If handler object has onXXX + * method according to XXX event, then onXXX method is called + * when XXX event occurs. + * + * If handler object has method_missing and there is no + * method according to the event, then method_missing + * called and 1-st argument is event name. + * + * If handler object has onXXX method and there is block + * defined by WIN32OLE_EVENT#on_event('XXX'){}, + * then block is executed but handler object method is not called + * when XXX event occurs. + * + * class Handler + * def onStatusTextChange(text) + * puts "StatusTextChanged" + * end + * def onPropertyChange(prop) + * puts "PropertyChanged" + * end + * def method_missing(ev, *arg) + * puts "other event #{ev}" + * end + * end + * + * handler = Handler.new + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event("StatusTextChange") {|*args| + * puts "this block executed." + * puts "handler.onStatusTextChange method is not called." + * } + * ev.handler = handler + * + */ +static VALUE +fev_set_handler(VALUE self, VALUE val) +{ + return rb_ivar_set(self, rb_intern("handler"), val); +} + +/* + * call-seq: + * WIN32OLE_EVENT#handler + * + * returns handler object. + * + */ +static VALUE +fev_get_handler(VALUE self) +{ + return rb_ivar_get(self, rb_intern("handler")); +} + +void +Init_win32ole_event(void) +{ + ary_ole_event = rb_ary_new(); + rb_gc_register_mark_object(ary_ole_event); + id_events = rb_intern("events"); + cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject); + rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0); + rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate); + rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1); + rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1); + rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1); + rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1); + rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0); + rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1); + rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_event.h b/jni/ruby/ext/win32ole/win32ole_event.h new file mode 100644 index 0000000..f1a5aa2 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_event.h @@ -0,0 +1,6 @@ +#ifndef WIN32OLE_EVENT_H +#define WIN32OLE_EVENT_H 1 + +void Init_win32ole_event(void); + +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_method.c b/jni/ruby/ext/win32ole/win32ole_method.c new file mode 100644 index 0000000..ba8cf78 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_method.c @@ -0,0 +1,950 @@ +#include "win32ole.h" + +static void olemethod_free(void *ptr); +static size_t olemethod_size(const void *ptr); +static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name); +static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name); +static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask); +static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name); +static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method); +static VALUE folemethod_name(VALUE self); +static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_type(VALUE self); +static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_vtype(VALUE self); +static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_type_detail(VALUE self); +static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_invkind(VALUE self); +static VALUE folemethod_invoke_kind(VALUE self); +static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_visible(VALUE self); +static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name); +static VALUE folemethod_event(VALUE self); +static VALUE folemethod_event_interface(VALUE self); +static HRESULT ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); +static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpstring(VALUE self); +static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpfile(VALUE self); +static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpcontext(VALUE self); +static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_dispid(VALUE self); +static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_offset_vtbl(VALUE self); +static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_size_params(VALUE self); +static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_size_opt_params(VALUE self); +static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_params(VALUE self); +static VALUE folemethod_inspect(VALUE self); + +static const rb_data_type_t olemethod_datatype = { + "win32ole_method", + {NULL, olemethod_free, olemethod_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static void +olemethod_free(void *ptr) +{ + struct olemethoddata *polemethod = ptr; + OLE_FREE(polemethod->pTypeInfo); + OLE_FREE(polemethod->pOwnerTypeInfo); + free(polemethod); +} + +static size_t +olemethod_size(const void *ptr) +{ + return ptr ? sizeof(struct olemethoddata) : 0; +} + +struct olemethoddata * +olemethod_data_get_struct(VALUE obj) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(obj, struct olemethoddata, &olemethod_datatype, pmethod); + return pmethod; +} + +static VALUE +ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + BSTR bstr; + FUNCDESC *pFuncDesc; + WORD i; + VALUE fname; + VALUE method = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + } + for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); + if (FAILED(hr)) + continue; + + hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) { + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + continue; + } + fname = WC2VSTR(bstr); + if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { + olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); + method = self; + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + pFuncDesc=NULL; + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return method; +} + +VALUE +ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + WORD i; + HREFTYPE href; + ITypeInfo *pRefTypeInfo; + VALUE methods = rb_ary_new(); + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + } + + ole_methods_sub(0, pTypeInfo, methods, mask); + for(i=0; i < pTypeAttr->cImplTypes; i++){ + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); + if(FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); + OLE_RELEASE(pRefTypeInfo); + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return methods; +} + +static VALUE +olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + WORD i; + HREFTYPE href; + ITypeInfo *pRefTypeInfo; + VALUE method = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + } + method = ole_method_sub(self, 0, pTypeInfo, name); + if (method != Qnil) { + return method; + } + for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); + if(FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); + OLE_RELEASE(pRefTypeInfo); + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return method; +} + +static VALUE +ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + BSTR bstr; + FUNCDESC *pFuncDesc; + VALUE method; + WORD i; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + } + for(i = 0; i < pTypeAttr->cFuncs; i++) { + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); + if (FAILED(hr)) + continue; + + hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) { + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + continue; + } + if(pFuncDesc->invkind & mask) { + method = folemethod_s_allocate(cWIN32OLE_METHOD); + olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, + i, WC2VSTR(bstr)); + rb_ary_push(methods, method); + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + pFuncDesc=NULL; + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + + return methods; +} + +VALUE +create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name) +{ + + VALUE method = folemethod_s_allocate(cWIN32OLE_METHOD); + VALUE obj = olemethod_from_typeinfo(method, pTypeInfo, name); + return obj; +} + +/* + * Document-class: WIN32OLE_METHOD + * + * WIN32OLE_METHOD objects represent OLE method information. + */ + +static VALUE +olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + pmethod->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pmethod->pOwnerTypeInfo = pOwnerTypeInfo; + OLE_ADDREF(pOwnerTypeInfo); + pmethod->index = index; + rb_ivar_set(self, rb_intern("name"), name); + return self; +} + +VALUE +folemethod_s_allocate(VALUE klass) +{ + struct olemethoddata *pmethod; + VALUE obj; + obj = TypedData_Make_Struct(klass, + struct olemethoddata, + &olemethod_datatype, pmethod); + pmethod->pTypeInfo = NULL; + pmethod->pOwnerTypeInfo = NULL; + pmethod->index = 0; + return obj; +} + +/* + * call-seq: + * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object + * + * Returns a new WIN32OLE_METHOD object which represents the information + * about OLE method. + * The first argument ole_type specifies WIN32OLE_TYPE object. + * The second argument method specifies OLE method name defined OLE class + * which represents WIN32OLE_TYPE object. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + */ +static VALUE +folemethod_initialize(VALUE self, VALUE oletype, VALUE method) +{ + VALUE obj = Qnil; + ITypeInfo *pTypeInfo; + if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { + SafeStringValue(method); + pTypeInfo = itypeinfo(oletype); + obj = olemethod_from_typeinfo(self, pTypeInfo, method); + if (obj == Qnil) { + rb_raise(eWIN32OLERuntimeError, "not found %s", + StringValuePtr(method)); + } + } + else { + rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); + } + return obj; +} + +/* + * call-seq + * WIN32OLE_METHOD#name + * + * Returns the name of the method. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.name # => SaveAs + * + */ +static VALUE +folemethod_name(VALUE self) +{ + return rb_ivar_get(self, rb_intern("name")); +} + +static VALUE +ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE type; + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + + type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_type + * + * Returns string of return value type of method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.return_type # => Workbook + * + */ +static VALUE +folemethod_return_type(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE vvt; + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + + vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return vvt; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_vtype + * + * Returns number of return value type of method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.return_vtype # => 26 + * + */ +static VALUE +folemethod_return_vtype(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE type = rb_ary_new(); + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return type; + + ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_type_detail + * + * Returns detail information of return value type of method. + * The information is array. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] + */ +static VALUE +folemethod_return_type_detail(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE invkind; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if(FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + invkind = INT2FIX(pFuncDesc->invkind); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return invkind; +} + +static VALUE +ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) +{ + VALUE type = rb_str_new2("UNKNOWN"); + VALUE invkind = ole_method_invkind(pTypeInfo, method_index); + if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && + (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { + type = rb_str_new2("PROPERTY"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { + type = rb_str_new2("PROPERTYGET"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { + type = rb_str_new2("PROPERTYPUT"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { + type = rb_str_new2("PROPERTYPUTREF"); + } else if(FIX2INT(invkind) & INVOKE_FUNC) { + type = rb_str_new2("FUNC"); + } + return type; +} + +/* + * call-seq: + * WIN32OLE_MTHOD#invkind + * + * Returns the method invoke kind. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.invkind # => 1 + * + */ +static VALUE +folemethod_invkind(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); +} + +/* + * call-seq: + * WIN32OLE_METHOD#invoke_kind + * + * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" + * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" + * or "FUNC". + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.invoke_kind # => "FUNC" + */ +static VALUE +folemethod_invoke_kind(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE visible; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if(FAILED(hr)) + return Qfalse; + if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | + FUNCFLAG_FHIDDEN | + FUNCFLAG_FNONBROWSABLE)) { + visible = Qfalse; + } else { + visible = Qtrue; + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return visible; +} + +/* + * call-seq: + * WIN32OLE_METHOD#visible? + * + * Returns true if the method is public. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.visible? # => true + */ +static VALUE +folemethod_visible(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_visible(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) +{ + TYPEATTR *pTypeAttr; + HRESULT hr; + WORD i; + int flags; + HREFTYPE href; + ITypeInfo *pRefTypeInfo; + FUNCDESC *pFuncDesc; + BSTR bstr; + VALUE name; + VALUE event = Qfalse; + + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + return event; + if(pTypeAttr->typekind != TKIND_COCLASS) { + pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); + return event; + } + for (i = 0; i < pTypeAttr->cImplTypes; i++) { + hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); + if (FAILED(hr)) + continue; + + if (flags & IMPLTYPEFLAG_FSOURCE) { + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, + i, &href); + if (FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, + href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, + &pFuncDesc); + if (FAILED(hr)) { + OLE_RELEASE(pRefTypeInfo); + continue; + } + + hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, + pFuncDesc->memid, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) { + pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); + OLE_RELEASE(pRefTypeInfo); + continue; + } + + name = WC2VSTR(bstr); + pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); + OLE_RELEASE(pRefTypeInfo); + if (rb_str_cmp(method_name, name) == 0) { + event = Qtrue; + break; + } + } + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return event; +} + +/* + * call-seq: + * WIN32OLE_METHOD#event? + * + * Returns true if the method is event. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') + * puts method.event? # => true + * + */ +static VALUE +folemethod_event(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + if (!pmethod->pOwnerTypeInfo) + return Qfalse; + return ole_method_event(pmethod->pOwnerTypeInfo, + pmethod->index, + rb_ivar_get(self, rb_intern("name"))); +} + +/* + * call-seq: + * WIN32OLE_METHOD#event_interface + * + * Returns event interface name if the method is event. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') + * puts method.event_interface # => WorkbookEvents + */ +static VALUE +folemethod_event_interface(VALUE self) +{ + BSTR name; + struct olemethoddata *pmethod; + HRESULT hr; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + if(folemethod_event(self) == Qtrue) { + hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL); + if(SUCCEEDED(hr)) + return WC2VSTR(name); + } + return Qnil; +} + +static HRESULT +ole_method_docinfo_from_type( + ITypeInfo *pTypeInfo, + UINT method_index, + BSTR *name, + BSTR *helpstr, + DWORD *helpcontext, + BSTR *helpfile + ) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return hr; + hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, + name, helpstr, + helpcontext, helpfile); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return hr; +} + +static VALUE +ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) +{ + HRESULT hr; + BSTR bhelpstring; + hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, + NULL, NULL); + if (FAILED(hr)) + return Qnil; + return WC2VSTR(bhelpstring); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpstring + * + * Returns help string of OLE method. If the help string is not found, + * then the method returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') + * method = WIN32OLE_METHOD.new(tobj, 'Navigate') + * puts method.helpstring # => Navigates to a URL or file. + * + */ +static VALUE +folemethod_helpstring(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) +{ + HRESULT hr; + BSTR bhelpfile; + hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, + NULL, &bhelpfile); + if (FAILED(hr)) + return Qnil; + return WC2VSTR(bhelpfile); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpfile + * + * Returns help file. If help file is not found, then + * the method returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.helpfile # => C:\...\VBAXL9.CHM + */ +static VALUE +folemethod_helpfile(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + + return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) +{ + HRESULT hr; + DWORD helpcontext = 0; + hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, + &helpcontext, NULL); + if (FAILED(hr)) + return Qnil; + return INT2FIX(helpcontext); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpcontext + * + * Returns help context. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.helpcontext # => 65717 + */ +static VALUE +folemethod_helpcontext(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE dispid = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return dispid; + dispid = INT2NUM(pFuncDesc->memid); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return dispid; +} + +/* + * call-seq: + * WIN32OLE_METHOD#dispid + * + * Returns dispatch ID. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.dispid # => 181 + */ +static VALUE +folemethod_dispid(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE offset_vtbl = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return offset_vtbl; + offset_vtbl = INT2FIX(pFuncDesc->oVft); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return offset_vtbl; +} + +/* + * call-seq: + * WIN32OLE_METHOD#offset_vtbl + * + * Returns the offset ov VTBL. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.offset_vtbl # => 40 + */ +static VALUE +folemethod_offset_vtbl(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE size_params = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return size_params; + size_params = INT2FIX(pFuncDesc->cParams); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return size_params; +} + +/* + * call-seq: + * WIN32OLE_METHOD#size_params + * + * Returns the size of arguments of the method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.size_params # => 11 + * + */ +static VALUE +folemethod_size_params(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE size_opt_params = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return size_opt_params; + size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return size_opt_params; +} + +/* + * call-seq: + * WIN32OLE_METHOD#size_opt_params + * + * Returns the size of optional parameters. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.size_opt_params # => 4 + */ +static VALUE +folemethod_size_opt_params(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + BSTR *bstrs; + UINT len, i; + VALUE param; + VALUE params = rb_ary_new(); + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return params; + + len = 0; + bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, + bstrs, pFuncDesc->cParams + 1, + &len); + if (FAILED(hr)) { + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return params; + } + SysFreeString(bstrs[0]); + if (pFuncDesc->cParams > 0) { + for(i = 1; i < len; i++) { + param = create_win32ole_param(pTypeInfo, method_index, i-1, WC2VSTR(bstrs[i])); + rb_ary_push(params, param); + } + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return params; +} + +/* + * call-seq: + * WIN32OLE_METHOD#params + * + * returns array of WIN32OLE_PARAM object corresponding with method parameters. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * p method.params # => [Filename, FileFormat, Password, WriteResPassword, + * ReadOnlyRecommended, CreateBackup, AccessMode, + * ConflictResolution, AddToMru, TextCodepage, + * TextVisualLayout] + */ +static VALUE +folemethod_params(VALUE self) +{ + struct olemethoddata *pmethod; + TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); + return ole_method_params(pmethod->pTypeInfo, pmethod->index); +} + +/* + * call-seq: + * WIN32OLE_METHOD#inspect -> String + * + * Returns the method name with class name. + * + */ +static VALUE +folemethod_inspect(VALUE self) +{ + return default_inspect(self, "WIN32OLE_METHOD"); +} + +void Init_win32ole_method(void) +{ + cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); + rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); + rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); + rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); + rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); + rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); + rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); + rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); + rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); + rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); + rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); + rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); + rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); + rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); + rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); + rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); + rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); + rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); + rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); + rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); + rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); + rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_method.h b/jni/ruby/ext/win32ole/win32ole_method.h new file mode 100644 index 0000000..ff2898e --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_method.h @@ -0,0 +1,16 @@ +#ifndef WIN32OLE_METHOD_H +#define WIN32OLE_METHOD_H 1 + +struct olemethoddata { + ITypeInfo *pOwnerTypeInfo; + ITypeInfo *pTypeInfo; + UINT index; +}; + +VALUE cWIN32OLE_METHOD; +VALUE folemethod_s_allocate(VALUE klass); +VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); +VALUE create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name); +struct olemethoddata *olemethod_data_get_struct(VALUE obj); +void Init_win32ole_method(void); +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_param.c b/jni/ruby/ext/win32ole/win32ole_param.c new file mode 100644 index 0000000..31cf853 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_param.c @@ -0,0 +1,438 @@ +#include "win32ole.h" + +VALUE cWIN32OLE_PARAM; + +struct oleparamdata { + ITypeInfo *pTypeInfo; + UINT method_index; + UINT index; +}; + +static void oleparam_free(void *ptr); +static size_t oleparam_size(const void *ptr); +static VALUE foleparam_s_allocate(VALUE klass); +static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index); +static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n); +static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n); +static VALUE foleparam_name(VALUE self); +static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index); +static VALUE foleparam_ole_type(VALUE self); +static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index); +static VALUE foleparam_ole_type_detail(VALUE self); +static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask); +static VALUE foleparam_input(VALUE self); +static VALUE foleparam_output(VALUE self); +static VALUE foleparam_optional(VALUE self); +static VALUE foleparam_retval(VALUE self); +static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index); +static VALUE foleparam_default(VALUE self); +static VALUE foleparam_inspect(VALUE self); + +static const rb_data_type_t oleparam_datatype = { + "win32ole_param", + {NULL, oleparam_free, oleparam_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static void +oleparam_free(void *ptr) +{ + struct oleparamdata *pole = ptr; + OLE_FREE(pole->pTypeInfo); + free(pole); +} + +static size_t +oleparam_size(const void *ptr) +{ + return ptr ? sizeof(struct oleparamdata) : 0; +} + +VALUE +create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name) +{ + struct oleparamdata *pparam; + VALUE obj = foleparam_s_allocate(cWIN32OLE_PARAM); + TypedData_Get_Struct(obj, struct oleparamdata, &oleparam_datatype, pparam); + + pparam->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pparam->method_index = method_index; + pparam->index = index; + rb_ivar_set(obj, rb_intern("name"), name); + return obj; +} + +/* + * Document-class: WIN32OLE_PARAM + * + * WIN32OLE_PARAM objects represent param information of + * the OLE method. + */ +static VALUE +foleparam_s_allocate(VALUE klass) +{ + struct oleparamdata *pparam; + VALUE obj; + obj = TypedData_Make_Struct(klass, + struct oleparamdata, + &oleparam_datatype, pparam); + pparam->pTypeInfo = NULL; + pparam->method_index = 0; + pparam->index = 0; + return obj; +} + +static VALUE +oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + BSTR *bstrs; + UINT len; + struct oleparamdata *pparam; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc"); + + len = 0; + bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, + bstrs, pFuncDesc->cParams + 1, + &len); + if (FAILED(hr)) { + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames"); + } + SysFreeString(bstrs[0]); + if (param_index < 1 || len <= (UINT)param_index) + { + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + rb_raise(rb_eIndexError, "index of param must be in 1..%d", len); + } + + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + pparam->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pparam->method_index = method_index; + pparam->index = param_index - 1; + rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index])); + + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return self; +} + +static VALUE +oleparam_ole_param(VALUE self, VALUE olemethod, int n) +{ + struct olemethoddata *pmethod = olemethod_data_get_struct(olemethod); + return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n); +} + +/* + * call-seq: + * WIN32OLE_PARAM.new(method, n) -> WIN32OLE_PARAM object + * + * Returns WIN32OLE_PARAM object which represents OLE parameter information. + * 1st argument should be WIN32OLE_METHOD object. + * 2nd argument `n' is n-th parameter of the method specified by 1st argument. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Scripting Runtime', 'IFileSystem') + * method = WIN32OLE_METHOD.new(tobj, 'CreateTextFile') + * param = WIN32OLE_PARAM.new(method, 2) # => # + * + */ +static VALUE +foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) +{ + int idx; + if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) { + rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object"); + } + idx = FIX2INT(n); + return oleparam_ole_param(self, olemethod, idx); +} + +/* + * call-seq: + * WIN32OLE_PARAM#name + * + * Returns name. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * param1 = method.params[0] + * puts param1.name # => Filename + */ +static VALUE +foleparam_name(VALUE self) +{ + return rb_ivar_get(self, rb_intern("name")); +} + +static VALUE +ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE type = rb_str_new2("unknown type"); + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return type; + type = ole_typedesc2val(pTypeInfo, + &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_PARAM#ole_type + * + * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method). + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * param1 = method.params[0] + * puts param1.ole_type # => VARIANT + */ +static VALUE +foleparam_ole_type(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index, + pparam->index); +} + +static VALUE +ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE typedetail = rb_ary_new(); + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return typedetail; + ole_typedesc2val(pTypeInfo, + &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return typedetail; +} + +/* + * call-seq: + * WIN32OLE_PARAM#ole_type_detail + * + * Returns detail information of type of argument. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') + * method = WIN32OLE_METHOD.new(tobj, 'SumIf') + * param1 = method.params[0] + * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"] + */ +static VALUE +foleparam_ole_type_detail(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index, + pparam->index); +} + +static VALUE +ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE ret = Qfalse; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if(FAILED(hr)) + return ret; + if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask) + ret = Qtrue; + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return ret; +} + +/* + * call-seq: + * WIN32OLE_PARAM#input? + * + * Returns true if the parameter is input. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * param1 = method.params[0] + * puts param1.input? # => true + */ +static VALUE +foleparam_input(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, + pparam->index, PARAMFLAG_FIN); +} + +/* + * call-seq: + * WIN32OLE#output? + * + * Returns true if argument is output. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') + * method = WIN32OLE_METHOD.new(tobj, 'NewWindow') + * method.params.each do |param| + * puts "#{param.name} #{param.output?}" + * end + * + * The result of above script is following: + * URL false + * Flags false + * TargetFrameName false + * PostData false + * Headers false + * Processed true + */ +static VALUE +foleparam_output(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, + pparam->index, PARAMFLAG_FOUT); +} + +/* + * call-seq: + * WIN32OLE_PARAM#optional? + * + * Returns true if argument is optional. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * param1 = method.params[0] + * puts "#{param1.name} #{param1.optional?}" # => Filename true + */ +static VALUE +foleparam_optional(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, + pparam->index, PARAMFLAG_FOPT); +} + +/* + * call-seq: + * WIN32OLE_PARAM#retval? + * + * Returns true if argument is return value. + * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', + * 'DirectPlayLobbyConnection') + * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName') + * param = method.params[0] + * puts "#{param.name} #{param.retval?}" # => name true + */ +static VALUE +foleparam_retval(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index, + pparam->index, PARAMFLAG_FRETVAL); +} + +static VALUE +ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) +{ + FUNCDESC *pFuncDesc; + ELEMDESC *pElemDesc; + PARAMDESCEX * pParamDescEx; + HRESULT hr; + USHORT wParamFlags; + USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT; + VALUE defval = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return defval; + pElemDesc = &pFuncDesc->lprgelemdescParam[index]; + wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags; + if ((wParamFlags & mask) == mask) { + pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex; + defval = ole_variant2val(&pParamDescEx->varDefaultValue); + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return defval; +} + +/* + * call-seq: + * WIN32OLE_PARAM#default + * + * Returns default value. If the default value does not exist, + * this method returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * method.params.each do |param| + * if param.default + * puts "#{param.name} (= #{param.default})" + * else + * puts "#{param}" + * end + * end + * + * The above script result is following: + * Filename + * FileFormat + * Password + * WriteResPassword + * ReadOnlyRecommended + * CreateBackup + * AccessMode (= 1) + * ConflictResolution + * AddToMru + * TextCodepage + * TextVisualLayout + */ +static VALUE +foleparam_default(VALUE self) +{ + struct oleparamdata *pparam; + TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); + return ole_param_default(pparam->pTypeInfo, pparam->method_index, + pparam->index); +} + +/* + * call-seq: + * WIN32OLE_PARAM#inspect -> String + * + * Returns the parameter name with class name. If the parameter has default value, + * then returns name=value string with class name. + * + */ +static VALUE +foleparam_inspect(VALUE self) +{ + VALUE detail = foleparam_name(self); + VALUE defval = foleparam_default(self); + if (defval != Qnil) { + rb_str_cat2(detail, "="); + rb_str_concat(detail, rb_inspect(defval)); + } + return make_inspect("WIN32OLE_PARAM", detail); +} + +void +Init_win32ole_param(void) +{ + cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject); + rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); + rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2); + rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0); + rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0); + rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0); + rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0); + rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0); + rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0); + rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0); + rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0); + rb_define_alias(cWIN32OLE_PARAM, "to_s", "name"); + rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_param.h b/jni/ruby/ext/win32ole/win32ole_param.h new file mode 100644 index 0000000..7e2650c --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_param.h @@ -0,0 +1,8 @@ +#ifndef WIN32OLE_PARAM_H +#define WIN32OLE_PARAM_H + +VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name); +void Init_win32ole_param(void); + +#endif + diff --git a/jni/ruby/ext/win32ole/win32ole_record.c b/jni/ruby/ext/win32ole/win32ole_record.c new file mode 100644 index 0000000..28d6238 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_record.c @@ -0,0 +1,604 @@ +#include "win32ole.h" + +struct olerecorddata { + IRecordInfo *pri; + void *pdata; +}; + +static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri); +static int hash2olerec(VALUE key, VALUE val, VALUE rec); +static void olerecord_free(void *pvar); +static size_t olerecord_size(const void *ptr); +static VALUE folerecord_s_allocate(VALUE klass); +static VALUE folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj); +static VALUE folerecord_to_h(VALUE self); +static VALUE folerecord_typename(VALUE self); +static VALUE olerecord_ivar_get(VALUE self, VALUE name); +static VALUE olerecord_ivar_set(VALUE self, VALUE name, VALUE val); +static VALUE folerecord_method_missing(int argc, VALUE *argv, VALUE self); +static VALUE folerecord_ole_instance_variable_get(VALUE self, VALUE name); +static VALUE folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val); +static VALUE folerecord_inspect(VALUE self); + +static const rb_data_type_t olerecord_datatype = { + "win32ole_record", + {NULL, olerecord_free, olerecord_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static HRESULT +recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri) +{ + + unsigned int count; + unsigned int i; + ITypeInfo *pTypeInfo; + HRESULT hr = OLE_E_LAST; + BSTR bstr; + + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (i = 0; i < count; i++) { + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) + continue; + + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); + if (FAILED(hr)) + continue; + + if (rb_str_cmp(WC2VSTR(bstr), name) == 0) { + hr = GetRecordInfoFromTypeInfo(pTypeInfo, ppri); + OLE_RELEASE(pTypeInfo); + return hr; + } + OLE_RELEASE(pTypeInfo); + } + hr = OLE_E_LAST; + return hr; +} + +static int +hash2olerec(VALUE key, VALUE val, VALUE rec) +{ + VARIANT var; + OLECHAR *pbuf; + struct olerecorddata *prec; + IRecordInfo *pri; + HRESULT hr; + + if (val != Qnil) { + TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec); + pri = prec->pri; + VariantInit(&var); + ole_val2variant(val, &var); + pbuf = ole_vstr2wc(key); + hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, prec->pdata, pbuf, &var); + SysFreeString(pbuf); + VariantClear(&var); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to putfield of `%s`", StringValuePtr(key)); + } + } + return ST_CONTINUE; +} + +void +ole_rec2variant(VALUE rec, VARIANT *var) +{ + struct olerecorddata *prec; + ULONG size = 0; + IRecordInfo *pri; + HRESULT hr; + VALUE fields; + TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec); + pri = prec->pri; + if (pri) { + hr = pri->lpVtbl->GetSize(pri, &size); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to get size for allocation of VT_RECORD object"); + } + if (prec->pdata) { + free(prec->pdata); + } + prec->pdata = ALLOC_N(char, size); + if (!prec->pdata) { + rb_raise(rb_eRuntimeError, "failed to memory allocation of %lu bytes", (unsigned long)size); + } + hr = pri->lpVtbl->RecordInit(pri, prec->pdata); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to initialize VT_RECORD object"); + } + fields = folerecord_to_h(rec); + rb_hash_foreach(fields, hash2olerec, rec); + V_RECORDINFO(var) = pri; + V_RECORD(var) = prec->pdata; + V_VT(var) = VT_RECORD; + } else { + rb_raise(eWIN32OLERuntimeError, "failed to retrieve IRecordInfo interface"); + } +} + +void +olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec) +{ + HRESULT hr; + BSTR bstr; + BSTR *bstrs; + ULONG count = 0; + ULONG i; + VALUE fields; + VALUE val; + VARIANT var; + void *pdata = NULL; + struct olerecorddata *pvar; + + TypedData_Get_Struct(obj, struct olerecorddata, &olerecord_datatype, pvar); + OLE_ADDREF(pri); + OLE_RELEASE(pvar->pri); + pvar->pri = pri; + + hr = pri->lpVtbl->GetName(pri, &bstr); + if (SUCCEEDED(hr)) { + rb_ivar_set(obj, rb_intern("typename"), WC2VSTR(bstr)); + } + + hr = pri->lpVtbl->GetFieldNames(pri, &count, NULL); + if (FAILED(hr) || count == 0) + return; + bstrs = ALLOCA_N(BSTR, count); + hr = pri->lpVtbl->GetFieldNames(pri, &count, bstrs); + if (FAILED(hr)) { + return; + } + + fields = rb_hash_new(); + rb_ivar_set(obj, rb_intern("fields"), fields); + for (i = 0; i < count; i++) { + pdata = NULL; + VariantInit(&var); + val = Qnil; + if (prec) { + hr = pri->lpVtbl->GetFieldNoCopy(pri, prec, bstrs[i], &var, &pdata); + if (SUCCEEDED(hr)) { + val = ole_variant2val(&var); + } + } + rb_hash_aset(fields, WC2VSTR(bstrs[i]), val); + } +} + +VALUE +create_win32ole_record(IRecordInfo *pri, void *prec) +{ + VALUE obj = folerecord_s_allocate(cWIN32OLE_RECORD); + olerecord_set_ivar(obj, pri, prec); + return obj; +} + +/* + * Document-class: WIN32OLE_RECORD + * + * WIN32OLE_RECORD objects represents VT_RECORD OLE variant. + * Win32OLE returns WIN32OLE_RECORD object if the result value of invoking + * OLE methods. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure Book + * _ + * Public title As String + * Public cost As Integer + * End Structure + * Public Function getBook() As Book + * Dim book As New Book + * book.title = "The Ruby Book" + * book.cost = 20 + * Return book + * End Function + * End Class + * + * then, you can retrieve getBook return value from the following + * Ruby script: + * + * require 'win32ole' + * obj = WIN32OLE.new('ComServer.ComClass') + * book = obj.getBook + * book.class # => WIN32OLE_RECORD + * book.title # => "The Ruby Book" + * book.cost # => 20 + * + */ + +static void +olerecord_free(void *ptr) { + struct olerecorddata *pvar = ptr; + OLE_FREE(pvar->pri); + if (pvar->pdata) { + free(pvar->pdata); + } + free(pvar); +} + +static size_t +olerecord_size(const void *ptr) +{ + const struct olerecorddata *pvar = ptr; + size_t s = 0; + ULONG size = 0; + HRESULT hr; + if (ptr) { + s += sizeof(struct olerecorddata); + if (pvar->pri) { + hr = pvar->pri->lpVtbl->GetSize(pvar->pri, &size); + if (SUCCEEDED(hr)) { + s += size; + } + } + } + return s; +} + +static VALUE +folerecord_s_allocate(VALUE klass) { + VALUE obj = Qnil; + struct olerecorddata *pvar; + obj = TypedData_Make_Struct(klass, struct olerecorddata, &olerecord_datatype, pvar); + pvar->pri = NULL; + pvar->pdata = NULL; + return obj; +} + +/* + * call-seq: + * WIN32OLE_RECORD.new(typename, obj) -> WIN32OLE_RECORD object + * + * Returns WIN32OLE_RECORD object. The first argument is struct name (String + * or Symbol). + * The second parameter obj should be WIN32OLE object or WIN32OLE_TYPELIB object. + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure Book + * _ + * Public title As String + * Public cost As Integer + * End Structure + * End Class + * + * then, you can create WIN32OLE_RECORD object is as following: + * + * require 'win32ole' + * obj = WIN32OLE.new('ComServer.ComClass') + * book1 = WIN32OLE_RECORD.new('Book', obj) # => WIN32OLE_RECORD object + * tlib = obj.ole_typelib + * book2 = WIN32OLE_RECORD.new('Book', tlib) # => WIN32OLE_RECORD object + * + */ +static VALUE +folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) { + HRESULT hr; + ITypeLib *pTypeLib = NULL; + IRecordInfo *pri = NULL; + + if (!RB_TYPE_P(typename, T_STRING) && !RB_TYPE_P(typename, T_SYMBOL)) { + rb_raise(rb_eArgError, "1st argument should be String or Symbol"); + } + if (RB_TYPE_P(typename, T_SYMBOL)) { + typename = rb_sym_to_s(typename); + } + + hr = S_OK; + if(rb_obj_is_kind_of(oleobj, cWIN32OLE)) { + hr = typelib_from_val(oleobj, &pTypeLib); + } else if (rb_obj_is_kind_of(oleobj, cWIN32OLE_TYPELIB)) { + pTypeLib = itypelib(oleobj); + OLE_ADDREF(pTypeLib); + if (pTypeLib) { + hr = S_OK; + } else { + hr = E_FAIL; + } + } else { + rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE_TYPELIB object"); + } + + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to query ITypeLib interface"); + } + + hr = recordinfo_from_itypelib(pTypeLib, typename, &pri); + OLE_RELEASE(pTypeLib); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "fail to query IRecordInfo interface for `%s'", StringValuePtr(typename)); + } + + olerecord_set_ivar(self, pri, NULL); + + return self; +} + +/* + * call-seq: + * WIN32OLE_RECORD#to_h #=> Ruby Hash object. + * + * Returns Ruby Hash object which represents VT_RECORD variable. + * The keys of Hash object are member names of VT_RECORD OLE variable and + * the values of Hash object are values of VT_RECORD OLE variable. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure Book + * _ + * Public title As String + * Public cost As Integer + * End Structure + * Public Function getBook() As Book + * Dim book As New Book + * book.title = "The Ruby Book" + * book.cost = 20 + * Return book + * End Function + * End Class + * + * then, the result of WIN32OLE_RECORD#to_h is the following: + * + * require 'win32ole' + * obj = WIN32OLE.new('ComServer.ComClass') + * book = obj.getBook + * book.to_h # => {"title"=>"The Ruby Book", "cost"=>20} + * + */ +static VALUE +folerecord_to_h(VALUE self) +{ + return rb_ivar_get(self, rb_intern("fields")); +} + +/* + * call-seq: + * WIN32OLE_RECORD#typename #=> String object + * + * Returns the type name of VT_RECORD OLE variable. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure Book + * _ + * Public title As String + * Public cost As Integer + * End Structure + * Public Function getBook() As Book + * Dim book As New Book + * book.title = "The Ruby Book" + * book.cost = 20 + * Return book + * End Function + * End Class + * + * then, the result of WIN32OLE_RECORD#typename is the following: + * + * require 'win32ole' + * obj = WIN32OLE.new('ComServer.ComClass') + * book = obj.getBook + * book.typename # => "Book" + * + */ +static VALUE +folerecord_typename(VALUE self) +{ + return rb_ivar_get(self, rb_intern("typename")); +} + +static VALUE +olerecord_ivar_get(VALUE self, VALUE name) +{ + VALUE fields; + fields = rb_ivar_get(self, rb_intern("fields")); + return rb_hash_fetch(fields, name); +} + +static VALUE +olerecord_ivar_set(VALUE self, VALUE name, VALUE val) +{ + long len; + char *p; + VALUE fields; + len = RSTRING_LEN(name); + p = RSTRING_PTR(name); + if (p[len-1] == '=') { + name = rb_str_subseq(name, 0, len-1); + } + fields = rb_ivar_get(self, rb_intern("fields")); + rb_hash_fetch(fields, name); + return rb_hash_aset(fields, name, val); +} + +/* + * call-seq: + * WIN32OLE_RECORD#method_missing(name) + * + * Returns value specified by the member name of VT_RECORD OLE variable. + * Or sets value specified by the member name of VT_RECORD OLE variable. + * If the member name is not correct, KeyError exception is raised. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure Book + * _ + * Public title As String + * Public cost As Integer + * End Structure + * End Class + * + * Then getting/setting value from Ruby is as the following: + * + * obj = WIN32OLE.new('ComServer.ComClass') + * book = WIN32OLE_RECORD.new('Book', obj) + * book.title # => nil ( book.method_missing(:title) is invoked. ) + * book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. ) + */ +static VALUE +folerecord_method_missing(int argc, VALUE *argv, VALUE self) +{ + VALUE name; + rb_check_arity(argc, 1, 2); + name = rb_sym_to_s(argv[0]); + +#if SIZEOF_SIZE_T > SIZEOF_LONG + { + size_t n = strlen(StringValueCStr(name)); + if (n >= LONG_MAX) { + rb_raise(rb_eRuntimeError, "too long member name"); + } + } +#endif + + if (argc == 1) { + return olerecord_ivar_get(self, name); + } else if (argc == 2) { + return olerecord_ivar_set(self, name, argv[1]); + } + return Qnil; +} + +/* + * call-seq: + * WIN32OLE_RECORD#ole_instance_variable_get(name) + * + * Returns value specified by the member name of VT_RECORD OLE object. + * If the member name is not correct, KeyError exception is raised. + * If you can't access member variable of VT_RECORD OLE object directly, + * use this method. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * Public Structure ComObject + * Public object_id As Ineger + * End Structure + * End Class + * + * and Ruby Object class has title attribute: + * + * then accessing object_id of ComObject from Ruby is as the following: + * + * srver = WIN32OLE.new('ComServer.ComClass') + * obj = WIN32OLE_RECORD.new('ComObject', server) + * # obj.object_id returns Ruby Object#object_id + * obj.ole_instance_variable_get(:object_id) # => nil + * + */ +static VALUE +folerecord_ole_instance_variable_get(VALUE self, VALUE name) +{ + VALUE sname; + if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) { + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + sname = name; + if (RB_TYPE_P(name, T_SYMBOL)) { + sname = rb_sym_to_s(name); + } + return olerecord_ivar_get(self, sname); +} + +/* + * call-seq: + * WIN32OLE_RECORD#ole_instance_variable_set(name, val) + * + * Sets value specified by the member name of VT_RECORD OLE object. + * If the member name is not correct, KeyError exception is raised. + * If you can't set value of member of VT_RECORD OLE object directly, + * use this method. + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * _ + * Public title As String + * Public cost As Integer + * End Class + * + * then setting value of the `title' member is as following: + * + * srver = WIN32OLE.new('ComServer.ComClass') + * obj = WIN32OLE_RECORD.new('Book', server) + * obj.ole_instance_variable_set(:title, "The Ruby Book") + * + */ +static VALUE +folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val) +{ + VALUE sname; + if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) { + rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)"); + } + sname = name; + if (RB_TYPE_P(name, T_SYMBOL)) { + sname = rb_sym_to_s(name); + } + return olerecord_ivar_set(self, sname, val); +} + +/* + * call-seq: + * WIN32OLE_RECORD#inspect -> String + * + * Returns the OLE struct name and member name and the value of member + * + * If COM server in VB.NET ComServer project is the following: + * + * Imports System.Runtime.InteropServices + * Public Class ComClass + * _ + * Public title As String + * Public cost As Integer + * End Class + * + * then + * + * srver = WIN32OLE.new('ComServer.ComClass') + * obj = WIN32OLE_RECORD.new('Book', server) + * obj.inspect # => nil, "cost" => nil}> + * + */ +static VALUE +folerecord_inspect(VALUE self) +{ + VALUE tname; + VALUE field; + tname = folerecord_typename(self); + if (tname == Qnil) { + tname = rb_inspect(tname); + } + field = rb_inspect(folerecord_to_h(self)); + return rb_sprintf("#", + tname, + field); +} + +void +Init_win32ole_record(void) +{ + cWIN32OLE_RECORD = rb_define_class("WIN32OLE_RECORD", rb_cObject); + rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate); + rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2); + rb_define_method(cWIN32OLE_RECORD, "to_h", folerecord_to_h, 0); + rb_define_method(cWIN32OLE_RECORD, "typename", folerecord_typename, 0); + rb_define_method(cWIN32OLE_RECORD, "method_missing", folerecord_method_missing, -1); + rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_get", folerecord_ole_instance_variable_get, 1); + rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_set", folerecord_ole_instance_variable_set, 2); + rb_define_method(cWIN32OLE_RECORD, "inspect", folerecord_inspect, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_record.h b/jni/ruby/ext/win32ole/win32ole_record.h new file mode 100644 index 0000000..ea431e9 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_record.h @@ -0,0 +1,10 @@ +#ifndef WIN32OLE_RECORD_H +#define WIN32OLE_RECORD_H 1 + +VALUE cWIN32OLE_RECORD; +void ole_rec2variant(VALUE rec, VARIANT *var); +void olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec); +VALUE create_win32ole_record(IRecordInfo *pri, void *prec); +void Init_win32ole_record(void); + +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_type.c b/jni/ruby/ext/win32ole/win32ole_type.c new file mode 100644 index 0000000..efcac88 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_type.c @@ -0,0 +1,915 @@ +#include "win32ole.h" + +struct oletypedata { + ITypeInfo *pTypeInfo; +}; + +static void oletype_free(void *ptr); +static size_t oletype_size(const void *ptr); +static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib); +static VALUE foletype_s_typelibs(VALUE self); +static VALUE foletype_s_progids(VALUE self); +static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name); +static VALUE foletype_s_allocate(VALUE klass); +static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass); +static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass); +static VALUE foletype_name(VALUE self); +static VALUE ole_ole_type(ITypeInfo *pTypeInfo); +static VALUE foletype_ole_type(VALUE self); +static VALUE ole_type_guid(ITypeInfo *pTypeInfo); +static VALUE foletype_guid(VALUE self); +static VALUE ole_type_progid(ITypeInfo *pTypeInfo); +static VALUE foletype_progid(VALUE self); +static VALUE ole_type_visible(ITypeInfo *pTypeInfo); +static VALUE foletype_visible(VALUE self); +static VALUE ole_type_major_version(ITypeInfo *pTypeInfo); +static VALUE foletype_major_version(VALUE self); +static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo); +static VALUE foletype_minor_version(VALUE self); +static VALUE ole_type_typekind(ITypeInfo *pTypeInfo); +static VALUE foletype_typekind(VALUE self); +static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo); +static VALUE foletype_helpstring(VALUE self); +static VALUE ole_type_src_type(ITypeInfo *pTypeInfo); +static VALUE foletype_src_type(VALUE self); +static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo); +static VALUE foletype_helpfile(VALUE self); +static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo); +static VALUE foletype_helpcontext(VALUE self); +static VALUE ole_variables(ITypeInfo *pTypeInfo); +static VALUE foletype_variables(VALUE self); +static VALUE foletype_methods(VALUE self); +static VALUE foletype_ole_typelib(VALUE self); +static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags); +static VALUE foletype_impl_ole_types(VALUE self); +static VALUE foletype_source_ole_types(VALUE self); +static VALUE foletype_default_event_sources(VALUE self); +static VALUE foletype_default_ole_types(VALUE self); +static VALUE foletype_inspect(VALUE self); + +static const rb_data_type_t oletype_datatype = { + "win32ole_type", + {NULL, oletype_free, oletype_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +/* + * Document-class: WIN32OLE_TYPE + * + * WIN32OLE_TYPE objects represent OLE type libarary information. + */ + +static void +oletype_free(void *ptr) +{ + struct oletypedata *poletype = ptr; + OLE_FREE(poletype->pTypeInfo); + free(poletype); +} + +static size_t +oletype_size(const void *ptr) +{ + return ptr ? sizeof(struct oletypedata) : 0; +} + +ITypeInfo *itypeinfo(VALUE self) +{ + struct oletypedata *ptype; + TypedData_Get_Struct(self, struct oletypedata, &oletype_datatype, ptype); + return ptype->pTypeInfo; +} + +VALUE +ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) +{ + ITypeLib *pTypeLib; + VALUE type = Qnil; + HRESULT hr; + unsigned int index; + BSTR bstr; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index ); + if(FAILED(hr)) { + return Qnil; + } + hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index, + &bstr, NULL, NULL, NULL); + OLE_RELEASE(pTypeLib); + if (FAILED(hr)) { + return Qnil; + } + type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr)); + return type; +} + + +/* + * call-seq: + * WIN32OLE_TYPE.ole_classes(typelib) + * + * Returns array of WIN32OLE_TYPE objects defined by the typelib type library. + * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead. + */ +static VALUE +foletype_s_ole_classes(VALUE self, VALUE typelib) +{ + VALUE obj; + + /* + rb_warn("%s is obsolete; use %s instead.", + "WIN32OLE_TYPE.ole_classes", + "WIN32OLE_TYPELIB.new(typelib).ole_types"); + */ + obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib); + return rb_funcall(obj, rb_intern("ole_types"), 0); +} + +/* + * call-seq: + * WIN32OLE_TYPE.typelibs + * + * Returns array of type libraries. + * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead. + * + */ +static VALUE +foletype_s_typelibs(VALUE self) +{ + /* + rb_warn("%s is obsolete. use %s instead.", + "WIN32OLE_TYPE.typelibs", + "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}"); + */ + return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); +} + +/* + * call-seq: + * WIN32OLE_TYPE.progids + * + * Returns array of ProgID. + */ +static VALUE +foletype_s_progids(VALUE self) +{ + HKEY hclsids, hclsid; + DWORD i; + LONG err; + VALUE clsid; + VALUE v = rb_str_new2(""); + VALUE progids = rb_ary_new(); + + err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids); + if(err != ERROR_SUCCESS) { + return progids; + } + for(i = 0; ; i++) { + clsid = reg_enum_key(hclsids, i); + if (clsid == Qnil) + break; + err = reg_open_vkey(hclsids, clsid, &hclsid); + if (err != ERROR_SUCCESS) + continue; + if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil) + rb_ary_push(progids, v); + if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil) + rb_ary_push(progids, v); + RegCloseKey(hclsid); + } + RegCloseKey(hclsids); + return progids; +} + +static VALUE +oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name) +{ + struct oletypedata *ptype; + TypedData_Get_Struct(self, struct oletypedata, &oletype_datatype, ptype); + rb_ivar_set(self, rb_intern("name"), name); + ptype->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + return self; +} + +static VALUE +foletype_s_allocate(VALUE klass) +{ + struct oletypedata *poletype; + VALUE obj; + ole_initialize(); + obj = TypedData_Make_Struct(klass,struct oletypedata, &oletype_datatype, poletype); + poletype->pTypeInfo = NULL; + return obj; +} + +VALUE +create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name) +{ + VALUE obj = foletype_s_allocate(cWIN32OLE_TYPE); + oletype_set_member(obj, pTypeInfo, name); + return obj; +} + +static VALUE +oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) +{ + + long count; + int i; + HRESULT hr; + BSTR bstr; + VALUE typelib; + ITypeInfo *pTypeInfo; + + VALUE found = Qfalse; + + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (i = 0; i < count && found == Qfalse; i++) { + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); + if (FAILED(hr)) + continue; + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) + continue; + typelib = WC2VSTR(bstr); + if (rb_str_cmp(oleclass, typelib) == 0) { + oletype_set_member(self, pTypeInfo, typelib); + found = Qtrue; + } + OLE_RELEASE(pTypeInfo); + } + return found; +} + +/* + * call-seq: + * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object + * + * Returns a new WIN32OLE_TYPE object. + * The first argument typelib specifies OLE type library name. + * The second argument specifies OLE class name. + * + * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * # => WIN32OLE_TYPE object of Application class of Excel. + */ +static VALUE +foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) +{ + VALUE file; + OLECHAR * pbuf; + ITypeLib *pTypeLib; + HRESULT hr; + + SafeStringValue(oleclass); + SafeStringValue(typelib); + file = typelib_file(typelib); + if (file == Qnil) { + file = typelib; + } + pbuf = ole_vstr2wc(file); + hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); + SysFreeString(pbuf); + if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) { + OLE_RELEASE(pTypeLib); + rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`", + StringValuePtr(oleclass), StringValuePtr(typelib)); + } + OLE_RELEASE(pTypeLib); + return self; +} + +/* + * call-seq: + * WIN32OLE_TYPE#name #=> OLE type name + * + * Returns OLE type name. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * puts tobj.name # => Application + */ +static VALUE +foletype_name(VALUE self) +{ + return rb_ivar_get(self, rb_intern("name")); +} + +static VALUE +ole_ole_type(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + VALUE type = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if(FAILED(hr)){ + return type; + } + switch(pTypeAttr->typekind) { + case TKIND_ENUM: + type = rb_str_new2("Enum"); + break; + case TKIND_RECORD: + type = rb_str_new2("Record"); + break; + case TKIND_MODULE: + type = rb_str_new2("Module"); + break; + case TKIND_INTERFACE: + type = rb_str_new2("Interface"); + break; + case TKIND_DISPATCH: + type = rb_str_new2("Dispatch"); + break; + case TKIND_COCLASS: + type = rb_str_new2("Class"); + break; + case TKIND_ALIAS: + type = rb_str_new2("Alias"); + break; + case TKIND_UNION: + type = rb_str_new2("Union"); + break; + case TKIND_MAX: + type = rb_str_new2("Max"); + break; + default: + type = Qnil; + break; + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return type; +} + +/* + * call-seq: + * WIN32OLE_TYPE#ole_type #=> OLE type string. + * + * returns type of OLE class. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * puts tobj.ole_type # => Class + */ +static VALUE +foletype_ole_type(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_ole_type(pTypeInfo); +} + +static VALUE +ole_type_guid(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + int len; + OLECHAR bstr[80]; + VALUE guid = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + return guid; + len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); + if (len > 3) { + guid = ole_wc2vstr(bstr, FALSE); + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return guid; +} + +/* + * call-seq: + * WIN32OLE_TYPE#guid #=> GUID + * + * Returns GUID. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * puts tobj.guid # => {00024500-0000-0000-C000-000000000046} + */ +static VALUE +foletype_guid(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_guid(pTypeInfo); +} + +static VALUE +ole_type_progid(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + OLECHAR *pbuf; + VALUE progid = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + return progid; + hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf); + if (SUCCEEDED(hr)) { + progid = ole_wc2vstr(pbuf, FALSE); + CoTaskMemFree(pbuf); + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return progid; +} + +/* + * call-seq: + * WIN32OLE_TYPE#progid #=> ProgID + * + * Returns ProgID if it exists. If not found, then returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * puts tobj.progid # => Excel.Application.9 + */ +static VALUE +foletype_progid(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_progid(pTypeInfo); +} + + +static VALUE +ole_type_visible(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + VALUE visible; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + return Qtrue; + if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) { + visible = Qfalse; + } else { + visible = Qtrue; + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return visible; +} + +/* + * call-seq: + * WIN32OLE_TYPE#visible? #=> true or false + * + * Returns true if the OLE class is public. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * puts tobj.visible # => true + */ +static VALUE +foletype_visible(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_visible(pTypeInfo); +} + +static VALUE +ole_type_major_version(ITypeInfo *pTypeInfo) +{ + VALUE ver; + TYPEATTR *pTypeAttr; + HRESULT hr; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + ver = INT2FIX(pTypeAttr->wMajorVerNum); + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return ver; +} + +/* + * call-seq: + * WIN32OLE_TYPE#major_version + * + * Returns major version. + * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * puts tobj.major_version # => 8 + */ +static VALUE +foletype_major_version(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_major_version(pTypeInfo); +} + +static VALUE +ole_type_minor_version(ITypeInfo *pTypeInfo) +{ + VALUE ver; + TYPEATTR *pTypeAttr; + HRESULT hr; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + ver = INT2FIX(pTypeAttr->wMinorVerNum); + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return ver; +} + +/* + * call-seq: + * WIN32OLE_TYPE#minor_version #=> OLE minor version + * + * Returns minor version. + * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * puts tobj.minor_version # => 2 + */ +static VALUE +foletype_minor_version(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_minor_version(pTypeInfo); +} + +static VALUE +ole_type_typekind(ITypeInfo *pTypeInfo) +{ + VALUE typekind; + TYPEATTR *pTypeAttr; + HRESULT hr; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + typekind = INT2FIX(pTypeAttr->typekind); + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return typekind; +} + +/* + * call-seq: + * WIN32OLE_TYPE#typekind #=> number of type. + * + * Returns number which represents type. + * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * puts tobj.typekind # => 4 + * + */ +static VALUE +foletype_typekind(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_typekind(pTypeInfo); +} + +static VALUE +ole_type_helpstring(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + BSTR bhelpstr; + hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL); + if(FAILED(hr)) { + return Qnil; + } + return WC2VSTR(bhelpstr); +} + +/* + * call-seq: + * WIN32OLE_TYPE#helpstring #=> help string. + * + * Returns help string. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') + * puts tobj.helpstring # => Web Browser interface + */ +static VALUE +foletype_helpstring(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_helpstring(pTypeInfo); +} + +static VALUE +ole_type_src_type(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + VALUE alias = Qnil; + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) + return alias; + if(pTypeAttr->typekind != TKIND_ALIAS) { + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return alias; + } + alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil); + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return alias; +} + +/* + * call-seq: + * WIN32OLE_TYPE#src_type #=> OLE source class + * + * Returns source class when the OLE class is 'Alias'. + * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') + * puts tobj.src_type # => I4 + * + */ +static VALUE +foletype_src_type(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_src_type(pTypeInfo); +} + +static VALUE +ole_type_helpfile(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + BSTR bhelpfile; + hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile); + if(FAILED(hr)) { + return Qnil; + } + return WC2VSTR(bhelpfile); +} + +/* + * call-seq: + * WIN32OLE_TYPE#helpfile + * + * Returns helpfile path. If helpfile is not found, then returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * puts tobj.helpfile # => C:\...\VBAXL9.CHM + * + */ +static VALUE +foletype_helpfile(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_helpfile(pTypeInfo); +} + +static VALUE +ole_type_helpcontext(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + DWORD helpcontext; + hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, + &helpcontext, NULL); + if(FAILED(hr)) + return Qnil; + return INT2FIX(helpcontext); +} + +/* + * call-seq: + * WIN32OLE_TYPE#helpcontext + * + * Returns helpcontext. If helpcontext is not found, then returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * puts tobj.helpfile # => 131185 + */ +static VALUE +foletype_helpcontext(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_helpcontext(pTypeInfo); +} + +static VALUE +ole_variables(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + TYPEATTR *pTypeAttr; + WORD i; + UINT len; + BSTR bstr; + VARDESC *pVarDesc; + VALUE var; + VALUE variables = rb_ary_new(); + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); + } + + for(i = 0; i < pTypeAttr->cVars; i++) { + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); + if(FAILED(hr)) + continue; + len = 0; + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, + 1, &len); + if(FAILED(hr) || len == 0 || !bstr) + continue; + + var = create_win32ole_variable(pTypeInfo, i, WC2VSTR(bstr)); + rb_ary_push(variables, var); + + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + pVarDesc = NULL; + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return variables; +} + +/* + * call-seq: + * WIN32OLE_TYPE#variables + * + * Returns array of WIN32OLE_VARIABLE objects which represent variables + * defined in OLE class. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * vars = tobj.variables + * vars.each do |v| + * puts "#{v.name} = #{v.value}" + * end + * + * The result of above sample script is follows: + * xlChart = -4109 + * xlDialogSheet = -4116 + * xlExcel4IntlMacroSheet = 4 + * xlExcel4MacroSheet = 3 + * xlWorksheet = -4167 + * + */ +static VALUE +foletype_variables(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_variables(pTypeInfo); +} + +/* + * call-seq: + * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects. + * + * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in + * OLE type library. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * methods = tobj.ole_methods.collect{|m| + * m.name + * } + * # => ['Activate', 'Copy', 'Delete',....] + */ +static VALUE +foletype_methods(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_methods_from_typeinfo(pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF); +} + +/* + * call-seq: + * WIN32OLE_TYPE#ole_typelib + * + * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE + * object. If it is not found, then returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library' + */ +static VALUE +foletype_ole_typelib(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_typelib_from_itypeinfo(pTypeInfo); +} + +static VALUE +ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) +{ + HRESULT hr; + ITypeInfo *pRefTypeInfo; + HREFTYPE href; + WORD i; + VALUE type; + TYPEATTR *pTypeAttr; + int flags; + + VALUE types = rb_ary_new(); + hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); + if (FAILED(hr)) { + return types; + } + for (i = 0; i < pTypeAttr->cImplTypes; i++) { + hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); + if (FAILED(hr)) + continue; + + hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); + if (FAILED(hr)) + continue; + hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); + if (FAILED(hr)) + continue; + + if ((flags & implflags) == implflags) { + type = ole_type_from_itypeinfo(pRefTypeInfo); + if (type != Qnil) { + rb_ary_push(types, type); + } + } + + OLE_RELEASE(pRefTypeInfo); + } + OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); + return types; +} + +/* + * call-seq: + * WIN32OLE_TYPE#implemented_ole_types + * + * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * object. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * p tobj.implemented_ole_types # => [_Worksheet, DocEvents] + */ +static VALUE +foletype_impl_ole_types(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_impl_ole_types(pTypeInfo, 0); +} + +/* + * call-seq: + * WIN32OLE_TYPE#source_ole_types + * + * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * object and having IMPLTYPEFLAG_FSOURCE. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * p tobj.source_ole_types + * # => [#, #] + */ +static VALUE +foletype_source_ole_types(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FSOURCE); +} + +/* + * call-seq: + * WIN32OLE_TYPE#default_event_sources + * + * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * p tobj.default_event_sources # => [#] + */ +static VALUE +foletype_default_event_sources(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT); +} + +/* + * call-seq: + * WIN32OLE_TYPE#default_ole_types + * + * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * object and having IMPLTYPEFLAG_FDEFAULT. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * p tobj.default_ole_types + * # => [#, #] + */ +static VALUE +foletype_default_ole_types(VALUE self) +{ + ITypeInfo *pTypeInfo = itypeinfo(self); + return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FDEFAULT); +} + +/* + * call-seq: + * WIN32OLE_TYPE#inspect -> String + * + * Returns the type name with class name. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ie.ole_type.inspect => # + */ +static VALUE +foletype_inspect(VALUE self) +{ + return default_inspect(self, "WIN32OLE_TYPE"); +} + +void Init_win32ole_type(void) +{ + cWIN32OLE_TYPE = rb_define_class("WIN32OLE_TYPE", rb_cObject); + rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1); + rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0); + rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0); + rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate); + rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2); + rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0); + rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0); + rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0); + rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0); + rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0); + rb_define_alias(cWIN32OLE_TYPE, "to_s", "name"); + rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0); + rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0); + rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0); + rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0); + rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0); + rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0); + rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0); + rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0); + rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0); + rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0); + rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0); + rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0); + rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0); + rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0); + rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_type.h b/jni/ruby/ext/win32ole/win32ole_type.h new file mode 100644 index 0000000..a26bf3e --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_type.h @@ -0,0 +1,8 @@ +#ifndef WIN32OLE_TYPE_H +#define WIN32OLE_TYPE_H 1 +VALUE cWIN32OLE_TYPE; +VALUE create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name); +ITypeInfo *itypeinfo(VALUE self); +VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo); +void Init_win32ole_type(void); +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_typelib.c b/jni/ruby/ext/win32ole/win32ole_typelib.c new file mode 100644 index 0000000..5a431d8 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_typelib.c @@ -0,0 +1,846 @@ +#include "win32ole.h" + +struct oletypelibdata { + ITypeLib *pTypeLib; +}; + +static VALUE reg_get_typelib_file_path(HKEY hkey); +static VALUE oletypelib_path(VALUE guid, VALUE version); +static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib); +static VALUE foletypelib_s_typelibs(VALUE self); +static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib); +static void oletypelib_free(void *ptr); +static size_t oletypelib_size(const void *ptr); +static VALUE foletypelib_s_allocate(VALUE klass); +static VALUE oletypelib_search_registry(VALUE self, VALUE typelib); +static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr); +static VALUE oletypelib_search_registry2(VALUE self, VALUE args); +static VALUE foletypelib_initialize(VALUE self, VALUE args); +static VALUE foletypelib_guid(VALUE self); +static VALUE foletypelib_name(VALUE self); +static VALUE make_version_str(VALUE major, VALUE minor); +static VALUE foletypelib_version(VALUE self); +static VALUE foletypelib_major_version(VALUE self); +static VALUE foletypelib_minor_version(VALUE self); +static VALUE foletypelib_path(VALUE self); +static VALUE foletypelib_visible(VALUE self); +static VALUE foletypelib_library_name(VALUE self); +static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes); +static VALUE typelib_file_from_typelib(VALUE ole); +static VALUE typelib_file_from_clsid(VALUE ole); +static VALUE foletypelib_ole_types(VALUE self); +static VALUE foletypelib_inspect(VALUE self); + +static const rb_data_type_t oletypelib_datatype = { + "win32ole_typelib", + {NULL, oletypelib_free, oletypelib_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static VALUE +reg_get_typelib_file_path(HKEY hkey) +{ + VALUE path = Qnil; + path = reg_get_val2(hkey, "win64"); + if (path != Qnil) { + return path; + } + path = reg_get_val2(hkey, "win32"); + if (path != Qnil) { + return path; + } + path = reg_get_val2(hkey, "win16"); + return path; +} + +static VALUE +oletypelib_path(VALUE guid, VALUE version) +{ + int k; + LONG err; + HKEY hkey; + HKEY hlang; + VALUE lang; + VALUE path = Qnil; + + VALUE key = rb_str_new2("TypeLib\\"); + rb_str_concat(key, guid); + rb_str_cat2(key, "\\"); + rb_str_concat(key, version); + + err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey); + if (err != ERROR_SUCCESS) { + return Qnil; + } + for(k = 0; path == Qnil; k++) { + lang = reg_enum_key(hkey, k); + if (lang == Qnil) + break; + err = reg_open_vkey(hkey, lang, &hlang); + if (err == ERROR_SUCCESS) { + path = reg_get_typelib_file_path(hlang); + RegCloseKey(hlang); + } + } + RegCloseKey(hkey); + return path; +} + +static HRESULT +oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib) +{ + VALUE path; + OLECHAR *pBuf; + HRESULT hr; + path = oletypelib_path(guid, version); + if (path == Qnil) { + return E_UNEXPECTED; + } + pBuf = ole_vstr2wc(path); + hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib); + SysFreeString(pBuf); + return hr; +} + +ITypeLib * +itypelib(VALUE self) +{ + struct oletypelibdata *ptlib; + TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib); + return ptlib->pTypeLib; +} + +VALUE +ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo) +{ + HRESULT hr; + ITypeLib *pTypeLib; + unsigned int index; + VALUE retval = Qnil; + + hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); + if(FAILED(hr)) { + return Qnil; + } + retval = create_win32ole_typelib(pTypeLib); + return retval; +} + +/* + * Document-class: WIN32OLE_TYPELIB + * + * WIN32OLE_TYPELIB objects represent OLE tyblib information. + */ + +/* + * call-seq: + * + * WIN32OLE_TYPELIB.typelibs + * + * Returns the array of WIN32OLE_TYPELIB object. + * + * tlibs = WIN32OLE_TYPELIB.typelibs + * + */ +static VALUE +foletypelib_s_typelibs(VALUE self) +{ + HKEY htypelib, hguid; + DWORD i, j; + LONG err; + VALUE guid; + VALUE version; + VALUE name = Qnil; + VALUE typelibs = rb_ary_new(); + VALUE typelib = Qnil; + HRESULT hr; + ITypeLib *pTypeLib; + + err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); + if(err != ERROR_SUCCESS) { + return typelibs; + } + for(i = 0; ; i++) { + guid = reg_enum_key(htypelib, i); + if (guid == Qnil) + break; + err = reg_open_vkey(htypelib, guid, &hguid); + if (err != ERROR_SUCCESS) + continue; + for(j = 0; ; j++) { + version = reg_enum_key(hguid, j); + if (version == Qnil) + break; + if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) { + hr = oletypelib_from_guid(guid, version, &pTypeLib); + if (SUCCEEDED(hr)) { + typelib = create_win32ole_typelib(pTypeLib); + rb_ary_push(typelibs, typelib); + } + } + } + RegCloseKey(hguid); + } + RegCloseKey(htypelib); + return typelibs; +} + +static VALUE +oletypelib_set_member(VALUE self, ITypeLib *pTypeLib) +{ + struct oletypelibdata *ptlib; + TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib); + ptlib->pTypeLib = pTypeLib; + return self; +} + +static void +oletypelib_free(void *ptr) +{ + struct oletypelibdata *poletypelib = ptr; + OLE_FREE(poletypelib->pTypeLib); + free(poletypelib); +} + +static size_t +oletypelib_size(const void *ptr) +{ + return ptr ? sizeof(struct oletypelibdata) : 0; +} + +static VALUE +foletypelib_s_allocate(VALUE klass) +{ + struct oletypelibdata *poletypelib; + VALUE obj; + ole_initialize(); + obj = TypedData_Make_Struct(klass, struct oletypelibdata, &oletypelib_datatype, poletypelib); + poletypelib->pTypeLib = NULL; + return obj; +} + +VALUE +create_win32ole_typelib(ITypeLib *pTypeLib) +{ + VALUE obj = foletypelib_s_allocate(cWIN32OLE_TYPELIB); + oletypelib_set_member(obj, pTypeLib); + return obj; +} + +static VALUE +oletypelib_search_registry(VALUE self, VALUE typelib) +{ + HKEY htypelib, hguid, hversion; + DWORD i, j; + LONG err; + VALUE found = Qfalse; + VALUE tlib; + VALUE guid; + VALUE ver; + HRESULT hr; + ITypeLib *pTypeLib; + + err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); + if(err != ERROR_SUCCESS) { + return Qfalse; + } + for(i = 0; !found; i++) { + guid = reg_enum_key(htypelib, i); + if (guid == Qnil) + break; + err = reg_open_vkey(htypelib, guid, &hguid); + if (err != ERROR_SUCCESS) + continue; + for(j = 0; found == Qfalse; j++) { + ver = reg_enum_key(hguid, j); + if (ver == Qnil) + break; + err = reg_open_vkey(hguid, ver, &hversion); + if (err != ERROR_SUCCESS) + continue; + tlib = reg_get_val(hversion, NULL); + if (tlib == Qnil) { + RegCloseKey(hversion); + continue; + } + if (rb_str_cmp(typelib, tlib) == 0) { + hr = oletypelib_from_guid(guid, ver, &pTypeLib); + if (SUCCEEDED(hr)) { + oletypelib_set_member(self, pTypeLib); + found = Qtrue; + } + } + RegCloseKey(hversion); + } + RegCloseKey(hguid); + } + RegCloseKey(htypelib); + return found; +} + +static void +oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr) +{ + HRESULT hr; + hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, + "failed to get library attribute(TLIBATTR) from ITypeLib"); + } +} + +static VALUE +oletypelib_search_registry2(VALUE self, VALUE args) +{ + HKEY htypelib, hguid, hversion; + double fver; + DWORD j; + LONG err; + VALUE found = Qfalse; + VALUE tlib; + VALUE ver; + VALUE version_str; + VALUE version = Qnil; + VALUE typelib = Qnil; + HRESULT hr; + ITypeLib *pTypeLib; + + VALUE guid = rb_ary_entry(args, 0); + version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2)); + + err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); + if(err != ERROR_SUCCESS) { + return Qfalse; + } + err = reg_open_vkey(htypelib, guid, &hguid); + if (err != ERROR_SUCCESS) { + RegCloseKey(htypelib); + return Qfalse; + } + if (version_str != Qnil) { + err = reg_open_vkey(hguid, version_str, &hversion); + if (err == ERROR_SUCCESS) { + tlib = reg_get_val(hversion, NULL); + if (tlib != Qnil) { + typelib = tlib; + version = version_str; + } + } + RegCloseKey(hversion); + } else { + fver = 0.0; + for(j = 0; ;j++) { + ver = reg_enum_key(hguid, j); + if (ver == Qnil) + break; + err = reg_open_vkey(hguid, ver, &hversion); + if (err != ERROR_SUCCESS) + continue; + tlib = reg_get_val(hversion, NULL); + if (tlib == Qnil) { + RegCloseKey(hversion); + continue; + } + if (fver < atof(StringValuePtr(ver))) { + fver = atof(StringValuePtr(ver)); + version = ver; + typelib = tlib; + } + RegCloseKey(hversion); + } + } + RegCloseKey(hguid); + RegCloseKey(htypelib); + if (typelib != Qnil) { + hr = oletypelib_from_guid(guid, version, &pTypeLib); + if (SUCCEEDED(hr)) { + found = Qtrue; + oletypelib_set_member(self, pTypeLib); + } + } + return found; +} + + +/* + * call-seq: + * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object + * + * Returns a new WIN32OLE_TYPELIB object. + * + * The first argument typelib specifies OLE type library name or GUID or + * OLE library file. + * The second argument is major version or version of the type library. + * The third argument is minor version. + * The second argument and third argument are optional. + * If the first argument is type library name, then the second and third argument + * are ignored. + * + * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}') + * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3) + * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3) + * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") + * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library' + * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library' + * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library' + * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library' + * puts tlib5.name # -> 'Microsoft Shell Controls And Automation' + * + */ +static VALUE +foletypelib_initialize(VALUE self, VALUE args) +{ + VALUE found = Qfalse; + VALUE typelib = Qnil; + int len = 0; + OLECHAR * pbuf; + ITypeLib *pTypeLib; + HRESULT hr = S_OK; + + len = RARRAY_LEN(args); + if (len < 1 || len > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); + } + + typelib = rb_ary_entry(args, 0); + + SafeStringValue(typelib); + + found = oletypelib_search_registry(self, typelib); + if (found == Qfalse) { + found = oletypelib_search_registry2(self, args); + } + if (found == Qfalse) { + pbuf = ole_vstr2wc(typelib); + hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); + SysFreeString(pbuf); + if (SUCCEEDED(hr)) { + found = Qtrue; + oletypelib_set_member(self, pTypeLib); + } + } + + if (found == Qfalse) { + rb_raise(eWIN32OLERuntimeError, "not found type library `%s`", + StringValuePtr(typelib)); + } + return self; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#guid -> The guid string. + * + * Returns guid string which specifies type library. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}' + */ +static VALUE +foletypelib_guid(VALUE self) +{ + ITypeLib *pTypeLib; + OLECHAR bstr[80]; + VALUE guid = Qnil; + int len; + TLIBATTR *pTLibAttr; + + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR)); + if (len > 3) { + guid = ole_wc2vstr(bstr, FALSE); + } + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + return guid; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#name -> The type library name + * + * Returns the type library name. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' + */ +static VALUE +foletypelib_name(VALUE self) +{ + ITypeLib *pTypeLib; + HRESULT hr; + BSTR bstr; + VALUE name; + pTypeLib = itypelib(self); + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, + NULL, &bstr, NULL, NULL); + + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib"); + } + name = WC2VSTR(bstr); + return name; +} + +static VALUE +make_version_str(VALUE major, VALUE minor) +{ + VALUE version_str = Qnil; + VALUE minor_str = Qnil; + if (major == Qnil) { + return Qnil; + } + version_str = rb_String(major); + if (minor != Qnil) { + minor_str = rb_String(minor); + rb_str_cat2(version_str, "."); + rb_str_append(version_str, minor_str); + } + return version_str; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#version -> The type library version String object. + * + * Returns the type library version. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * puts tlib.version #-> "1.3" + */ +static VALUE +foletypelib_version(VALUE self) +{ + TLIBATTR *pTLibAttr; + ITypeLib *pTypeLib; + VALUE version; + + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + version = rb_sprintf("%d.%d", pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum); + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + return version; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#major_version -> The type library major version. + * + * Returns the type library major version. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * puts tlib.major_version # -> 1 + */ +static VALUE +foletypelib_major_version(VALUE self) +{ + TLIBATTR *pTLibAttr; + VALUE major; + ITypeLib *pTypeLib; + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + + major = INT2NUM(pTLibAttr->wMajorVerNum); + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + return major; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#minor_version -> The type library minor version. + * + * Returns the type library minor version. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * puts tlib.minor_version # -> 3 + */ +static VALUE +foletypelib_minor_version(VALUE self) +{ + TLIBATTR *pTLibAttr; + VALUE minor; + ITypeLib *pTypeLib; + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + minor = INT2NUM(pTLibAttr->wMinorVerNum); + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + return minor; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#path -> The type library file path. + * + * Returns the type library file path. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * puts tlib.path #-> 'C:\...\EXCEL9.OLB' + */ +static VALUE +foletypelib_path(VALUE self) +{ + TLIBATTR *pTLibAttr; + HRESULT hr = S_OK; + BSTR bstr; + LCID lcid = cWIN32OLE_lcid; + VALUE path; + ITypeLib *pTypeLib; + + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + hr = QueryPathOfRegTypeLib(&pTLibAttr->guid, + pTLibAttr->wMajorVerNum, + pTLibAttr->wMinorVerNum, + lcid, + &bstr); + if (FAILED(hr)) { + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib"); + } + + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + path = WC2VSTR(bstr); + return path; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#visible? + * + * Returns true if the type library information is not hidden. + * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN, + * the method returns false, otherwise, returns true. + * If the method fails to access the TLIBATTR information, then + * WIN32OLERuntimeError is raised. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib.visible? # => true + */ +static VALUE +foletypelib_visible(VALUE self) +{ + ITypeLib *pTypeLib = NULL; + VALUE visible = Qtrue; + TLIBATTR *pTLibAttr; + + pTypeLib = itypelib(self); + oletypelib_get_libattr(pTypeLib, &pTLibAttr); + + if ((pTLibAttr->wLibFlags == 0) || + (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) || + (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) { + visible = Qfalse; + } + pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); + return visible; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#library_name + * + * Returns library name. + * If the method fails to access library name, WIN32OLERuntimeError is raised. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib.library_name # => Excel + */ +static VALUE +foletypelib_library_name(VALUE self) +{ + HRESULT hr; + ITypeLib *pTypeLib = NULL; + VALUE libname = Qnil; + BSTR bstr; + + pTypeLib = itypelib(self); + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name"); + } + libname = WC2VSTR(bstr); + return libname; +} + +static VALUE +ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes) +{ + long count; + int i; + HRESULT hr; + BSTR bstr; + ITypeInfo *pTypeInfo; + VALUE type; + + count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); + for (i = 0; i < count; i++) { + hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, + &bstr, NULL, NULL, NULL); + if (FAILED(hr)) + continue; + + hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); + if (FAILED(hr)) + continue; + + type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr)); + + rb_ary_push(classes, type); + OLE_RELEASE(pTypeInfo); + } + return classes; +} + +static VALUE +typelib_file_from_typelib(VALUE ole) +{ + HKEY htypelib, hclsid, hversion, hlang; + double fver; + DWORD i, j, k; + LONG err; + BOOL found = FALSE; + VALUE typelib; + VALUE file = Qnil; + VALUE clsid; + VALUE ver; + VALUE lang; + + err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib); + if(err != ERROR_SUCCESS) { + return Qnil; + } + for(i = 0; !found; i++) { + clsid = reg_enum_key(htypelib, i); + if (clsid == Qnil) + break; + err = reg_open_vkey(htypelib, clsid, &hclsid); + if (err != ERROR_SUCCESS) + continue; + fver = 0; + for(j = 0; !found; j++) { + ver = reg_enum_key(hclsid, j); + if (ver == Qnil) + break; + err = reg_open_vkey(hclsid, ver, &hversion); + if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver))) + continue; + fver = atof(StringValuePtr(ver)); + typelib = reg_get_val(hversion, NULL); + if (typelib == Qnil) + continue; + if (rb_str_cmp(typelib, ole) == 0) { + for(k = 0; !found; k++) { + lang = reg_enum_key(hversion, k); + if (lang == Qnil) + break; + err = reg_open_vkey(hversion, lang, &hlang); + if (err == ERROR_SUCCESS) { + if ((file = reg_get_typelib_file_path(hlang)) != Qnil) + found = TRUE; + RegCloseKey(hlang); + } + } + } + RegCloseKey(hversion); + } + RegCloseKey(hclsid); + } + RegCloseKey(htypelib); + return file; +} + +static VALUE +typelib_file_from_clsid(VALUE ole) +{ + HKEY hroot, hclsid; + LONG err; + VALUE typelib; + char path[MAX_PATH + 1]; + + err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot); + if (err != ERROR_SUCCESS) { + return Qnil; + } + err = reg_open_key(hroot, StringValuePtr(ole), &hclsid); + if (err != ERROR_SUCCESS) { + RegCloseKey(hroot); + return Qnil; + } + typelib = reg_get_val2(hclsid, "InprocServer32"); + RegCloseKey(hroot); + RegCloseKey(hclsid); + if (typelib != Qnil) { + ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path)); + path[MAX_PATH] = '\0'; + typelib = rb_str_new2(path); + } + return typelib; +} + +VALUE +typelib_file(VALUE ole) +{ + VALUE file = typelib_file_from_clsid(ole); + if (file != Qnil) { + return file; + } + return typelib_file_from_typelib(ole); +} + + +/* + * call-seq: + * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library. + * + * Returns the type library file path. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...] + */ +static VALUE +foletypelib_ole_types(VALUE self) +{ + ITypeLib *pTypeLib = NULL; + VALUE classes = rb_ary_new(); + pTypeLib = itypelib(self); + ole_types_from_typelib(pTypeLib, classes); + return classes; +} + +/* + * call-seq: + * WIN32OLE_TYPELIB#inspect -> String + * + * Returns the type library name with class name. + * + * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" + */ +static VALUE +foletypelib_inspect(VALUE self) +{ + return default_inspect(self, "WIN32OLE_TYPELIB"); +} + +void +Init_win32ole_typelib(void) +{ + cWIN32OLE_TYPELIB = rb_define_class("WIN32OLE_TYPELIB", rb_cObject); + rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); + rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); + rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2); + rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0); + rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0); + rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0); + rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0); + rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0); + rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0); + rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0); + rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types"); + rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0); + rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0); + rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name"); + rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0); +} diff --git a/jni/ruby/ext/win32ole/win32ole_typelib.h b/jni/ruby/ext/win32ole/win32ole_typelib.h new file mode 100644 index 0000000..9fc117f --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_typelib.h @@ -0,0 +1,11 @@ +#ifndef WIN32OLE_TYPELIB_H +#define WIN32OLE_TYPELIB_H 1 + +VALUE cWIN32OLE_TYPELIB; + +void Init_win32ole_typelib(void); +ITypeLib * itypelib(VALUE self); +VALUE typelib_file(VALUE ole); +VALUE create_win32ole_typelib(ITypeLib *pTypeLib); +VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo); +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_variable.c b/jni/ruby/ext/win32ole/win32ole_variable.c new file mode 100644 index 0000000..dd58382 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variable.c @@ -0,0 +1,380 @@ +#include "win32ole.h" + +struct olevariabledata { + ITypeInfo *pTypeInfo; + UINT index; +}; + +static void olevariable_free(void *ptr); +static size_t olevariable_size(const void *ptr); +static VALUE folevariable_name(VALUE self); +static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_ole_type(VALUE self); +static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_ole_type_detail(VALUE self); +static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_value(VALUE self); +static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_visible(VALUE self); +static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_variable_kind(VALUE self); +static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index); +static VALUE folevariable_varkind(VALUE self); +static VALUE folevariable_inspect(VALUE self); + +static const rb_data_type_t olevariable_datatype = { + "win32ole_variable", + {NULL, olevariable_free, olevariable_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static void +olevariable_free(void *ptr) +{ + struct olevariabledata *polevar = ptr; + OLE_FREE(polevar->pTypeInfo); + free(polevar); +} + +static size_t +olevariable_size(const void *ptr) +{ + return ptr ? sizeof(struct olevariabledata) : 0; +} + +/* + * Document-class: WIN32OLE_VARIABLE + * + * WIN32OLE_VARIABLE objects represent OLE variable information. + */ + +VALUE +create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name) +{ + struct olevariabledata *pvar; + VALUE obj = TypedData_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata, + &olevariable_datatype, pvar); + pvar->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pvar->index = index; + rb_ivar_set(obj, rb_intern("name"), name); + return obj; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#name + * + * Returns the name of variable. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.name}" + * end + * + * The result of above script is following: + * xlChart + * xlDialogSheet + * xlExcel4IntlMacroSheet + * xlExcel4MacroSheet + * xlWorksheet + * + */ +static VALUE +folevariable_name(VALUE self) +{ + return rb_ivar_get(self, rb_intern("name")); +} + +static VALUE +ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE type; + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); + type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil); + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#ole_type + * + * Returns OLE type string. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.ole_type} #{variable.name}" + * end + * + * The result of above script is following: + * INT xlChart + * INT xlDialogSheet + * INT xlExcel4IntlMacroSheet + * INT xlExcel4MacroSheet + * INT xlWorksheet + * + */ +static VALUE +folevariable_ole_type(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_ole_type(pvar->pTypeInfo, pvar->index); +} + +static VALUE +ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE type = rb_ary_new(); + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc"); + ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type); + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#ole_type_detail + * + * Returns detail information of type. The information is array of type. + * + * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') + * variable = tobj.variables.find {|variable| variable.name == 'lFlags'} + * tdetail = variable.ole_type_detail + * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"] + * + */ +static VALUE +folevariable_ole_type_detail(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index); +} + +static VALUE +ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE val = Qnil; + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + return Qnil; + if(pVarDesc->varkind == VAR_CONST) + val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue)); + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + return val; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#value + * + * Returns value if value is exists. If the value does not exist, + * this method returns nil. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.name} #{variable.value}" + * end + * + * The result of above script is following: + * xlChart = -4109 + * xlDialogSheet = -4116 + * xlExcel4IntlMacroSheet = 4 + * xlExcel4MacroSheet = 3 + * xlWorksheet = -4167 + * + */ +static VALUE +folevariable_value(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_value(pvar->pTypeInfo, pvar->index); +} + +static VALUE +ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE visible = Qfalse; + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + return visible; + if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN | + VARFLAG_FRESTRICTED | + VARFLAG_FNONBROWSABLE))) { + visible = Qtrue; + } + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + return visible; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#visible? + * + * Returns true if the variable is public. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.name} #{variable.visible?}" + * end + * + * The result of above script is following: + * xlChart true + * xlDialogSheet true + * xlExcel4IntlMacroSheet true + * xlExcel4MacroSheet true + * xlWorksheet true + * + */ +static VALUE +folevariable_visible(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_visible(pvar->pTypeInfo, pvar->index); +} + +static VALUE +ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE kind = rb_str_new2("UNKNOWN"); + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + return kind; + switch(pVarDesc->varkind) { + case VAR_PERINSTANCE: + kind = rb_str_new2("PERINSTANCE"); + break; + case VAR_STATIC: + kind = rb_str_new2("STATIC"); + break; + case VAR_CONST: + kind = rb_str_new2("CONSTANT"); + break; + case VAR_DISPATCH: + kind = rb_str_new2("DISPATCH"); + break; + default: + break; + } + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + return kind; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#variable_kind + * + * Returns variable kind string. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.name} #{variable.variable_kind}" + * end + * + * The result of above script is following: + * xlChart CONSTANT + * xlDialogSheet CONSTANT + * xlExcel4IntlMacroSheet CONSTANT + * xlExcel4MacroSheet CONSTANT + * xlWorksheet CONSTANT + */ +static VALUE +folevariable_variable_kind(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_kind(pvar->pTypeInfo, pvar->index); +} + +static VALUE +ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index) +{ + VARDESC *pVarDesc; + HRESULT hr; + VALUE kind = Qnil; + hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc); + if (FAILED(hr)) + return kind; + pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); + kind = INT2FIX(pVarDesc->varkind); + return kind; +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#varkind + * + * Returns the number which represents variable kind. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * variables = tobj.variables + * variables.each do |variable| + * puts "#{variable.name} #{variable.varkind}" + * end + * + * The result of above script is following: + * xlChart 2 + * xlDialogSheet 2 + * xlExcel4IntlMacroSheet 2 + * xlExcel4MacroSheet 2 + * xlWorksheet 2 + */ +static VALUE +folevariable_varkind(VALUE self) +{ + struct olevariabledata *pvar; + TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar); + return ole_variable_varkind(pvar->pTypeInfo, pvar->index); +} + +/* + * call-seq: + * WIN32OLE_VARIABLE#inspect -> String + * + * Returns the OLE variable name and the value with class name. + * + */ +static VALUE +folevariable_inspect(VALUE self) +{ + VALUE v = rb_inspect(folevariable_value(self)); + VALUE n = folevariable_name(self); + VALUE detail = rb_sprintf("%"PRIsVALUE"=%"PRIsVALUE, n, v); + return make_inspect("WIN32OLE_VARIABLE", detail); +} + +void Init_win32ole_variable(void) +{ + cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject); + rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0); + rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0); + rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0); + rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0); + rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0); + rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0); + rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0); + rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0); + rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name"); +} diff --git a/jni/ruby/ext/win32ole/win32ole_variable.h b/jni/ruby/ext/win32ole/win32ole_variable.h new file mode 100644 index 0000000..704dc13 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variable.h @@ -0,0 +1,8 @@ +#ifndef WIN32OLE_VARIABLE_H +#define WIN32OLE_VARIABLE_H 1 + +VALUE cWIN32OLE_VARIABLE; +VALUE create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name); +void Init_win32ole_variable(void); + +#endif diff --git a/jni/ruby/ext/win32ole/win32ole_variant.c b/jni/ruby/ext/win32ole/win32ole_variant.c new file mode 100644 index 0000000..1731ab7 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variant.c @@ -0,0 +1,734 @@ +#include "win32ole.h" + +struct olevariantdata { + VARIANT realvar; + VARIANT var; +}; + +static void olevariant_free(void *ptr); +static size_t olevariant_size(const void *ptr); +static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar); +static void ole_val2variant_err(VALUE val, VARIANT *var); +static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt); +static VALUE folevariant_s_allocate(VALUE klass); +static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt); +static void check_type_val2variant(VALUE val); +static VALUE folevariant_initialize(VALUE self, VALUE args); +static LONG *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa); +static void unlock_safe_array(SAFEARRAY *psa); +static SAFEARRAY *get_locked_safe_array(VALUE val); +static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self); +static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self); +static VALUE folevariant_value(VALUE self); +static VALUE folevariant_vartype(VALUE self); +static VALUE folevariant_set_value(VALUE self, VALUE val); + +static const rb_data_type_t olevariant_datatype = { + "win32ole_variant", + {NULL, olevariant_free, olevariant_size,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + +static void +olevariant_free(void *ptr) +{ + struct olevariantdata *pvar = ptr; + VariantClear(&(pvar->realvar)); + VariantClear(&(pvar->var)); + free(pvar); +} + +static size_t +olevariant_size(const void *ptr) +{ + return ptr ? sizeof(struct olevariantdata) : 0; +} + +static void +ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) +{ + HRESULT hr = S_OK; + + if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) { + long len = RSTRING_LEN(val); + void *pdest = NULL; + SAFEARRAY *p = NULL; + SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len); + if (!psa) { + rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector"); + } + hr = SafeArrayAccessData(psa, &pdest); + if (SUCCEEDED(hr)) { + memcpy(pdest, RSTRING_PTR(val), len); + SafeArrayUnaccessData(psa); + V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); + p = V_ARRAY(&(pvar->realvar)); + if (p != NULL) { + SafeArrayDestroy(p); + } + V_ARRAY(&(pvar->realvar)) = psa; + if (vt & VT_BYREF) { + V_VT(&(pvar->var)) = vt; + V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); + } else { + hr = VariantCopy(&(pvar->var), &(pvar->realvar)); + } + } else { + if (psa) + SafeArrayDestroy(psa); + } + } else if (vt & VT_ARRAY) { + if (val == Qnil) { + V_VT(&(pvar->var)) = vt; + if (vt & VT_BYREF) { + V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); + } + } else { + hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); + if (SUCCEEDED(hr)) { + if (vt & VT_BYREF) { + V_VT(&(pvar->var)) = vt; + V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); + } else { + hr = VariantCopy(&(pvar->var), &(pvar->realvar)); + } + } + } +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { + ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); + ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); + V_VT(&(pvar->var)) = vt; + if (vt & VT_BYREF) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } +#endif + } else if ( (vt & ~VT_BYREF) == VT_ERROR) { + ole_val2variant_err(val, &(pvar->realvar)); + if (vt & VT_BYREF) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } else { + hr = VariantCopy(&(pvar->var), &(pvar->realvar)); + } + } else { + if (val == Qnil) { + V_VT(&(pvar->var)) = vt; + if (vt == (VT_BYREF | VT_VARIANT)) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } else { + V_VT(&(pvar->realvar)) = vt & ~VT_BYREF; + if (vt & VT_BYREF) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } + } + } else { + ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); + if (vt == (VT_BYREF | VT_VARIANT)) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } else if (vt & VT_BYREF) { + if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) { + hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar), + cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); + } + if (SUCCEEDED(hr)) { + ole_set_byref(&(pvar->realvar), &(pvar->var), vt); + } + } else { + if (vt == V_VT(&(pvar->realvar))) { + hr = VariantCopy(&(pvar->var), &(pvar->realvar)); + } else { + hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), + cWIN32OLE_lcid, 0, vt); + } + } + } + } + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to change type"); + } +} + +static void +ole_val2variant_err(VALUE val, VARIANT *var) +{ + VALUE v = val; + if (rb_obj_is_kind_of(v, cWIN32OLE_VARIANT)) { + v = folevariant_value(v); + } + if (TYPE(v) != T_FIXNUM && TYPE(v) != T_BIGNUM && v != Qnil) { + rb_raise(eWIN32OLERuntimeError, "failed to convert VT_ERROR VARIANT:`%"PRIsVALUE"'", rb_inspect(v)); + } + V_VT(var) = VT_ERROR; + if (v != Qnil) { + V_ERROR(var) = NUM2LONG(val); + } else { + V_ERROR(var) = 0; + } +} + +static void +ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt) +{ + V_VT(var) = vt; + if (vt == (VT_VARIANT|VT_BYREF)) { + V_VARIANTREF(var) = realvar; + } else { + if (V_VT(realvar) != (vt & ~VT_BYREF)) { + rb_raise(eWIN32OLERuntimeError, "variant type mismatch"); + } + switch(vt & ~VT_BYREF) { + case VT_I1: + V_I1REF(var) = &V_I1(realvar); + break; + case VT_UI1: + V_UI1REF(var) = &V_UI1(realvar); + break; + case VT_I2: + V_I2REF(var) = &V_I2(realvar); + break; + case VT_UI2: + V_UI2REF(var) = &V_UI2(realvar); + break; + case VT_I4: + V_I4REF(var) = &V_I4(realvar); + break; + case VT_UI4: + V_UI4REF(var) = &V_UI4(realvar); + break; + case VT_R4: + V_R4REF(var) = &V_R4(realvar); + break; + case VT_R8: + V_R8REF(var) = &V_R8(realvar); + break; + +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) +#ifdef V_I8REF + case VT_I8: + V_I8REF(var) = &V_I8(realvar); + break; +#endif +#ifdef V_UI8REF + case VT_UI8: + V_UI8REF(var) = &V_UI8(realvar); + break; +#endif +#endif + case VT_INT: + V_INTREF(var) = &V_INT(realvar); + break; + + case VT_UINT: + V_UINTREF(var) = &V_UINT(realvar); + break; + + case VT_CY: + V_CYREF(var) = &V_CY(realvar); + break; + case VT_DATE: + V_DATEREF(var) = &V_DATE(realvar); + break; + case VT_BSTR: + V_BSTRREF(var) = &V_BSTR(realvar); + break; + case VT_DISPATCH: + V_DISPATCHREF(var) = &V_DISPATCH(realvar); + break; + case VT_ERROR: + V_ERRORREF(var) = &V_ERROR(realvar); + break; + case VT_BOOL: + V_BOOLREF(var) = &V_BOOL(realvar); + break; + case VT_UNKNOWN: + V_UNKNOWNREF(var) = &V_UNKNOWN(realvar); + break; + case VT_ARRAY: + V_ARRAYREF(var) = &V_ARRAY(realvar); + break; + default: + rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt); + break; + } + } +} + +static VALUE +folevariant_s_allocate(VALUE klass) +{ + struct olevariantdata *pvar; + VALUE obj; + ole_initialize(); + obj = TypedData_Make_Struct(klass, struct olevariantdata, &olevariant_datatype, pvar); + VariantInit(&(pvar->var)); + VariantInit(&(pvar->realvar)); + return obj; +} + +/* + * call-seq: + * WIN32OLE_VARIANT.array(ary, vt) + * + * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. + * The first argument should be Array object which specifies dimensions + * and each size of dimensions of OLE array. + * The second argument specifies variant type of the element of OLE array. + * + * The following create 2 dimensions OLE array. The first dimensions size + * is 3, and the second is 4. + * + * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) + * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] + * + */ +static VALUE +folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt) +{ + VALUE obj = Qnil; + VARTYPE vt; + struct olevariantdata *pvar; + SAFEARRAYBOUND *psab = NULL; + SAFEARRAY *psa = NULL; + UINT dim = 0; + UINT i = 0; + + ole_initialize(); + + vt = NUM2UINT(vvt); + vt = (vt | VT_ARRAY); + Check_Type(elems, T_ARRAY); + obj = folevariant_s_allocate(klass); + + TypedData_Get_Struct(obj, struct olevariantdata, &olevariant_datatype, pvar); + dim = RARRAY_LEN(elems); + + psab = ALLOC_N(SAFEARRAYBOUND, dim); + + if(!psab) { + rb_raise(rb_eRuntimeError, "memory allocation error"); + } + + for (i = 0; i < dim; i++) { + psab[i].cElements = FIX2INT(rb_ary_entry(elems, i)); + psab[i].lLbound = 0; + } + + psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab); + if (psa == NULL) { + if (psab) free(psab); + rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)"); + } + + V_VT(&(pvar->var)) = vt; + if (vt & VT_BYREF) { + V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); + V_ARRAY(&(pvar->realvar)) = psa; + V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); + } else { + V_ARRAY(&(pvar->var)) = psa; + } + if (psab) free(psab); + return obj; +} + +static void +check_type_val2variant(VALUE val) +{ + VALUE elem; + int len = 0; + int i = 0; + if(!rb_obj_is_kind_of(val, cWIN32OLE) && + !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) && + !rb_obj_is_kind_of(val, rb_cTime)) { + switch (TYPE(val)) { + case T_ARRAY: + len = RARRAY_LEN(val); + for(i = 0; i < len; i++) { + elem = rb_ary_entry(val, i); + check_type_val2variant(elem); + } + break; + case T_STRING: + case T_FIXNUM: + case T_BIGNUM: + case T_FLOAT: + case T_TRUE: + case T_FALSE: + case T_NIL: + break; + default: + rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s", + rb_obj_classname(val)); + } + } +} + +/* + * Document-class: WIN32OLE_VARIANT + * + * WIN32OLE_VARIANT objects represents OLE variant. + * + * Win32OLE converts Ruby object into OLE variant automatically when + * invoking OLE methods. If OLE method requires the argument which is + * different from the variant by automatic conversion of Win32OLE, you + * can convert the specfied variant type by using WIN32OLE_VARIANT class. + * + * param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4) + * oleobj.method(param) + * + * WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD + * class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed. + */ + +/* + * call-seq: + * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object. + * + * Returns Ruby object wrapping OLE variant. + * The first argument specifies Ruby object to convert OLE variant variable. + * The second argument specifies VARIANT type. + * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method + * + * shell = WIN32OLE.new("Shell.Application") + * folder = shell.NameSpace("C:\\Windows") + * item = folder.ParseName("tmp.txt") + * # You can't use Ruby String object to call FolderItem.InvokeVerb. + * # Instead, you have to use WIN32OLE_VARIANT object to call the method. + * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)") + * item.invokeVerb(shortcut) + * + */ +static VALUE +folevariant_initialize(VALUE self, VALUE args) +{ + int len = 0; + VARIANT var; + VALUE val; + VALUE vvt; + VARTYPE vt; + struct olevariantdata *pvar; + + len = RARRAY_LEN(args); + if (len < 1 || len > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); + } + VariantInit(&var); + val = rb_ary_entry(args, 0); + + check_type_val2variant(val); + + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + if (len == 1) { + ole_val2variant(val, &(pvar->var)); + } else { + vvt = rb_ary_entry(args, 1); + vt = NUM2INT(vvt); + if ((vt & VT_TYPEMASK) == VT_RECORD) { + rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE_VARIANT object"); + } + ole_val2olevariantdata(val, vt, pvar); + } + return self; +} + +static SAFEARRAY * +get_locked_safe_array(VALUE val) +{ + struct olevariantdata *pvar; + SAFEARRAY *psa = NULL; + HRESULT hr; + TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar); + if (!(V_VT(&(pvar->var)) & VT_ARRAY)) { + rb_raise(rb_eTypeError, "variant type is not VT_ARRAY."); + } + psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var)); + if (psa == NULL) { + return psa; + } + hr = SafeArrayLock(psa); + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock"); + } + return psa; +} + +static LONG * +ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa) +{ + long dim; + LONG *pid; + long i; + dim = SafeArrayGetDim(psa); + if (dim != ary_size) { + rb_raise(rb_eArgError, "unmatch number of indices"); + } + pid = ALLOC_N(LONG, dim); + if (pid == NULL) { + rb_raise(rb_eRuntimeError, "failed to allocate memory for indices"); + } + for (i = 0; i < dim; i++) { + pid[i] = NUM2INT(ary[i]); + } + return pid; +} + +static void +unlock_safe_array(SAFEARRAY *psa) +{ + HRESULT hr; + hr = SafeArrayUnlock(psa); + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock"); + } +} + +/* + * call-seq: + * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. + * + * Returns the element of WIN32OLE_VARIANT object(OLE array). + * This method is available only when the variant type of + * WIN32OLE_VARIANT object is VT_ARRAY. + * + * REMARK: + * The all indicies should be 0 or natural number and + * lower than or equal to max indicies. + * (This point is different with Ruby Array indicies.) + * + * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) + * p obj[0,0] # => 1 + * p obj[1,0] # => 4 + * p obj[2,0] # => WIN32OLERuntimeError + * p obj[0, -1] # => WIN32OLERuntimeError + * + */ +static VALUE +folevariant_ary_aref(int argc, VALUE *argv, VALUE self) +{ + struct olevariantdata *pvar; + SAFEARRAY *psa; + VALUE val = Qnil; + VARIANT variant; + LONG *pid; + HRESULT hr; + + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + if (!V_ISARRAY(&(pvar->var))) { + rb_raise(eWIN32OLERuntimeError, + "`[]' is not available for this variant type object"); + } + psa = get_locked_safe_array(self); + if (psa == NULL) { + return val; + } + + pid = ary2safe_array_index(argc, argv, psa); + + VariantInit(&variant); + V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF; + hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"); + } + val = ole_variant2val(&variant); + + unlock_safe_array(psa); + if (pid) free(pid); + return val; +} + +/* + * call-seq: + * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array + * + * Set the element of WIN32OLE_VARIANT object(OLE array) to val. + * This method is available only when the variant type of + * WIN32OLE_VARIANT object is VT_ARRAY. + * + * REMARK: + * The all indicies should be 0 or natural number and + * lower than or equal to max indicies. + * (This point is different with Ruby Array indicies.) + * + * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) + * obj[0,0] = 7 + * obj[1,0] = 8 + * p obj.value # => [[7,2,3], [8,5,6]] + * obj[2,0] = 9 # => WIN32OLERuntimeError + * obj[0, -1] = 9 # => WIN32OLERuntimeError + * + */ +static VALUE +folevariant_ary_aset(int argc, VALUE *argv, VALUE self) +{ + struct olevariantdata *pvar; + SAFEARRAY *psa; + VARIANT var; + VARTYPE vt; + LONG *pid; + HRESULT hr; + VOID *p = NULL; + + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + if (!V_ISARRAY(&(pvar->var))) { + rb_raise(eWIN32OLERuntimeError, + "`[]' is not available for this variant type object"); + } + psa = get_locked_safe_array(self); + if (psa == NULL) { + rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer"); + } + + pid = ary2safe_array_index(argc-1, argv, psa); + + VariantInit(&var); + vt = (V_VT(&(pvar->var)) & ~VT_ARRAY); + p = val2variant_ptr(argv[argc-1], &var, vt); + if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) || + (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) { + rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface"); + } + hr = SafeArrayPutElement(psa, pid, p); + if (FAILED(hr)) { + ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement"); + } + + unlock_safe_array(psa); + if (pid) free(pid); + return argv[argc-1]; +} + +/* + * call-seq: + * WIN32OLE_VARIANT.value #=> Ruby object. + * + * Returns Ruby object value from OLE variant. + * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) + * obj.value # => "1" (not Fixnum object, but String object "1") + * + */ +static VALUE +folevariant_value(VALUE self) +{ + struct olevariantdata *pvar; + VALUE val = Qnil; + VARTYPE vt; + int dim; + SAFEARRAY *psa; + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + + val = ole_variant2val(&(pvar->var)); + vt = V_VT(&(pvar->var)); + + if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { + if (vt & VT_BYREF) { + psa = *V_ARRAYREF(&(pvar->var)); + } else { + psa = V_ARRAY(&(pvar->var)); + } + if (!psa) { + return val; + } + dim = SafeArrayGetDim(psa); + if (dim == 1) { + val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); + } + } + return val; +} + +/* + * call-seq: + * WIN32OLE_VARIANT.vartype #=> OLE variant type. + * + * Returns OLE variant type. + * obj = WIN32OLE_VARIANT.new("string") + * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR + * + */ +static VALUE +folevariant_vartype(VALUE self) +{ + struct olevariantdata *pvar; + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + return INT2FIX(V_VT(&pvar->var)); +} + +/* + * call-seq: + * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val. + * + * Sets variant value to val. If the val type does not match variant value + * type(vartype), then val is changed to match variant value type(vartype) + * before setting val. + * Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). + * If the vartype is VT_UI1|VT_ARRAY, the val should be String object. + * + * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 + * obj.value = 3.2 # 3.2 is changed to 3 when setting value. + * p obj.value # => 3 + */ +static VALUE +folevariant_set_value(VALUE self, VALUE val) +{ + struct olevariantdata *pvar; + VARTYPE vt; + TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); + vt = V_VT(&(pvar->var)); + if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) { + rb_raise(eWIN32OLERuntimeError, + "`value=' is not available for this variant type object"); + } + ole_val2olevariantdata(val, vt, pvar); + return Qnil; +} + +void +ole_variant2variant(VALUE val, VARIANT *var) +{ + struct olevariantdata *pvar; + TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar); + VariantCopy(var, &(pvar->var)); +} + +void +Init_win32ole_variant(void) +{ + cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject); + rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); + rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2); + rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2); + rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0); + rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1); + rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0); + rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1); + rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1); + + /* + * represents VT_EMPTY OLE object. + */ + rb_define_const(cWIN32OLE_VARIANT, "Empty", + rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY))); + + /* + * represents VT_NULL OLE object. + */ + rb_define_const(cWIN32OLE_VARIANT, "Null", + rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL))); + + /* + * represents Nothing of VB.NET or VB. + */ + rb_define_const(cWIN32OLE_VARIANT, "Nothing", + rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH))); + + /* + * represents VT_ERROR variant with DISP_E_PARAMNOTFOUND. + * This constants is used for not specified parameter. + * + * fso = WIN32OLE.new("Scripting.FileSystemObject") + * fso.openTextFile(filename, WIN32OLE_VARIANT::NoParam, false) + */ + rb_define_const(cWIN32OLE_VARIANT, "NoParam", + rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), INT2FIX(VT_ERROR))); +} diff --git a/jni/ruby/ext/win32ole/win32ole_variant.h b/jni/ruby/ext/win32ole/win32ole_variant.h new file mode 100644 index 0000000..efe7ea8 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variant.h @@ -0,0 +1,9 @@ +#ifndef WIN32OLE_VARIANT_H +#define WIN32OLE_VARIANT_H 1 + +VALUE cWIN32OLE_VARIANT; +void ole_variant2variant(VALUE val, VARIANT *var); +void Init_win32ole_variant(void); + +#endif + diff --git a/jni/ruby/ext/win32ole/win32ole_variant_m.c b/jni/ruby/ext/win32ole/win32ole_variant_m.c new file mode 100644 index 0000000..eb3b0b1 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variant_m.c @@ -0,0 +1,149 @@ +#include "win32ole.h" + +void Init_win32ole_variant_m(void) +{ + /* + * Document-module: WIN32OLE::VARIANT + * + * The WIN32OLE::VARIANT module includes constants of VARIANT type constants. + * The constants is used when creating WIN32OLE_VARIANT object. + * + * obj = WIN32OLE_VARIANT.new("2e3", WIN32OLE::VARIANT::VT_R4) + * obj.value # => 2000.0 + * + */ + mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT"); + + /* + * represents VT_EMPTY type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", INT2FIX(VT_EMPTY)); + + /* + * represents VT_NULL type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", INT2FIX(VT_NULL)); + + /* + * represents VT_I2 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_I2", INT2FIX(VT_I2)); + + /* + * represents VT_I4 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_I4", INT2FIX(VT_I4)); + + /* + * represents VT_R4 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_R4", INT2FIX(VT_R4)); + + /* + * represents VT_R8 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_R8", INT2FIX(VT_R8)); + + /* + * represents VT_CY type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_CY", INT2FIX(VT_CY)); + + /* + * represents VT_DATE type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", INT2FIX(VT_DATE)); + + /* + * represents VT_BSTR type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", INT2FIX(VT_BSTR)); + + /* + * represents VT_USERDEFINED type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", INT2FIX(VT_USERDEFINED)); + + /* + * represents VT_PTR type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", INT2FIX(VT_PTR)); + + /* + * represents VT_DISPATCH type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", INT2FIX(VT_DISPATCH)); + + /* + * represents VT_ERROR type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", INT2FIX(VT_ERROR)); + + /* + * represents VT_BOOL type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", INT2FIX(VT_BOOL)); + + /* + * represents VT_VARIANT type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", INT2FIX(VT_VARIANT)); + + /* + * represents VT_UNKNOWN type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", INT2FIX(VT_UNKNOWN)); + + /* + * represents VT_I1 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_I1", INT2FIX(VT_I1)); + + /* + * represents VT_UI1 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", INT2FIX(VT_UI1)); + + /* + * represents VT_UI2 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", INT2FIX(VT_UI2)); + + /* + * represents VT_UI4 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", INT2FIX(VT_UI4)); + +#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) + /* + * represents VT_I8 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_I8", INT2FIX(VT_I8)); + + /* + * represents VT_UI8 type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", INT2FIX(VT_UI8)); +#endif + + /* + * represents VT_INT type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_INT", INT2FIX(VT_INT)); + + /* + * represents VT_UINT type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", INT2FIX(VT_UINT)); + + /* + * represents VT_ARRAY type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", INT2FIX(VT_ARRAY)); + + /* + * represents VT_BYREF type constant. + */ + rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", INT2FIX(VT_BYREF)); + +} diff --git a/jni/ruby/ext/win32ole/win32ole_variant_m.h b/jni/ruby/ext/win32ole/win32ole_variant_m.h new file mode 100644 index 0000000..afbef30 --- /dev/null +++ b/jni/ruby/ext/win32ole/win32ole_variant_m.h @@ -0,0 +1,7 @@ +#ifndef WIN32OLE_VARIANT_M_H +#define WIN32OLE_VARIANT_M_H 1 + +VALUE mWIN32OLE_VARIANT; +void Init_win32ole_variant_m(void); + +#endif -- cgit v1.2.3