5

I want to make a little application that changes the default playback device in windows 7. The only solution was to interact with the Sound Applet. I succeeded to get the handle to the SysListView32 window that has the devices name but i cant get the text from the ListView.

This is the code used:

IntPtr sListView = (window handle received from another function)
LVITEM lvi = new LVITEM();
lvi.mask = LVIF_TEXT;
lvi.cchTextMax = 1024;
lvi.iItem = 0; // i tried with a loop trought all the items
lvi.iSubItem = 0;
lvi.pszText = Marshal.AllocHGlobal(1024);

IntPtr ptrLvi = Marshal.AllocHGlobal(Marshal.SizeOf(lvi));
Marshal.StructureToPtr(lvi, ptrLvi, false);

SendMessage(sListView, (int)WinMesages.LVM_GETITEMW, IntPtr.Zero, ptrLvi);

string strLvi = Marshal.PtrToStringAuto(lvi.pszText);

The result (strLvi) are some chinese letters. What is wrong in the script?

UPDATE: LVITEM struct is this:

private struct LVITEM
{
    public uint mask;
    public int iItem;
    public int iSubItem;
    public uint state;
    public uint stateMask;
    public IntPtr pszText;
    public int cchTextMax;
    public int iImage;
    public IntPtr lParam;
}

The sLIstView handle is correct... a checked in spy++. What test do i need to perform to check where is the problem? I could give you all the script if that would help.

Sp3ct3R
  • 715
  • 1
  • 12
  • 24

1 Answers1

1

Have you tried using LWM_GETITEMTEXTW instead?

Sergey Kudriavtsev
  • 10,328
  • 4
  • 43
  • 68
  • @Sp3ct3R: Than what about string encoding? Can you try using PtrToStringUni/PtrToStringAnsi instead of PtrToStringAuto? – Sergey Kudriavtsev Sep 30 '11 at 20:58
  • There are another characters but not decipherable. i`ve tried with LWM_GETITEMTEXTW and LWM_GETITEMW like in my original post. Thanks for replying. – Sp3ct3R Sep 30 '11 at 21:52
  • @Sp3ct3R: Did some search on the Internet - seems your code is generally correct, but only for in-process communication. You just can't use it for interprocess communication because a pointer returned from call to SendMessage will be relative to process and thus invalid in your process context. Link to the forum topic where you can find some suggestions: http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-interop/1285/C-Win32-Interop-LVM-GETITEM-Plz-Help . – Sergey Kudriavtsev Oct 01 '11 at 08:02
  • Thanks i will try to convert that c++ script into C#. I will post here if i get in trouble. – Sp3ct3R Oct 01 '11 at 09:03
  • ok... i`ve got a problem at this line: lvItem.pszText = (LPTSTR)(lpRemoteBuffer + sizeof( LVITEM )); how can i set the pszText in C#? – Sp3ct3R Oct 01 '11 at 10:53
  • and here: WriteProcessMemory( hProcess, (LPVOID)lpRemoteBuffer, &lvItem, sizeof(LVITEM), NULL ); How can i write these in C# i have problem at LPVOID, &lvItem and sizeof(LVITEM) witch C# cannot retreive. – Sp3ct3R Oct 01 '11 at 11:08
  • [DllImport("kernel32.dll")] private static unsafe extern Boolean WriteProcessMemory(IntPtr hProcess, uint lpBaseAddress, byte[] lpBuffer, int nSize, void* lpNumberOfBytesWritten); – Sergey Kudriavtsev Oct 01 '11 at 13:45
  • for pszText do just a "+" operation, it should work - I mean, lvItem.pszText = lpRemoteBuffer + Marshal.SizeOf( lvItem ); – Sergey Kudriavtsev Oct 01 '11 at 13:53
  • well for pszText i`ve tried lvi.pszText = remBuffer + new IntPtr(Marshal.SizeOf(lvi)); but i gives me an `Operator '+' cannot be applied to operands of type 'System.IntPtr' and 'System.IntPtr'` error. – Sp3ct3R Oct 01 '11 at 14:53
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3949/discussion-between-sp3ct3r-and-sergey-kudriavtsev) – Sp3ct3R Oct 01 '11 at 14:54