Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Help: How to pass a struct as a pointer to Win32API?

Reply
Thread Tools

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

 
 
Jing Li
Guest
Posts: n/a
 
      07-26-2010
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,
szText, :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

 
Reply With Quote
 
 
 
 
Heesob Park
Guest
Posts: n/a
 
      07-27-2010
Hi,

2010/7/27 Jing Li <(E-Mail Removed)>:
> =C2=A0Hi all,
>
> As titled, I want to read text content from a standard syslistview32 cont=

rol
> in an application. =C2=A0And the syslistview32 control is not a pop-up bu=

t
> embedded in the application, which means the control has same process ID =

as
> the application. =C2=A0In that case, I don't have to call VirtualAllocEx =

or
> WriteProcessMemory.
>
> So far, I could successfully get syslistview32 control's handle, count ho=

w
> many items listed. =C2=A0But still can not read its content. =C2=A0Could =

you please
> tell me how to do it correctly?
>
> require 'Win32API'
> findwin =3D Win32API.new('user32', 'FindWindow', 'PP', 'L')
> getdlg =3D Win32API.new('user32', 'GetDlgItem', 'LL', 'L')
> sendmsg =3D 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 =3D 3739380
>
> puts "Count of items =3D #{sendmsg.call(resultslist, 4100, 0, nil)}"
> #LVM_GETITEMCOUNT =3D 0x1004
> puts header =3D 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 wh=

en
> I tried to pack, this is due to my lack of knowledge on pack&unpack
> LV_item =3D Struct.new(:mask, :iItem, :iSubItem, :state, :stateMask, sz=

Text,
> :cchTextMax, :iImage, :lParam)
> lv_item =3D LV_item.new()
> puts sendmsg.call(resultslist, 4165, 1, lv_item.to_a.pack("p"))
> =C2=A0 =C2=A0=3D> return value is 1, success?
> puts lv_item.inspect
> =C2=A0 =C2=A0=3D> #<struct LV_item mask=3Dnil, iItem=3Dnil, iSubItem=3Dni=

l, state=3Dnil,
> stateMask=3Dnil, pszText=3Dnil, cchTextMax=3Dnil, iImage=3Dnil, lParam=3D=

nil>
> absolutely not succeed
> #If I initiate lv_item =3D LV_item.new(0, 0, 0, 0, 0, "", 0, 0, ""), then
> error occurs at packing: can't convert Fixnum into String (TypeError). =

=C2=A0Can
> I pack integer pointer except pack("p")?
>
> #Solution II: Directly pack an array and pass to SendMessage, return valu=

e
> is still nil
> lv_item =3D [0, 0, 0, 0, 0, "\000", 0, 0, "\000"]
> lv_item =3D lv_item.pack("IiiIIpiip")
> puts sendmsg.call(resultslist, 4165, 1, lv_item)
> =C2=A0 =C2=A0=3D> return value is 1, success?
> lv_item =3D lv_item.unpack("IiiIIpiip")
> puts lv_item.inspect
> =C2=A0 =C2=A0=3D> [0, 0, 0, 0, 0, "\000", 0, 0, "\000"], nothing is padde=

d 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 =3D Win32API.new('user32', 'FindWindow', 'PP', 'L')
getdlg =3D Win32API.new('user32', 'GetDlgItem', 'LL', 'L')
sendmsg =3D Win32API.new('user32', 'SendMessage', 'LLLP', 'L')

getWindowThreadProcessId =3D Win32API.new('user32',
'GetWindowThreadProcessId', 'LP', 'L')
openProcess =3D Win32API.new('kernel32', 'OpenProcess', 'LIL', 'L')
virtualAllocEx =3D Win32API.new('kernel32', 'VirtualAllocEx', 'LPLLL', 'L')
virtualFreeEx =3D Win32API.new('kernel32', 'VirtualFreeEx', 'LLLL', 'L')
writeProcessMemory =3D Win32API.new('kernel32', 'WriteProcessMemory',
'LLPLP', 'I')
readProcessMemory =3D Win32API.new('kernel32', 'ReadProcessMemory', 'LLPLP'=
, 'I')

