import ctypes, win32gui, struct
from ctypes import wintypes

user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

hdesk = user32.OpenInputDesktop(0, False, 0x01FF)
if hdesk:
    user32.SetThreadDesktop(hdesk)

hwnd = 0x541030 # SysListView32 in AutoVLBS
LVM_GETITEMCOUNT = 0x1000 + 4
LVM_GETITEMTEXTW = 0x1000 + 115

count = user32.SendMessageW(hwnd, LVM_GETITEMCOUNT, 0, 0)
print(f"AutoVLBS ListView item count: {count}")

pid = wintypes.DWORD()
user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
hProcess = kernel32.OpenProcess(0x0038, False, pid.value) # PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE

if hProcess:
    # Allocate memory in AutoVLBS process for LVITEMW and buffer
    # LVITEMW struct size is 60 bytes (32-bit) or 88 bytes (64-bit). AutoVLBS is 32-bit.
    # We allocate 1024 bytes
    pRemote = kernel32.VirtualAllocEx(hProcess, None, 1024, 0x1000, 0x04) # MEM_COMMIT, PAGE_READWRITE
    pText = pRemote + 128
    
    for i in range(count):
        # struct LVITEMW:
        # UINT mask = 0x0001 (LVIF_TEXT)
        # int iItem = i
        # int iSubItem = 0
        # UINT state = 0
        # UINT stateMask = 0
        # LPWSTR pszText = pText
        # int cchTextMax = 256
        lv_data = struct.pack('<IIiiIIII', 0x0001, i, 0, 0, 0, pText, 256, 0)
        kernel32.WriteProcessMemory(hProcess, pRemote, lv_data, len(lv_data), None)
        user32.SendMessageW(hwnd, LVM_GETITEMTEXTW, i, pRemote)
        
        buf = ctypes.create_unicode_buffer(256)
        kernel32.ReadProcessMemory(hProcess, pText, buf, 512, None)
        print(f"  Item {i}: '{buf.value}'")
        
    kernel32.VirtualFreeEx(hProcess, pRemote, 0, 0x8000)
    kernel32.CloseHandle(hProcess)
else:
    print(f"Cannot OpenProcess on AutoVLBS PID {pid.value}, err={kernel32.GetLastError()}")
