- win32-api
- windows-api
require 'windows/com'
require 'windows/unicode'
require 'windows/error'
require 'windows/national'
require 'windows/window/message'
require 'windows/msvcrt/buffer'
require 'watir/win32ole'
include Windows::COM
include Windows::Unicode
include Windows::National
include Windows::Error
include Windows::Window::Message
include Windows::MSVCRT::Buffer
VariantInit = Win32::API.new('VariantInit', 'P', 'V', 'oleaut32')
OleUninitialize = Win32::API.new('OleUninitialize', 'V', 'V', 'ole32')
DISPID_UNKNOWN = -1
DISPID_VALUE = 0
DISPID_PROPERTYPUT = -3
DISPID_NEWENUM = -4
DISPID_EVALUATE = -5
DISPID_CONSTRUCTOR = -6
DISPID_DESTRUCTOR = -7
DISPID_COLLECT = -8
DISPATCH_METHOD = 0x1
DISPATCH_PROPERTYGET = 0x2
DISPATCH_PROPERTYPUT = 0x4
DISPATCH_PROPERTYPUTREF = 0x8
# Initialize OLE Libraries.
OleInitialize()
SMTO_ABORTIFHUNG = 0x0002
ObjectFromLresult = Win32::API.new('ObjectFromLresult', 'LPIP', 'L', 'oleacc')
IID_NULL = [0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00].pack('LSSC8')
def get_control_from_hwnd(hnd)
CoInitialize(0)
reg_msg = RegisterWindowMessage("WM_HTML_GETOBJECT")
puts "msg: " + reg_msg.to_s
iid =[0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37].pack('LSSC8')
result = 0.chr*4
SendMessageTimeout(hnd.hex, reg_msg, 0, 0, SMTO_ABORTIFHUNG,1000, result)
puts "result unpacked: " + result.unpack("L").to_s
result = result.unpack('L')[0]
idisp = 0.chr * 4
r = ObjectFromLresult.call(result, iid, 0, idisp)
if r == 0
idisp = idisp.unpack('L').first
puts "idisp: " + idisp.to_s
end
pDisp = idisp
ucPtr = multi_to_wide("Script")
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,28)
table = table.unpack('L*')
getIDsOfNames = Win32::API::Function.new(table[5],'PPPLLP','L')
dispID = 0.chr * 4
getIDsOfNames.call(pDisp,IID_NULL,[ucPtr].pack('P'),1,LOCALE_USER_DEFAULT,dispID)
dispID = dispID.unpack('L').first
dispParams = [0,0,0,0].pack('LLLL')
res = 0.chr * 16
invoke = Win32::API::Function.new(table[6],'PLPLLPPPP','L')
hr = invoke.call(pDisp,
dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET | DISPATCH_METHOD,
dispParams, res, nil, nil)
if hr != S_OK
raise StandardError, "IDispatch::Invoke() failed with %08x" % hr
end
res = res.unpack('SSSSLL')
if res[0] == VT_DISPATCH
pDisp = res[4]
ucPtr = multi_to_wide("Document")
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,28)
table = table.unpack('L*')
getIDsOfNames = Win32::API::Function.new(table[5],'PPPLLP','L')
dispID = 0.chr * 4
getIDsOfNames.call(pDisp,IID_NULL,[ucPtr].pack('P'),1,LOCALE_USER_DEFAULT,dispID)
dispID = dispID.unpack('L').first
dispParams = [0,0,0,0].pack('LLLL')
res = 0.chr * 16
invoke = Win32::API::Function.new(table[6],'PLPLLPPPP','L')
hr = invoke.call(pDisp,
dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET | DISPATCH_METHOD,
dispParams, res, nil, nil)
if hr != S_OK
raise StandardError, "IDispatch::Invoke() failed with %08x" % hr
end
res = res.unpack('SSSSLL')
if res[0] == VT_DISPATCH
pDisp = res[4]
ucPtr = multi_to_wide("parentWindow")
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,28)
table = table.unpack('L*')
getIDsOfNames = Win32::API::Function.new(table[5],'PPPLLP','L')
dispID = 0.chr * 4
getIDsOfNames.call(pDisp,IID_NULL,[ucPtr].pack('P'),1,LOCALE_USER_DEFAULT,dispID)
dispID = dispID.unpack('L').first
dispParams = [0,0,0,0].pack('LLLL')
res = 0.chr * 16
invoke = Win32::API::Function.new(table[6],'PLPLLPPPP','L')
hr = invoke.call(pDisp,
dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET | DISPATCH_METHOD,
dispParams, res, nil, nil)
if hr != S_OK
raise StandardError, "IDispatch::Invoke() failed with %08x" % hr
end
res = res.unpack('SSSSLL')
if res[0] == VT_DISPATCH
puts "#{res}"
return res[4]
end
end
end
0
end
Maybe the time will come and I'll dig into this code deeper to get an idea what exactly is going on here but for now it's enough for me to know that this code returns the Dispatch pointer to the OLE object corresponding to the window with specified HWND (passed as parameter). The only thing left here is to connect to OLE object and use it methods and properties. It looks like: obj = get_control_from_hwnd(handle) ie = WIN32OLE.connect_unknown( obj )Where handle variable contains previously found HWND of our OLE object. After that we are free to use OLE object. So, I can write something like:
handle = "00C40180" obj = get_control_from_hwnd(handle) ie = WIN32OLE.connect_unknown( obj ) puts ie.window.document.body.innerHTMLOf course, handle should be initialized with the proper HWND value of existing object. In order to get more details about document objects and methods we just have to dig into MSDN here.
That's it and current problem no longer disturbs me, so let's look for other challenges.
No comments:
Post a Comment