Class: WIN32OLE_EVENT

Inherits:
Object
  • Object
show all
Defined in:
lib/win32ole-pr.rb

Defined Under Namespace

Classes: IEVENTSINKOBJ, IEventSinkVtbl

Constant Summary collapse

@@ary_ole_event =
[]
@@g_IsEventSinkVtblInitialized =
false
@@EVENTSINK_QueryInterface =
Win32::API::Callback.new('LLL', 'L', &lambda { |pEV, riid, ppv|
  ref = 0.chr * 20
  memcpy(ref, pEV, 20)
   iid = 0.chr * 16
  memcpy(iid, riid, 16)
   ptr = IEVENTSINKOBJ.new(*ref.unpack('L*'))
  m_iid = ptr.m_iid
  ref = 0.chr * 16
  memcpy(ref, m_iid, 16)
   if iid == WIN32OLE::IID_IUnknown || iid == WIN32OLE::IID_IDispatch || iid == ref
    memcpy(ppv, [pEV].pack('L'), 4)
  else
    memcpy(ppv, 0.chr * 4, 4)
    return E_NOINTERFACE
  end
   lpVtbl = 0.chr * 4
  table = 0.chr * 28
  memcpy(lpVtbl, pEV, 4)
  memcpy(table, lpVtbl.unpack('L').first, 28)
  table = table.unpack('L*')
   addRef = Win32::API::Function.new(table[1], 'P', 'L')
  addRef.call(pEV)
   S_OK
})
@@EVENTSINK_AddRef =
Win32::API::Callback.new('L', 'L') { |pEV|
  m_cRef = 0.chr * 4
  memcpy(m_cRef, pEV+4, 4)
  m_cRef = [m_cRef.unpack('L').first+1].pack('L')
  memcpy(pEV+4, m_cRef, 4)
  m_cRef.unpack('L').first
}
@@EVENTSINK_Release =
Win32::API::Callback.new('L', 'L') { |pEV|
  m_cRef = 0.chr * 4
  memcpy(m_cRef, pEV+4, 4)
  m_cRef = [m_cRef.unpack('L').first-1].pack('L')
  memcpy(pEV+4, m_cRef, 4)
   if m_cRef.unpack('L').first != 0
    m_cRef.unpack('L').first
  else
    WIN32OLE_EVENT.EVENTSINK_Destructor(pEV)
    0
  end
}
@@EVENTSINK_Invoke =
Win32::API::Callback.new('LLPLLLPPP', 'L', &lambda { |pEventSink, dispid, riid, lcid, wFlags, pdispparams, pvarResult, pexceptinfo, puArgErr|
  ptr = 0.chr * 20
  memcpy(ptr, pEventSink, 20)
  pEV = IEVENTSINKOBJ.new(*ptr.unpack('L*'))
  pTypeInfo = pEV.pTypeInfo
  m_event_id = pEV.m_event_id
  obj = @@ary_ole_event[m_event_id]
   if !obj.is_a?(WIN32OLE_EVENT)
    return S_OK
  end
   ary = obj.events
   if ary.nil? || !ary.is_a?(Array)
    return S_OK
  end
   lpVtbl = 0.chr * 4
  table = 0.chr * 32
  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 32)
  table = table.unpack('L*')
  getNames = Win32::API::Function.new(table[7], 'PLPLP', 'L')
  bstr = 0.chr * 4
  count = 0.chr * 4
  hr = getNames.call(pTypeInfo, dispid, bstr, 1, count)
   if hr != S_OK
    return S_OK
  end
   bstr = bstr.unpack('L').first
  str = 0.chr * 256
  wcscpy(str, bstr)
  SysFreeString(bstr)
  ev = wide_to_multi(str)
  event, is_default_handler = WIN32OLE_EVENT.ole_search_event(ary, ev)
   if event.is_a?(Array)
    handler = event[0]
    mid = 'call'
    is_outarg = event[3]
  else
    handler = obj.handler
    if handler.nil?
      return S_OK
    end
    mid, is_default_handler = ole_search_handler_method(handler, ev)
  end
   if handler.nil? || mid.nil?
    return S_OK
  end
   args = []
   if is_default_handler
    args.push(ev)
  end
   cArgs = 0.chr * 4
  memcpy(cArgs, pdispparams+8, 4)
  cArgs = cArgs.unpack('L').first
   for i in 0 ... cArgs
    rgvarg = 0.chr * 4
    memcpy(rgvarg, pdispparams, 4)
    pvar = 0.chr * 16
    memcpy(pvar, rgvarg.unpack('L').first + (cArgs-i-1)*16, 16)
    args.push(WIN32OLE.ole_variant2val(pvar))
  end
   outargv = nil
   if is_outarg
    outargv = []
    args.push(outargv)
  end
   arg = [handler, mid, args]
   begin
    result = handler.send(mid, *args)
  rescue Exception => err
    raise err
  end
   if result.is_a?(Hash)
    hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams)
    result = hash2result(result)
  elsif is_outarg && outargv.is_a?(Array)
    ary2ptr_dispparams(outargv, pdispparams)
  end
   if pvarResult
    varResult = 0.chr * 16
    WIN32OLE.ole_val2variant(result, varResult)
    memcpy(pvarResult, varResult, 16)
  end
   S_OK
})
@@EVENTSINK_GetIDsOfNames =
Win32::API::Callback.new('LPPLLP', 'L') { |pEventSink, riid, sznames, cNames, lcid, pDispID|
  pEV = pEventSink
  ptr = 0.chr * 4
  memcpy(ptr, pEV+12, 4)
  pTypeInfo = ptr.unpack('L').first
   if pTypeInfo != 0
    lpVtbl = 0.chr * 4
    table = 0.chr * 28
    memcpy(lpVtbl, pTypeInfo, 4)
    memcpy(table, lpVtbl.unpack('L').first, 28)
    table = table.unpack('L*')
    getIDsOfNames = Win32::API::Function.new(table[5], 'PPPLLP', 'L')
    return getIDsOfNames.call(pTypeInfo, szNames, cNames, pDIspID)
  end
   DISP_E_UNKNOWNNAME
}
@@EVENTSINK_GetTypeInfoCount =
Win32::API::Callback.new('LP', 'L') { |pEV, pct|
  pct[0, 4] = 0.chr * 4
  S_OK
}
@@EVENTSINK_GetTypeInfo =
Win32::API::Callback.new('LLLL', 'L') { |pEV, info, lcid, pInfo|
  memcpy(pInfo, 0.chr * 4, 4)
  DISP_E_BADINDEX
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ole, event = nil) ⇒ WIN32OLE_EVENT

