Help: How to pass a struct as a pointer to Win32API?

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
=> #
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

Hi,

2010/7/27 Jing Li [email protected]:

tell me how to do it correctly?
puts “Count of items = #{sendmsg.call(resultslist, 4100, 0, nil)}”
lv_item = LV_item.new()
#Solution II: Directly pack an array and pass to SendMessage, return value

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 H.

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 P. [email protected]

Hi,

2010/7/27 李晶 [email protected]:

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 H.

Hi Park,

I tried both, with VirtualAllocEx and WriteProcessMemory part and
without.
The problem now is that I can not unpack lv_item after sendmessage.
Error
prompted: in “unpack”: non associated pointer. I guess I can simply try
to
unpack pszText, i.e. 5th element of lv_item, but i don’t know the
length?

BTW, from your code: lv_item[20,4], could you plz explain why it’s 20?
What
I understand is there are only 15 elements. And what’s more, according
to
MSDN, the LVITEM struct has only 14 elements. Correct me if I’m wrong.
Thanks.

Here attached both snippets. Thanks for your patient answer.

Regards and Thanks,
Jing Li

2010/7/27 Heesob P. [email protected]