From: Jing Li on 26 Jul 2010 16:13 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 => #<struct LV_item mask=nil, iItem=nil, iSubItem=nil, state=nil, 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. Have a good nite or morning/afternoon, Thyrlian
From: Heesob Park on 26 Jul 2010 23:26 Hi, 2010/7/27 Jing Li <thyrlian(a)gmail.com>: > Â 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 > Â Â => #<struct LV_item mask=nil, iItem=nil, iSubItem=nil, state=nil, > 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
From: 李晶 on 27 Jul 2010 03:51 [Note: parts of this message were removed to make it a legal post.] 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 <phasis(a)gmail.com> > Hi, > > 2010/7/27 Jing Li <thyrlian(a)gmail.com>: > > 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 > > => #<struct LV_item mask=nil, iItem=nil, iSubItem=nil, state=nil, > > 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 > >
From: Heesob Park on 27 Jul 2010 04:40 Hi, 2010/7/27 ææ¶ <thyrlian(a)gmail.com>: > 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. > Did you tried the whole code with VirtualAllocEx and WriteProcessMemory? What's your code? If you want to remove VirtualAllocEx and WriteProcessMemory part, lv_item[20,4] = [_item].pack('L') should be lv_item[20,4] = [item].pack('p') lv_item[20,4] = [_subitem].pack('L') should be lv_item[20,4] = [subitem].pack('p') Regards, Park Heesob
|
Pages: 1 Prev: Directory structure best practice? Next: interactive ruby development |