Returns a new instance of WIN32OLE_EVENT.



5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
# File 'lib/win32ole-pr.rb', line 5131

def initialize(ole, event=nil)
  if Win32::API::VERSION<='1.4.0'
    raise WIN32OLERuntimeError, 'win32-api version 1.4.1 or higher required'
  end

  @dwCookie = 0
  @pConnectionPoint = nil
  @event_id = 0
  ev_advise(ole, event)
  @@ary_ole_event.push(self)
  @events = []
  @handler = nil
  self
end

Instance Attribute Details

#eventsObject

Returns the value of attribute events.



4549
4550
4551
# File 'lib/win32ole-pr.rb', line 4549

def events
  @events
end

#handlerObject

Returns the value of attribute handler.



4550
4551
4552
# File 'lib/win32ole-pr.rb', line 4550

def handler
  @handler
end

Class Method Details

.EVENTSINK_Destructor(pEV) ⇒ Object



4638
4639
4640
4641
4642
4643
4644
4645
4646
# File 'lib/win32ole-pr.rb', line 4638

def self.EVENTSINK_Destructor(pEV)
  if pEV != 0
    pEVObj = 0.chr * 20
    memcpy(pEVObj, pEV, 20)
    pEVObj = IEVENTSINKOBJ.new(*pEVObj.unpack('L*'))
    WIN32OLE.ole_release(pEVObj.pTypeInfo)
    pEVObj = nil
  end
end

.message_loopObject



5126
5127
5128
5129
# File 'lib/win32ole-pr.rb', line 5126

def self.message_loop
  ole_msg_loop()
  nil
end

.ole_msg_loopObject



5118
5119
5120
5121
5122
5123
5124
# File 'lib/win32ole-pr.rb', line 5118

def self.ole_msg_loop
  msg = 0.chr * 100
  while (PeekMessage(msg, nil, 0, 0, 1))
    TranslateMessage(msg)
    DispatchMessage(msg)
  end
end

.ole_search_event(ary, ev) ⇒ Object



5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
# File 'lib/win32ole-pr.rb', line 5162

def self.ole_search_event(ary, ev)
  is_default = false
  for i in 0 ... ary.length
    event = ary[i]
    event_name = event[1]
    if event_name.nil?
      is_default = true
      def_event = event
    elsif ev == event_name
      is_default = false
      return [event, is_default]
    end
  end
  [def_event, is_default]
end

Instance Method Details

#add_event_call_back(event, data) ⇒ Object



5199
5200
5201
5202
5203
5204
5205
5206
5207
# File 'lib/win32ole-pr.rb', line 5199

