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

Discussion in 'Ruby' started by Jing Li, Jul 26, 2010.

  1. Jing Li

    Jing Li Guest

    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
     
    Jing Li, Jul 26, 2010
    #1
    1. Advertising

  2. Jing Li

    Heesob Park Guest

    Hi,

    2010/7/27 Jing Li <>:
    > =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, :psz=

    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_READ|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
     
    Heesob Park, Jul 27, 2010
    #2
    1. Advertising

  3. Jing Li

    æŽæ™¶ Guest

    [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 <>

    > 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
    > > => #<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
    >
    >
     
    æŽæ™¶, Jul 27, 2010
    #3
  4. Jing Li

    Heesob Park Guest

    Hi,

    2010/7/27 =E6=9D=8E=E6=99=B6 <>:
    > 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
     
    Heesob Park, Jul 27, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Fogelklou
    Replies:
    36
    Views:
    1,391
    Chris Fogelklou
    Apr 20, 2004
  2. beetle
    Replies:
    2
    Views:
    911
    beetle
    Jan 25, 2005
  3. Zero
    Replies:
    16
    Views:
    657
    Barry Schwarz
    Nov 19, 2005
  4. Daniel Berger

    Win32API struct member help

    Daniel Berger, Mar 18, 2006, in forum: Ruby
    Replies:
    0
    Views:
    141
    Daniel Berger
    Mar 18, 2006
  5. aleksa

    Struct pointer vs. struct array pointer

    aleksa, Feb 20, 2013, in forum: C Programming
    Replies:
    16
    Views:
    471
    Shao Miller
    Feb 20, 2013
Loading...

Share This Page