From: "李晶" Date: 2010-07-27T16:51:11+09:00 Subject: Re: Help: How to pass a struct as a pointer to Win32API? --001636c5b77ba3dcad048c59c33c Content-Type: text/plain; charset=UTF-8 Hi Park, Thanks for your answer, and I've tried your code, everything is fine but nothing is retrieved for item or subitem. So the result will be like this: - - - which should be "#{item} - #{subitem}" Could you plz tell me what's wrong? Meanwhile I will investigate on this. BTW, does it matter if I remove VirtualAllocEx and WriteProcessMemory part? Since I mentioned it's not a pop-up. Thanks a lot. Regards, Jing Li 2010/7/27 Heesob Park > Hi, > > 2010/7/27 Jing Li : > > Hi all, > > > > As titled, I want to read text content from a standard syslistview32 > control > > in an application. And the syslistview32 control is not a pop-up but > > embedded in the application, which means the control has same process ID > as > > the application. In that case, I don't have to call VirtualAllocEx or > > WriteProcessMemory. > > > > So far, I could successfully get syslistview32 control's handle, count > how > > many items listed. But still can not read its content. Could you please > > tell me how to do it correctly? > > > > require 'Win32API' > > findwin = Win32API.new('user32', 'FindWindow', 'PP', 'L') > > getdlg = Win32API.new('user32', 'GetDlgItem', 'LL', 'L') > > sendmsg = Win32API.new('user32', 'SendMessage', 'LLLP', 'L') > > > > #Some irrelevant details are ignored > > #Here I've already got syslistview32 control's handle, let's assume it is > > resultslist = 3739380 > > > > puts "Count of items = #{sendmsg.call(resultslist, 4100, 0, nil)}" > > #LVM_GETITEMCOUNT = 0x1004 > > puts header = getdlg.call(resultslist, 0).to_s(16).upcase > > #No problem, this works > > > > #From here I tried to SendMessage with LVM_GETITEMTEXT parameter to get > > syslistview32's content > > #Solution I: define a struct as described in MSDN, but something wrong > when > > I tried to pack, this is due to my lack of knowledge on pack&unpack > > LV_item = Struct.new(:mask, :iItem, :iSubItem, :state, :stateMask, > :pszText, > > :cchTextMax, :iImage, :lParam) > > lv_item = LV_item.new() > > puts sendmsg.call(resultslist, 4165, 1, lv_item.to_a.pack("p")) > > => return value is 1, success? > > puts lv_item.inspect > > => # > stateMask=nil, pszText=nil, cchTextMax=nil, iImage=nil, lParam=nil> > > absolutely not succeed > > #If I initiate lv_item = LV_item.new(0, 0, 0, 0, 0, "", 0, 0, ""), then > > error occurs at packing: can't convert Fixnum into String (TypeError). > Can > > I pack integer pointer except pack("p")? > > > > #Solution II: Directly pack an array and pass to SendMessage, return > value > > is still nil > > lv_item = [0, 0, 0, 0, 0, "\000", 0, 0, "\000"] > > lv_item = lv_item.pack("IiiIIpiip") > > puts sendmsg.call(resultslist, 4165, 1, lv_item) > > => return value is 1, success? > > lv_item = lv_item.unpack("IiiIIpiip") > > puts lv_item.inspect > > => [0, 0, 0, 0, 0, "\000", 0, 0, "\000"], nothing is padded actually > > > > I really appreciate if you can answer my question, thanks in advance. > > > Here is a code using VirtualAllocEx and WriteProcessMemory for a > general purpose. > > > require 'Win32API' > > findwin = Win32API.new('user32', 'FindWindow', 'PP', 'L') > getdlg = Win32API.new('user32', 'GetDlgItem', 'LL', 'L') > sendmsg = Win32API.new('user32', 'SendMessage', 'LLLP', 'L') > > getWindowThreadProcessId = Win32API.new('user32', > 'GetWindowThreadProcessId', 'LP', 'L') > openProcess = Win32API.new('kernel32', 'OpenProcess', 'LIL', 'L') > virtualAllocEx = Win32API.new('kernel32', 'VirtualAllocEx', 'LPLLL', 'L') > virtualFreeEx = Win32API.new('kernel32', 'VirtualFreeEx', 'LLLL', 'L') > writeProcessMemory = Win32API.new('kernel32', 'WriteProcessMemory', > 'LLPLP', 'I') > readProcessMemory = Win32API.new('kernel32', 'ReadProcessMemory', 'LLPLP', > 'I') > > PROCESS_VM_OPERATION = 0x08 > PROCESS_VM_READ = 0x10 > PROCESS_VM_WRITE = 0x20 > PROCESS_QUERY_INFORMATION = 0x400 > MEM_COMMIT = 0x1000 > MEM_RELEASE = 0x8000 > PAGE_READWRITE = 0x04 > LVM_GETITEMTEXT = 0x1000+45 > LVM_GETITEMCOUNT = 0x1000+4 > SIZE_OF_LVITEM = 60 > > resultslist = 0xB0044 ##<== start with some given handle > > count = sendmsg.call(resultslist,LVM_GETITEMCOUNT, 0, nil) > lv_item = [0, 0, 0, 0, 0, nil, 512, 0, 0,0,0,0,0,0,0] > lv_item = lv_item.pack("LiiLLpiiLiiLLLL") > pid = 0.chr*4 > getWindowThreadProcessId.call(resultslist, pid) > pid = pid.unpack('L').first > process = > openProcess.call(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION,0,pid) > _lvi=virtualAllocEx.call(process, nil, SIZE_OF_LVITEM,MEM_COMMIT, > PAGE_READWRITE) > _item=virtualAllocEx.call(process, nil, 512, MEM_COMMIT,PAGE_READWRITE) > _subitem=virtualAllocEx.call(process, nil, 512, MEM_COMMIT,PAGE_READWRITE) > > for i in 0..count > lv_item[8,4] = [0].pack('L') > item = 0.chr * 512 > lv_item[20,4] = [_item].pack('L') > writeProcessMemory.call(process, _lvi, lv_item, SIZE_OF_LVITEM, nil) > sendmsg.call(resultslist, LVM_GETITEMTEXT, i, _lvi) > > subitem = 0.chr * 512 > lv_item[8,4] = [1].pack('L') > lv_item[20,4] = [_subitem].pack('L') > writeProcessMemory.call(process, _lvi, lv_item, SIZE_OF_LVITEM, nil) > sendmsg.call(resultslist, LVM_GETITEMTEXT, i, _lvi) > > readProcessMemory.call(process, _item, item, 512, nil) > readProcessMemory.call(process, _item, subitem, 512, nil) > item = item.strip! > subitem = subitem.strip! > puts "#{item} - #{subitem}" > end > > virtualFreeEx.call(process, _lvi, 0, MEM_RELEASE) > virtualFreeEx.call(process, _item, 0, MEM_RELEASE) > virtualFreeEx.call(process, _subitem, 0, MEM_RELEASE) > > > > Regards, > Park Heesob > > --001636c5b77ba3dcad048c59c33c--