def add_event_call_back(event, data)
  events = @events
  if events.nil? || !events.is_a?(Array)
    events = []
    @events = events
  end
  ole_delete_event(events, event)
  events.push(data)
end

#ary2ptr_dispparams(ary, pdispparams) ⇒ Object



4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
# File 'lib/win32ole-pr.rb', line 4598

def ary2ptr_dispparams(ary, pdispparams)
  i = 0
  cArgs = 0.chr * 4
  memcpy(cArgs, pdispparams+8, 4)
  cArgs = cArgs.unpack('L').first

  while i < ary.length && i < cArgs
    v = ary[i]
    rgvarg = 0.chr * 4
    memcpy(rgvarg, pdispparams, 4)
    pvar = 0.chr * 16
    memcpy(pvar, rgvarg.unpack('L').first + (cArgs-i-1)*16, 16)
    ole_val2ptr_variant(v, pvar)
    i += 1
  end
end

#ev_advise(ole, itf) ⇒ Object



5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
# File 'lib/win32ole-pr.rb', line 5025

def ev_advise(ole, itf)
  if !ole.is_a?(WIN32OLE)
    raise TypeError, "1st parameter must be WIN32OLE object"
  end

  if itf
    if $SAFE > 0 && itf.tainted
      raise SecurityError, "Insecure Event Creation - #{itf}"
    end

    unless itf.is_a?(String)
      raise TypeError, "2nd parameter must be String"
    end

    p = 0.chr * 4
    iid = 0.chr * 16
    hr = find_iid(ole, itf, iid, p)
    pTypeInfo = p.unpack('L').first
    lpVtbl = 0.chr * 4
    memcpy(lpVtbl, pTypeInfo, 4)
  else
    p = 0.chr * 4
    hr = find_default_source(ole, iid, p)
    pTypeInfo = p.unpack('L').first
  end

  if hr != S_OK
    raise RuntimeError, "interface not found"
  end

  pDipatch = ole.pDispatch
  lpVtbl = 0.chr * 4
  memcpy(lpVtbl, pDipatch, 4)
  table = 0.chr * 28
  memcpy(table, lpVtbl.unpack('L').first, 28)
  table = table.unpack('L*')
  queryInterface = Win32::API::Function.new(table[0], 'PPP', 'L')
  ptr = 0.chr * 4
  hr = queryInterface.call(pDipatch, WIN32OLE::IID_IConnectionPointContainer, ptr)

  if hr != S_OK
    WIN32OLE.ole_release(pTypeInfo)
    raise RuntimeError, "failed to query IConnectionPointContainer"
  end

  pContainer = p.unpack('L').first
  lpVtbl = 0.chr * 4
  table = 0.chr * 28
  memcpy(lpVtbl, pContainer, 4)
  memcpy(table, lpVtbl.unpack('L').first, 28)
  table = table.unpack('L*')
  findConnectionPoint = Win32::API::Function.new(table[4], 'PPP', 'L')

  ptr = 0.chr * 4
  hr = findConnectionPoint.call(pContainer, iid, ptr)
  WIN32OLE.ole_release(pContainer)
  pConnectionPoint = ptr.unpack('L').first

  if hr != S_OK
    WIN32OLE.ole_release(pTypeInfo)
    raise RuntimeError, "failed to query IConnectionPoint"
  end

  pIEV = EVENTSINK_Constructor()
  pIEV.m_iid = [iid].pack('P').unpack('L').first
  @pIEV = pIEV.to_a.pack('L*')
  lpVtbl = 0.chr * 4
  table = 0.chr * 28

  memcpy(lpVtbl, pConnectionPoint, 4)
  memcpy(table, lpVtbl.unpack('L').first, 28)

  table = table.unpack('L*')
  advise = Win32::API::Function.new(table[5], 'LLP', 'L')
  dwCookie = 0.chr * 4
  hr = advise.call(pConnectionPoint, [@pIEV].pack('P').unpack('L').first, dwCookie)
  dwCookie = dwCookie.unpack('L').first

  if hr != S_OK
    raise RuntimeError, "Advise Error"
  end

  pIEV = IEVENTSINKOBJ.new(*@pIEV.unpack('L*'))
  pIEV.m_event_id = @@ary_ole_event.length
  pIEV.pTypeInfo = pTypeInfo
  @dwCookie = dwCookie
  @pConnectionPoint = pConnectionPoint
  @event_id = pIEV.m_event_id
  memcpy([@pIEV].pack('P').unpack('L').first, pIEV.to_a.pack('L*'), 20)

  self
end

#ev_on_event(args, is_ary_arg, &blk) ⇒ Object



5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
# File 'lib/win32ole-pr.rb', line 5209