PROCESS_VM_OPERATION =3D 0x08
PROCESS_VM_READ =3D 0x10
PROCESS_VM_WRITE =3D 0x20
PROCESS_QUERY_INFORMATION =3D 0x400
MEM_COMMIT =3D 0x1000
MEM_RELEASE =3D 0x8000
PAGE_READWRITE =3D 0x04
LVM_GETITEMTEXT =3D 0x1000+45
LVM_GETITEMCOUNT =3D 0x1000+4
SIZE_OF_LVITEM =3D 60

resultslist =3D 0xB0044 ##<=3D=3D start with some given handle

count =3D sendmsg.call(resultslist,LVM_GETITEMCOUNT, 0, nil)
lv_item =3D [0, 0, 0, 0, 0, nil, 512, 0, 0,0,0,0,0,0,0]
lv_item =3D lv_item.pack("LiiLLpiiLiiLLLL")
pid =3D 0.chr*4
getWindowThreadProcessId.call(resultslist, pid)
pid =3D pid.unpack('L').first
process =3D openProcess.call(PROCESS_VM_OPERATION|PROCESS_VM_R EAD|PROCESS_V=
M_WRITE|PROCESS_QUERY_INFORMATION,0,pid)
_lvi=3DvirtualAllocEx.call(process, nil, SIZE_OF_LVITEM,MEM_COMMIT,
PAGE_READWRITE)
_item=3DvirtualAllocEx.call(process, nil, 512, MEM_COMMIT,PAGE_READWRITE)
_subitem=3DvirtualAllocEx.call(process, nil, 512, MEM_COMMIT,PAGE_READWRITE=
)

for i in 0..count
lv_item[8,4] =3D [0].pack('L')
item =3D 0.chr * 512
lv_item[20,4] =3D [_item].pack('L')
writeProcessMemory.call(process, _lvi, lv_item, SIZE_OF_LVITEM, nil)
sendmsg.call(resultslist, LVM_GETITEMTEXT, i, _lvi)

subitem =3D 0.chr * 512
lv_item[8,4] =3D [1].pack('L')
lv_item[20,4] =3D [_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 =3D item.strip!
subitem =3D 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

 
Reply With Quote
 
 
 
 
李晶
Guest
Posts: n/a
 
      07-27-2010
[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 <(E-Mail Removed)>

> Hi,
>
> 2010/7/27 Jing Li <(E-Mail Removed)>:
> > 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,

> szText,
> > :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_R EAD|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION,0,p id)
> _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
>
>


 
Reply With Quote
 
Heesob Park
Guest
Posts: n/a
 
      07-27-2010
Hi,

2010/7/27 =E6=9D=8E=E6=99=B6 <(E-Mail Removed)>:
> 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:
> =C2=A0-
> =C2=A0-
> =C2=A0-
> which should be "#{item} - #{subitem}"
>
> Could you plz tell me what's wrong? =C2=A0Meanwhile I will investigate on=

this.
>
> BTW, does it matter if I remove VirtualAllocEx and WriteProcessMemory par=

t?
> 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] =3D [_item].pack('L')
should be
lv_item[20,4] =3D [item].pack('p')

lv_item[20,4] =3D [_subitem].pack('L')
should be
lv_item[20,4] =3D [subitem].pack('p')


Regards,
Park Heesob

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Struct pointer vs. struct array pointer aleksa C Programming 16 02-20-2013 08:20 PM
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
(: Pointer to struct withing pointer to struct :) Zero C Programming 16 11-19-2005 01:27 AM
passing pointer->struct->pointer->struct to function. .. ?? beetle C Programming 2 01-25-2005 06:08 PM



Advertisments