Question

I have an Owner Drawn List Box in an external application (America Online) that I need to get data out of for building a component to assist people with its usability. (the utility will be making access of certain things more simple, etc).

Notice

My knowledge of C++ is very poor. I am a C# programmer.

I have the hWnd to the List Box in question, but it appears to be owner drawn. Using LB_GETTEXT returns bad data, I just get junk (it renders in my debugger as a bunch of chinese characters) and going through LB_GETITEMDATA returns much the same.

I believe this is because the owner drawn list box has graphics on it. Doing a lot of digging, I have discovered others in the past with this problem. I have unearthed the following code that is supposed to remedy this issue. However it does not. The code is posted below, and the issues beneath it.

void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
    int result;
    DWORD processID;
    HANDLE hProcess;
    char *itemData;
    char sDataRead[5];
    DWORD bytes;
    DWORD lListItemHold, lListItemDataHold;
    *outputResult=0;

    if( hListWnd )
    {
        GetWindowThreadProcessId( hListWnd, &processID );

        hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );

        if( hProcess )
        {
            lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
            lListItemHold=lListItemHold+24;

            result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
            if( !result )
            {
                RaiseWinErr();
            }

            memcpy( &lListItemDataHold, &sDataRead, 4 );
            lListItemDataHold=lListItemDataHold+6;

            ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );

            CloseHandle( hProcess );
        }
    }
}

My understanding, limited as it is, is that lListItemHold=lListItemHold+24 tries to account for whatever 'structure' is in the ListBox and pass through the first 24 bytes of it, and return what remains. However this does not seem to be working for me.

Can anyone shed some light on things I could try? I know I am grasping at straws as it is. I am coding this in C#, so this function is used using p/invoke such as follows;

    [DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern void RetrieveListItem(
        System.IntPtr hWnd,
        System.Int32 index,
        [MarshalAs(UnmanagedType.LPArray)]byte[] buffer
    );

    [DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern void RetrieveListItem(
        System.IntPtr hWnd,
        System.Int32 index,
        [MarshalAs(UnmanagedType.LPTStr)]System.Text.StringBuilder buffer
    );
Was it helpful?

Solution

I have two blog posts on the topic

http://taylorza.blogspot.com/2009/08/archive-hacking-my-way-across-process.html http://taylorza.blogspot.com/2010/06/crossing-process-boundary-with-net.html

These however are for a ListView control, but you might want to take a look at the code. The second post is using P/Invoke to achieve this in .NET.

1- Why are you adding 24 to lListItemHold?

2- Are you sure lListItemhold is a pointer to a string, it might be some internal structure of the application.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top