def ev_on_event(args, is_ary_arg, &blk)
  if @pConnectionPoint.nil?
    raise WIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first."
  end
  event = args.shift
  if event
    if !event.is_a?(String) && event.is_a?(Symbol)
      raise TypeError, "wrong argument type (expected String or Symbol)"
    end
    if event.is_a?(Symbol)
      event = event.to_s
    end
  end
  data = [blk, event, args, is_ary_arg]
  add_event_call_back(event, data)
  nil
end

#EVENTSINK_ConstructorObject



4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
# File 'lib/win32ole-pr.rb', line 4615

def EVENTSINK_Constructor()
  if !@@g_IsEventSinkVtblInitialized
    @@vtEventSink = IEventSinkVtbl.new
    @@vtEventSink.QueryInterface=@@EVENTSINK_QueryInterface.address
    @@vtEventSink.AddRef = @@EVENTSINK_AddRef.address
    @@vtEventSink.AddRef = @@EVENTSINK_AddRef.address
    @@vtEventSink.Release = @@EVENTSINK_Release.address
    @@vtEventSink.Invoke = @@EVENTSINK_Invoke.address
    @@vtEventSink.GetIDsOfNames = @@EVENTSINK_GetIDsOfNames.address
    @@vtEventSink.GetTypeInfoCount = @@EVENTSINK_GetTypeInfoCount.address
    @@vtEventSink.GetTypeInfo = @@EVENTSINK_GetTypeInfo.address
    @@vtEventSinktbl = @@vtEventSink.to_a.pack('L*')
    @@g_IsEventSinkVtblInitialized = true
  end

  pEv = IEVENTSINKOBJ.new
  pEv.lpVtbl = [@@vtEventSinktbl].pack('P').unpack('L').first
  pEv.m_cRef = 0
  pEv.m_event_id = 0
  pEv.pTypeInfo = 0
  pEv
end

#find_coclass(pTypeInfo, pTypeAttr, pCOTypeInfo, pCOTypeAttr) ⇒ Object



4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
# File 'lib/win32ole-pr.rb', line 4779

def find_coclass(pTypeInfo, pTypeAttr, pCOTypeInfo, pCOTypeAttr)
  found = false
  lpVtbl = 0.chr * 4
  table = 0.chr * 4 * 22
  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 88)
  table = table.unpack('L*')
  pTypeInfo = 0.chr * 4

  getContainingTypeLib = Win32::API::Function.new(table[18], 'PPP', 'L')
  getTypeAttr = Win32::API::Function.new(table[3], 'PP', 'L')
  getVarDesc = Win32::API::Function.new(table[6], 'PLP', 'L')
  getNames = Win32::API::Function.new(table[7], 'PLPLP', 'L')
  releaseTypeAttr = Win32::API::Function.new(table[19], 'PP', 'L')
  getRefTypeOfImplType = Win32::API::Function.new(table[8], 'PLP', 'L')
  getImplTypeFlags = Win32::API::Function.new(table[9], 'PLP', 'L')
  getRefTypeInfo = Win32::API::Function.new(table[14], 'PLP', 'L')

  p = 0.chr * 4
  hr = getContainingTypeLib.call(pTypeInfo, p, nil)
  pTypeLib = p.unpack('L').first
  return hr if hr != S_OK
  lpVtbl = 0.chr * 4
  table = 0.chr * 56
  memcpy(lpVtbl, pTypeLib, 4)
  memcpy(table, lpVtbl.unpack('L').first, 40)
  table = table.unpack('L*')
  getTypeInfoCount = Win32::API::Function.new(table[3], 'P', 'L')
  getTypeInfo = Win32::API::Function.new(table[4], 'PLP', 'L')

  count = getTypeInfoCount.call(pTypeLib)
  for i in 0 ... count
    break if found

    p = 0.chr * 4
    h = getTypeInfo.call(pTypeLib, i, p)
    pTypeInfo2 = p.unpack('L').first

    next if hr != S_OK

    p = 0.chr * 4
    hr = getTypeAttr.call(pTypeInfo2, p)
    pTypeAttr2 = p.unpack('L').first

    if hr != S_OK
      WIN32OLE.ole_release(pTypeInfo2)
      next
    end

    typeAttr = 0.chr * 76
    memcpy(typeAttr, pTypeAttr, 76)
    typekind = typeAttr[40, 4].unpack('L').first
    cImplTypes = typeAttr[48, 2].unpack('S').first

    if typekind != TKIND_COCLASS
      releaseTypeAttr.call(pTypeInfo2, pTypeAttr2)
      WIN32OLE.ole_release(pTypeInfo2)
      next
    end

    for j in 0 ... cImplTypes
      break if found
      flags = 0.chr * 4
      hr = getImplTypeFlags.call(pTypeInfo2, j, flags)
      next if hr != S_OK
      next if (flags.unpack('L').first & IMPLTYPEFLAG_FDEFAULT) == 0
      href = 0.chr * 4
      hr = getRefTypeOfImplType.call(pTypeInfo2, j, href)
      next if hr != S_OK
      href = href.unpack('L').first
      p = 0.chr * 4
      hr = getRefTypeInfo.call(pTypeInfo2, href, p)
      next if hr != S_OK
      pRefTypeInfo = p.unpack('L').first
      p = 0.chr * 4
      hr = getTypeAttr.call(pRefTypeInfo, p)
      pRefTypeAttr = p.unpack('L').first

      if hr != S_OK
        WIN32OLE.ole_release(pRefTypeInfo)
        next
      end

      guid1 = 0.chr * 16
      memcpy(typeAttr, pTypeAttr, 76)
      guid2 = 0.chr * 16
      memcpy(typeAttr, pRefTypeAttr, 76)

      if guid1 == guid2
        found = true
      end
    end

    if !found
      releaseTypeAttr.call(pTypeInfo2, pTypeAttr2)
      WIN32OLE.ole_release(pTypeInfo2)
    end
  end

  WIN32OLE.ole_release(pTypeLib)

  if found
    pCOTypeInfo[0, 4] = [pTypeInfo2].pack('L')
    pCOTypeAttr[0, 4] = [pTypeAttr2].pack('L')
    hr = S_OK
  else
    hr = [E_NOINTERFACE].pack('L').unpack('l').first
  end

  hr
end

#find_default_source(ole, piid, ppTypeInfo) ⇒ Object



4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
# File 'lib/win32ole-pr.rb', line 4928

def find_default_source(ole, piid, ppTypeInfo)
  pDispatch = ole.pDispatch
  lpVtbl = 0.chr * 4
  table = 0.chr * 28
  memcpy(lpVtbl, pDispatch, 4)
  memcpy(table, lpVtbl.unpack('L').first, 28)
  table = table.unpack('L*')
  queryInterface = Win32::API::Function.new(table[0], 'PPP', 'L')
  getTypeInfo = Win32::API::Function.new(table[4], 'PLLP', 'L')
  p = 0.chr * 4
  hr = queryInterface.call(pDispatch, IID_IProvideClassInfo2, p)
  if hr == S_OK
    pProvideClassInfo2 = p.unpack('L').first
    lpVtbl = 0.chr * 4
    table = 0.chr * 20
    memcpy(lpVtbl, pProvideClassInfo2, 4)
    memcpy(table, lpVtbl.unpack('L').first, 20)
    table = table.unpack('L*')
    getGUID = Win32::API::Function.new(table[4], 'PLP', 'L')
    ppid = 0.chr * 16
    hr = getGUID.call(pProvideClassInfo2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, ppid)
    WIN32OLE.olerelease(pProvideClassInfo2)
    if hr == S_OK
      hr = find_iid(ole, nil, ppid, ppTypeInfo)
    end
  end
  return hr if hr == S_OK
  p = 0.chr * 4
  hr = queryInterface.call(pDispatch, IID_IProvideClassInfo, p)
  if hr == S_OK
    pProvideClassInfo = p.unpack('L').first
    lpVtbl = 0.chr * 4
    table = 0.chr * 20
    memcpy(lpVtbl, pProvideClassInfo2, 4)
    memcpy(table, lpVtbl.unpack('L').first, 20)
    table = table.unpack('L*')
    getClassInfo = Win32::API::Function.new(table[3], 'PP', 'L')
    p = 0.chr * 4
    hr = getClassInfo.call(pProvideClassInfo, p)
    pTypeInfo = p.unpack('L').first
    WIN32OLE.olerelease(pProvideClassInfo2)
  end
  if hr != S_OK
    p = 0.chr * 4
    hr = getTypeInfo.call(pDispatch, 0, WIN32OLE.locale, p)
  end
  return hr if hr != S_OK
  pTypeInfo = p.unpack('L').first
  lpVtbl = 0.chr * 4
  table = 0.chr * 88
  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 88)
  table = table.unpack('L*')
  getTypeAttr = Win32::API::Function.new(table[3], 'PP', 'L')
  getVarDesc = Win32::API::Function.new(table[6], 'PLP', 'L')
  getNames = Win32::API::Function.new(table[7], 'PLPLP', 'L')
  releaseTypeAttr = Win32::API::Function.new(table[19], 'PP', 'L')
  p = 0.chr * 4
  hr = getTypeAttr(pTypeInfo, p)
  pTypeAttr = p.unpack('L').first
  if hr != S_OK
    WIN32OLE.olerelease(pTypeInfo)
    return hr
  end
  ppTypeInfo[0, 4] = 0.chr * 4
  hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo)
  if ppTypeInfo.unpack('L').first == 0
    pTypeInfo2 = 0.chr * 4
    pTypeAttr2 = 0.chr * 4
    hr = find_coclass(pTypeInfo, pTypeAttr, pTypeInfo2, pTypeAttr2)
    if hr == S_OK
      pTypeInfo2 = pTypeInfo2.unpack('L').first
      pTypeAttr2 = pTypeAttr2.unpack('L').first
      hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo)
      releaseTypeAttr.call(pTypeInfo2, pTypeAttr2)
      WIN32OLE.olerelease(pTypeInfo2)
    end
  end
  releaseTypeAttr.call(pTypeInfo, pTypeAttr)
  WIN32OLE.olerelease(pTypeInfo)
  if ppTypeInfo.unpack('L').first == 0
    hr = E_UNEXPECTED if hr == S_OK
    return hr
  end
  pTypeInfo = ppTypeInfo.unpack('L').first
  p = 0.chr * 4
  hr = getTypeAttr.call(pTypeInfo, p)
  pTypeAttr = p.unpack('L').first
  if hr == S_OK
    memcpy(piid, pTypeAttr, 16)
    releaseTypeAttr.call(pTypeInfo, pTypeAttr)
  else
    WIN32OLE.olerelease(pTypeInfo)
  end
  hr
end

#find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo) ⇒ Object



4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
# File 'lib/win32ole-pr.rb', line 4891

def find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo)
  typeAttr = 0.chr * 76
  memcpy(typeAttr, pTypeAttr, 76)
  typekind = typeAttr[40, 4].unpack('L').first
  cImplTypes = typeAttr[48, 2].unpack('S').first
  lpVtbl = 0.chr * 4
  table = 0.chr * 80

  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 80)

  table = table.unpack('L*')
  getTypeAttr = Win32::API::Function.new(table[3], 'PP', 'L')
  getRefTypeOfImplType = Win32::API::Function.new(table[8], 'PLP', 'L')
  getImplTypeFlags = Win32::API::Function.new(table[9], 'PLP', 'L')
  getRefTypeInfo = Win32::API::Function.new(table[14], 'PLP', 'L')
  releaseTypeAttr = Win32::API::Function.new(table[19], 'PP', 'L')
  hr = E_NOINTERFACE

  for i in 0 ... cImplTypes
    flags = 0.chr * 4
    hr = getImplTypeFlags.call(pTypeInfo, i, flags)
    next if hr != S_OK
    flags = flags.unpack('L').first

    if (flgas & IMPLTYPEFLAG_FDEFAULT) != 0 && (flgas & IMPLTYPEFLAG_FSOURCE) != 0
      ref = 0.chr * 4
      hr = getRefTypeOfImplType.call(pTypeInfo, i, ref)
      next if hr != S_OK
      hRefType = ref.unpack('L').first
      hr = getRefTypeInfo.call(pTypeInfo, hRefType, ppTypeInfo)
      break if hr == S_OK
    end
  end
  hr
end

#find_iid(ole, ptif, piid, ppTypeInfo) ⇒ Object



4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
# File 'lib/win32ole-pr.rb', line 4648

def find_iid(ole, ptif, piid, ppTypeInfo)
  is_found = false
  pDispatch = ole.pDispatch
  lpVtbl = 0.chr * 4
  table = 0.chr * 28
  memcpy(lpVtbl, pDispatch, 4)
  memcpy(table, lpVtbl.unpack('L').first, 28)
  table = table.unpack('L*')
  ptr = 0.chr * 4
  getTypeInfo = Win32::API::Function.new(table[4], 'PLLP', 'L')
  hr = getTypeInfo.call(pDispatch, 0, WIN32OLE.locale, ptr)
  pTypeInfo = ptr.unpack('L').first
  return hr if hr != S_OK

  lpVtbl = 0.chr * 4
  table = 0.chr * 4 * 22
  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 88)
  table = table.unpack('L*')

  getContainingTypeLib = Win32::API::Function.new(table[18], 'PPP', 'L')
  ptr = 0.chr * 4
  index = 0.chr * 4
  getContainingTypeLib.call(pTypeInfo, ptr, index)
  pTypeLib = ptr.unpack('L').first
  WIN32OLE.ole_release(pTypeInfo)
  return hr if hr != S_OK

  lpVtbl = 0.chr * 4
  table = 0.chr * 24
  memcpy(lpVtbl, pTypeLib, 4)
  memcpy(table, lpVtbl.unpack('L').first, 24)
  table = table.unpack('L*')
  getTypeInfo = Win32::API::Function.new(table[4], 'PLP', 'L')
  getTypeInfoCount = Win32::API::Function.new(table[3], 'P', 'L')
  getTypeInfoOfGuid = Win32::API::Function.new(table[5], 'PPP', 'L')
  getTypeInfoOfGuid = Win32::API::Function.new(table[5], 'PPP', 'L')

  if ptif.nil?
    hr = getTypeInfoOfGuid.call(pTypeLib, ppid, ppTypeInfo)
    WIN32OLE.ole_release(pTypeInfo)
    return hr
  end

  count = getTypeInfoCount.call(pTypeLib)

  for index in 0 ... count
    ptr = 0.chr * 4
    hr = getTypeInfo.call(pTypeLib, index, ptr)
    pTypeInfo = ptr.unpack('L').first
    break if hr != S_OK
    lpVtbl = 0.chr * 4
    table = 0.chr * 88
    memcpy(lpVtbl, pTypeInfo, 4)
    memcpy(table, lpVtbl.unpack('L').first, 88)
    table = table.unpack('L*')

    getTypeAttr = Win32::API::Function.new(table[3], 'PP', 'L')
    getVarDesc = Win32::API::Function.new(table[6], 'PLP', 'L')
    getNames = Win32::API::Function.new(table[7], 'PLPLP', 'L')
    getRefTypeOfImplType = Win32::API::Function.new(table[8], 'PLP', 'L')
    getRefTypeInfo = Win32::API::Function.new(table[14], 'PLP', 'L')
    getFuncDesc = Win32::API::Function.new(table[5], 'PLP', 'L')
    getDocumentation = Win32::API::Function.new(table[12], 'PLPPPP', 'L')
    releaseTypeAttr = Win32::API::Function.new(table[19], 'PP', 'L')
    releaseVarDesc = Win32::API::Function.new(table[21], 'PP', 'L')
    addRef = Win32::API::Function.new(table[1], 'P', 'L')

    ptr = 0.chr * 4
    hr = getTypeAttr.call(pTypeInfo, ptr)
    pTypeAttr = ptr.unpack('L').first

    if hr != S_OK
      WIN32OLE.ole_release(pTypeInfo)
      break
    end

    typeAttr = 0.chr * 76
    memcpy(typeAttr, pTypeAttr, 76)
    typekind = typeAttr[40, 4].unpack('L').first
    cImplTypes = typeAttr[48, 2].unpack('S').first

    if typekind == TKIND_COCLASS
      for type in 0 ... cImplTypes
        ref = 0.chr * 4
        hr = getRefTypeOfImplType.call(pTypeInfo, type, ref)
        break if hr != S_OK
        ref = ref.unpack('L').first
        p = 0.chr * 4
        hr = getRefTypeInfo.call(pTypeInfo, ref, p)
        pImplTypeInfo = p.unpack('L').first
        bstr = 0.chr * 4
        hr = getDocumentation.call(pImplTypeInfo, -1, bstr, nil, nil, nil)

        if hr != S_OK
          WIN32OLE.ole_release(pTypeInfo)
          break
        end

        str = 0.chr * 256
        wcscpy(str, bstr.unpack('L').first)
        pstr = wide_to_multi(str)

        if ptif == pstr
          p = 0.chr * 4
          hr = getTypeAttr.call(pImplTypeInfo, p)
          pImplTypeAttr = p.unpack('L').first
          if hr == S_OK
            is_found = true
            memcpy(piid, pImplTypeAttr, 16)
            if ppTypeInfo
              ppTypeInfo[0, 4] = [pImplTypeInfo].pack('L')
              addRef.call(pImplTypeInfo)
            end
            releaseTypeAttr.call(pImplTypeInfo, pImplTypeAttr)
          end
        end
        WIN32OLE.ole_release(pImplTypeInfo)
        break if is_found || hr != S_OK
      end
    end
    releaseTypeAttr.call(pTypeInfo, pTypeAttr)
    WIN32OLE.ole_release(pTypeInfo)
    break if is_found || hr != S_OK
  end

  WIN32OLE.ole_release(pTypeLib)
  return [E_NOINTERFACE].pack('L').unpack('l').first if !is_found
  hr
end

#hash2ptr_dispparams(hash, pTypeInfo, dispid, pdispparams) ⇒ Object



4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
# File 'lib/win32ole-pr.rb', line 4552

def hash2ptr_dispparams(hash, pTypeInfo, dispid, pdispparams)
  cArgs = 0.chr * 4
  memcpy(cArgs, pdispparams+8, 4)
  cArgs = cArgs.unpack('L').first
  bstrs = 0.chr * 4 * (cArgs+1)
  lpVtbl = 0.chr * 4
  table = 0.chr * 32
  memcpy(lpVtbl, pTypeInfo, 4)
  memcpy(table, lpVtbl.unpack('L').first, 32)
  table = table.unpack('L*')
  getNames = Win32::API::Function.new(table[7], 'PLPLP', 'L')
  len = 0.chr * 4
  hr = getNames.call(pTypeInfo, dispid, bstrs, cArgs+1, len)
  len = len.unpack('L').first

  return if hr != S_OK

  for i in 0 ... len-1
    str = 0.chr * 256
    bstr = bstrs[(i+1)*4, 4].unpack('L').first
    wcscpy(str, bstr)
    SysFreeString(bstr)
    key = wide_to_multi(str)
    val = hash[i]
    if val.nil?
      val = hash[key]
    end
    if val.nil?
      val = hash[key.intern]
      rgvarg = 0.chr * 4
      memcpy(rgvarg, pdispparams, 4)
      pvar = 0.chr * 16
      memcpy(pvar, rgvarg.unpack('L').first + (cArgs-i-1)*16, 16)
      ole_val2ptr_variant(val, pvar)
    end
  end
end

#hash2result(hash) ⇒ Object



4590
4591
4592
4593
4594
4595
4596
# File 'lib/win32ole-pr.rb', line 4590

def hash2result(hash)
  ret = hash['return']
  if ret.nil?
    ret = hash[:return]
  end
  ret
end

#off_event(event = nil) ⇒ Object



5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
# File 'lib/win32ole-pr.rb', line 5235

def off_event(event=nil)
  if event
    if !event.is_a?(String) && event.is_a?(Symbol)
      raise TypeError, "wrong argument type (expected String or Symbol)"
    end
    if event.is_a?(Symbol)
      event = event.to_s
    end
  end

  events = @events
  return nil if events.nil?
  ole_delete_event(events, event)
  nil
end

#ole_delete_event(ary, ev) ⇒ Object



5192
5193
5194
5195
5196
5197
# File 'lib/win32ole-pr.rb', line 5192

def ole_delete_event(ary, ev)
  at = ole_search_event_at(ary, ev)
  if at>=0
    ary.delete_at(at)
  end
end

#ole_search_event_at(ary, ev) ⇒ Object



5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
# File 'lib/win32ole-pr.rb', line 5146

def ole_search_event_at(ary, ev)
  ret = -1
  for i in 0 ... ary.length
    event = ary[i]
    event_name = event[1]
    if event_name.nil? && ev.nil?
      ret = i
      break
    elsif ev.is_a?(String) && event_name.is_a?(String) && ev == event_name
      ret = i
      break
    end
  end
  ret
end

#ole_search_handler_method(handler, ev) ⇒ Object



5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
# File 'lib/win32ole-pr.rb', line 5178

def ole_search_handler_method(handler, ev)
  is_default_handler = false
  mid = "on#{ev}"
  if handler.respond_to?("on#{ev}")
    return mid, is_default_handler
  end
  mid = "method_missing"
  if handler.respond_to?(mid)
    is_default_handler = true
    return [mid, is_default_handler]
  end
  [nil, is_default_handler]
end

#on_event(*args, &blk) ⇒ Object



5227
5228
5229
# File 'lib/win32ole-pr.rb', line 5227

def on_event(*args, &blk)
  ev_on_event(args, false, &blk)
end

#on_event_with_outargs(*args, &blk) ⇒ Object



5231
5232
5233
# File 'lib/win32ole-pr.rb', line 5231

def on_event_with_outargs(*args, &blk)
  ev_on_event(args, true, &blk)
end

#unadviseObject



5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
# File 'lib/win32ole-pr.rb', line 5251

def unadvise
  if @pConnectionPoint
    WIN32OLE_EVENT.ole_msg_loop()
    @@ary_ole_event[@event_id]=nil
    lpVtbl = 0.chr * 4
    table = 0.chr * 28
    memcpy(lpVtbl, @pConnectionPoint, 4)
    memcpy(table, lpVtbl.unpack('L').first, 28)
    table = table.unpack('L*')
    unadvise = Win32::API::Function.new(table[6], 'LP', 'L')
    unadvise.call(@pConnectionPoint, @dwCookie)
    WIN32OLE.ole_release(@pConnectionPoint)
    @pConnectionPoint = nil
  end
  nil
end