Results 1 to 16 of 16

Thread: [VB6] SendMessage - 64 bit compatible.

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,778

    [VB6] SendMessage - 64 bit compatible.

    Hello eveyone.

    I've added SendMessageW64 function to this module. Now you can pass a message to 64 bit applications and get 64 bit result. This is the example where you can obtain the treeview nodes from 64-bit regedit.exe:

    Code:
    ' //
    ' // Call 64-bit SendMessage from 32-bit process
    ' //
    
    Option Explicit
    
    Private Const MAX_PATH                As Long = 260
    Private Const PROCESS_VM_READ         As Long = &H10
    Private Const PROCESS_VM_OPERATION    As Long = &H8
    Private Const PROCESS_VM_WRITE        As Long = &H20
    Private Const TV_FIRST                As Long = &H1100
    Private Const TVM_GETNEXTITEM         As Long = (TV_FIRST + 10)
    Private Const TVM_GETITEM             As Long = (TV_FIRST + 62)
    Private Const TVGN_ROOT               As Long = 0
    Private Const TVGN_NEXT               As Long = 1
    Private Const TVGN_CHILD              As Long = 4
    Private Const TVIF_TEXT               As Long = 1
    Private Const MEM_RESERVE             As Long = &H2000&
    Private Const MEM_COMMIT              As Long = &H1000&
    Private Const MEM_RELEASE             As Long = &H8000&
    Private Const PAGE_READWRITE          As Long = 4&
    
    Private Type STARTUPINFO
        cb              As Long
        lpReserved      As Long
        lpDesktop       As Long
        lpTitle         As Long
        dwX             As Long
        dwY             As Long
        dwXSize         As Long
        dwYSize         As Long
        dwXCountChars   As Long
        dwYCountChars   As Long
        dwFillAttribute As Long
        dwFlags         As Long
        wShowWindow     As Integer
        cbReserved2     As Integer
        lpReserved2     As Long
        hStdInput       As OLE_HANDLE
        hStdOutput      As OLE_HANDLE
        hStdError       As OLE_HANDLE
    End Type
    
    Private Type PROCESS_INFORMATION
        hProcess        As Long
        hThread         As OLE_HANDLE
        dwProcessId     As Long
        dwThreadId      As OLE_HANDLE
    End Type
    
    Private Type TVITEM64
        mask            As Long
        lPad            As Long
        hItem           As Currency
        State           As Long
        stateMask       As Long
        pszText         As Currency
        cchTextMax      As Long
        iImage          As Long
        iSelectedImage  As Long
        cChildren       As Long
        lParam          As Currency
    End Type
    
    Private Declare Function CreateProcess Lib "kernel32" _
                             Alias "CreateProcessW" ( _
                             ByVal lpApplicationName As Long, _
                             ByVal lpCommandLine As Long, _
                             ByRef lpProcessAttributes As Any, _
                             ByRef lpThreadAttributes As Any, _
                             ByVal bInheritHandles As Long, _
                             ByVal dwCreationFlags As Long, _
                             ByRef lpEnvironment As Any, _
                             ByVal lpCurrentDirectory As Long, _
                             ByRef lpStartupInfo As STARTUPINFO, _
                             ByRef lpProcessInformation As PROCESS_INFORMATION) As Long
    Private Declare Function Wow64DisableWow64FsRedirection Lib "kernel32" ( _
                             ByRef lvalue As Long) As Long
    Private Declare Function Wow64RevertWow64FsRedirection Lib "kernel32" ( _
                             ByVal lvalue As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" ( _
                             ByVal hObject As OLE_HANDLE) As Long
    Private Declare Function WaitForInputIdle Lib "user32" ( _
                             ByVal hProcess As OLE_HANDLE, _
                             ByVal dwMilliseconds As Long) As Long
    Private Declare Function GetWindowsDirectory Lib "kernel32" _
                             Alias "GetWindowsDirectoryW" ( _
                             ByVal lpBuffer As Long, _
                             ByVal nSize As Long) As Long
    Private Declare Function FindWindowEx Lib "user32" _
                             Alias "FindWindowExW" ( _
                             ByVal hWndParent As Long, _
                             ByVal hWndChildAfter As Long, _
                             ByVal lpClassName As Long, _
                             ByVal lpWindowName As Long) As Long
    Private Declare Function GetProcessId Lib "kernel32" ( _
                             ByVal hProcess As OLE_HANDLE) As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32" ( _
                             ByVal hwnd As OLE_HANDLE, _
                             ByRef lpdwProcessId As Long) As Long
    Private Declare Function OpenProcess Lib "kernel32" ( _
                             ByVal dwDesiredAccess As Long, _
                             ByVal bInheritHandle As Long, _
                             ByVal dwProcessId As Long) As OLE_HANDLE
    Private Declare Function VirtualAllocEx Lib "kernel32.dll" ( _
                             ByVal hProcess As OLE_HANDLE, _
                             ByVal lpAddress As Long, _
                             ByVal dwSize As Long, _
                             ByVal flAllocationType As Long, _
                             ByVal flProtect As Long) As Long
    Private Declare Function WriteProcessMemory Lib "kernel32" ( _
                             ByVal hProcess As OLE_HANDLE, _
                             ByVal lpBaseAddress As Long, _
                             ByRef lpBuffer As Any, _
                             ByVal nSize As Long, _
                             ByRef lpNumberOfBytesWritten As Long) As Long
    Private Declare Function ReadProcessMemory Lib "kernel32" ( _
                             ByVal hProcess As OLE_HANDLE, _
                             ByVal lpBaseAddress As Long, _
                             ByRef lpBuffer As Any, _
                             ByVal nSize As Long, _
                             ByRef lpNumberOfBytesWritten As Long) As Long
    Private Declare Function VirtualFreeEx Lib "kernel32.dll" ( _
                             ByVal hProcess As OLE_HANDLE, _
                             ByVal lpAddress As Long, _
                             ByVal dwSize As Long, _
                             ByVal dwFreeType As Long) As Long
    Private Declare Function SendMessage Lib "user32" _
                             Alias "SendMessageW" ( _
                             ByVal hwnd As OLE_HANDLE, _
                             ByVal wMsg As Long, _
                             ByVal wParam As Long, _
                             ByRef lParam As Any) As Long
    Private Declare Function Sleep Lib "kernel32" ( _
                             ByVal dwMilliseconds As Long) As Long
                             
    Public Sub Main()
        Dim hProcess    As OLE_HANDLE
        Dim hTVWnd      As OLE_HANDLE
        Dim lPID        As Long
        Dim h64Current  As Currency
        Dim pMemory     As Long
        Dim lPass       As Long
        
        On Error GoTo CleanUp
        
        If Not modX64Call.Initialize Then
            MsgBox "Unable to initialize modX64Call", vbCritical
            Exit Sub
        End If
        
        hTVWnd = GetTVWindow(0)
        
        If hTVWnd = 0 Then
            
            hProcess = Run64BitRegEdit()
            
            If hProcess = 0 Then
                MsgBox "Unable to run regedit", vbCritical
                GoTo CleanUp
            End If
            
            For lPass = 0 To 2
            
                hTVWnd = GetTVWindow(0)
                
                If hTVWnd Then
                    Exit For
                End If
                
                Sleep 200
                
            Next
            
            If lPass = 2 Then
                MsgBox "Unable to find treeview", vbCritical
                GoTo CleanUp
            End If
            
        Else
        
            If GetWindowThreadProcessId(hTVWnd, lPID) = 0 Then
                MsgBox "GetWindowThreadProcessId failed", vbCritical
                GoTo CleanUp
            End If
            
            hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, lPID)
            
            If hProcess = 0 Then
                MsgBox "OpenProcess failed", vbCritical
                GoTo CleanUp
            End If
            
        End If
        
        pMemory = VirtualAllocEx(hProcess, 0, 4096, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
        
        If pMemory = 0 Then
            MsgBox "VirtualAllocEx failed", vbCritical
            GoTo CleanUp
        End If
        
        h64Current = SendMessageW64(hTVWnd, TVM_GETNEXTITEM, 0, TVGN_ROOT / 10000)
        
        If h64Current = 0 Then
            MsgBox "SendMessageW64 failed", vbCritical
            GoTo CleanUp
        End If
        
        DumpTV64 0, hProcess, hTVWnd, h64Current, pMemory
        
    CleanUp:
    
        If hProcess Then
            CloseHandle hProcess
        End If
        
        modX64Call.Uninitialize
    
    End Sub
    
    Private Sub DumpTV64( _
                ByVal lIdent As Long, _
                ByVal hProcess As OLE_HANDLE, _
                ByVal hwnd As OLE_HANDLE, _
                ByVal h64Item As Currency, _
                ByVal pMemory As Long)
        Dim tItem       As TVITEM64
        Dim h64Child    As Currency
        Dim sBuf        As String
        Dim lSize       As Long
        
        sBuf = Space$(260)
        
        tItem.pszText = (pMemory + 1024) / 10000
        tItem.mask = TVIF_TEXT
        tItem.cchTextMax = Len(sBuf)
        
        Do While h64Item <> 0@
            
            ' // Get text
            tItem.hItem = h64Item
    
            If WriteProcessMemory(hProcess, pMemory, tItem, LenB(tItem), 0) = 0 Then
                MsgBox "WriteProcessMemory failed", vbCritical
                Exit Sub
            End If
            
            If SendMessage(hwnd, TVM_GETITEM, 0, ByVal pMemory) = 0 Then
                MsgBox "SendMessageW64 failed", vbCritical
                Exit Sub
            End If
            
            If ReadProcessMemory(hProcess, pMemory + 1024, ByVal StrPtr(sBuf), LenB(sBuf), 0) = 0 Then
                MsgBox "ReadProcessMemory failed", vbCritical
                Exit Sub
            End If
        
            lSize = InStr(1, sBuf, vbNullChar)
            
            If lSize Then
                Debug.Print Space$(lIdent * 4) & Left$(sBuf, lSize - 1)
            End If
            
            h64Child = SendMessageW64(hwnd, TVM_GETNEXTITEM, TVGN_CHILD / 10000, h64Item)
            
            If h64Child <> 0 Then
                DumpTV64 lIdent + 1, hProcess, hwnd, h64Child, pMemory
            End If
            
            h64Item = SendMessageW64(hwnd, TVM_GETNEXTITEM, TVGN_NEXT / 10000, h64Item)
            
        Loop
        
    End Sub
    
    Private Function GetTVWindow( _
                     ByVal hProcess As OLE_HANDLE) As OLE_HANDLE
        Dim hwnd    As OLE_HANDLE
        Dim lPID    As Long
        Dim lPIDWnd As Long
        
        If hProcess Then
            lPID = GetProcessId(hProcess)
        End If
        
        Do
        
            hwnd = FindWindowEx(0, hwnd, StrPtr("RegEdit_RegEdit"), 0)
                
            If hwnd = 0 Then
                Exit Function
            End If
            
            If lPID Then
                If GetWindowThreadProcessId(hwnd, lPIDWnd) Then
                    If lPIDWnd = lPID Then
                    
                        GetTVWindow = FindWindowEx(hwnd, 0, StrPtr("SysTreeView32"), 0)
                        Exit Function
                    
                    End If
                End If
            Else
                GetTVWindow = FindWindowEx(hwnd, 0, StrPtr("SysTreeView32"), 0)
                Exit Function
            End If
            
        Loop While True
    
    End Function
    
    Private Function Run64BitRegEdit() As OLE_HANDLE
        Dim lFSRedirect As Long
        Dim tSI         As STARTUPINFO
        Dim tPI         As PROCESS_INFORMATION
        Dim hProcess    As OLE_HANDLE
        Dim lResult     As Long
        Dim sPath       As String
        Dim lSize       As Long
        
        sPath = Space$(MAX_PATH)
        lSize = GetWindowsDirectory(StrPtr(sPath), Len(sPath) + 1)
        sPath = Left$(sPath, lSize)
        
        If Wow64DisableWow64FsRedirection(lFSRedirect) = 0 Then
            Exit Function
        End If
        
        tSI.cb = Len(tSI)
        
        lResult = CreateProcess(StrPtr(sPath & "\regedit.exe"), 0, ByVal 0&, ByVal 0&, 0, 0, ByVal 0&, 0, tSI, tPI)
        
        Wow64RevertWow64FsRedirection lFSRedirect
        
        If lResult = 0 Then
            Exit Function
        End If
        
        CloseHandle tPI.hThread
        
        WaitForInputIdle tPI.hProcess, -1
        
        Run64BitRegEdit = tPI.hProcess
        
    End Function
    Attached Files Attached Files

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,731

    Re: [VB6] SendMessage - 64 bit compatible.

    I removed a couple of posts from this thread at the request of the original poster, because they deemed them off topic for what he wanted the thread to be. Personally, I don't have enough experience with the language or the subject to really know whether they were off topic or not, so I deferred to the OP. The thread did appear that it could have been its own thread in the CodeBank, though I'm not certain.
    My usual boring signature: Nothing

  3. #3
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,040

    Re: [VB6] SendMessage - 64 bit compatible.

    Quote Originally Posted by Shaggy Hiker View Post
    I removed a couple of posts from this thread at the request of the original poster, because they deemed them off topic for what he wanted the thread to be. Personally, I don't have enough experience with the language or the subject to really know whether they were off topic or not, so I deferred to the OP. The thread did appear that it could have been its own thread in the CodeBank, though I'm not certain.
    So the question I was asking is what happens if you come across another data type, which is the code inside.
    For data types such as long, strings are available, for date types, array types or cdecl, ArgType = vbDouble,vbDecimal,CallX64 is there more support

    Code:
    Public Function CallX64( _
    ByVal pfn64 As Currency, _
    ParamArray vArgs() As Variant) As Currency
    
     hr = DispCallFunc(ByVal 0&, m_pCodeBuffer, 4, vbCurrency, 0, ByVal 0&, ByVal 0&, vRet)
        GetMem4 0&, ByVal ArrPtr(bCode)
    Dim vRet        As Variant
    CallX64=vRet
    If the data returned is a string or array, can a type such as vbDecimal handle it?
    Also ask, is there a 32-bit address call module?

    Thank you very much for your contribution to this area, much of the code is so easy to understand
    Last edited by xiaoyao; May 15th, 2023 at 04:34 PM.

  4. #4
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    579

    Re: [VB6] SendMessage - 64 bit compatible.

    Great job The Trick as always brilliant

  5. #5
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    335

    Re: [VB6] SendMessage - 64 bit compatible.

    does this means we can use most of the x64 api now, like in user32 kerner32

  6. #6

  7. #7
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    335

    Re: [VB6] SendMessage - 64 bit compatible.

    can you write this code in twinBasic?

  8. #8

  9. #9
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    335

    Re: [VB6] SendMessage - 64 bit compatible.

    oh yes, forget it, there is no need for tb.

  10. #10
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,040

    Re: [VB6] SendMessage - 64 bit compatible.

    I found that you mainly posted a lot of theme articles in 2015. Source Code Example

    After 2023, no new articles were published.
    Your technology is very powerful, and I hope you can participate in the community development and improvement of twinbasic.

  11. #11
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,040

    Re: [VB6] SendMessage - 64 bit compatible.

    How to get the contents of x64 ListView, TreeView and the coordinates of each row and cell?

  12. #12
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,819

    Re: [VB6] SendMessage - 64 bit compatible.

    Sending LV messages isn't fundamentally different so you'd just follow the same way as the initial post... Import the 64bit defs you need substituting Currency for LongPtr.

    Though as brilliant as this is a proxy process made in tB would be far easier if you can't follow how the code here works, which is so ingenious it's difficult for me too.

  13. #13
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,040

    Re: [VB6] SendMessage - 64 bit compatible.

    Quote Originally Posted by fafalone View Post
    Sending LV messages isn't fundamentally different so you'd just follow the same way as the initial post... Import the 64bit defs you need substituting Currency for LongPtr.

    Though as brilliant as this is a proxy process made in tB would be far easier if you can't follow how the code here works, which is so ingenious it's difficult for me too.
    Perhaps the best way is to sort out all the 64-bit APIs.Like win32api.tlb, make a win32x64tlb, or API declare the source format.Then add a decision 32-bit 64-bit automatic switching.Plus a mode cross process.Maybe one day another computer will be able to operate. It's like Google Debug Protocol. Web socket interface
    You can directly operate the mobile phone browser. You can also operate web pages on Linux computers and mac computers.

    https://www.vbforums.com/showthread....be-need-x64-ap


    VB6 enumeration of all tray icons
    In the English version of the system, the control name for the taskbar tray area is "Notification Area". To retrieve all icons and programs in the taskbar tray area and simulate right-click operations, you can use the Windows API function ShellNotifyIcon to manipulate tray icons. Here is a basic step and example code

    why lngbuttons=0 in x64?

    why use SendMessage/SendMessageW64? not same?

    Win11 22H2 (10.0.22621) can't support TB_BUTTONCOUNT message of System Toolbar - Microsoft Q&A
    https://learn.microsoft.com/en-nz/an...-tb-buttoncoun

    Code:
     If SendMessage(hwnd, TVM_GETITEM, 0, ByVal pMemory) = 0 Then
                MsgBox "SendMessageW64 failed", vbCritical
                Exit Sub
            End If
            
            If ReadProcessMemory(hProcess, pMemory + 1024, ByVal StrPtr(sBuf), LenB(sBuf), 0) = 0 Then
                MsgBox "ReadProcessMemory failed", vbCritical
                Exit Sub
            End If
         
            
            h64Child = SendMessageW64(hwnd, TVM_GETNEXTITEM, TVGN_CHILD / 10000, h64Item)
    Last edited by xiaoyao; Jan 27th, 2025 at 07:45 AM.

  14. #14
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,819

    Re: [VB6] SendMessage - 64 bit compatible.

    Quote Originally Posted by xiaoyao View Post
    Perhaps the best way is to sort out all the 64-bit APIs.Like win32api.tlb, make a win32x64tlb, or API declare the source format.Then add a decision 32-bit 64-bit automatic switching.Plus a mode cross process.Maybe one day another computer will be able to operate. It's like Google Debug Protocol. Web socket interface
    You can directly operate the mobile phone browser. You can also operate web pages on Linux computers and mac computers.

    https://www.vbforums.com/showthread....be-need-x64-ap


    VB6 enumeration of all tray icons
    In the English version of the system, the control name for the taskbar tray area is "Notification Area". To retrieve all icons and programs in the taskbar tray area and simulate right-click operations, you can use the Windows API function ShellNotifyIcon to manipulate tray icons. Here is a basic step and example code

    why lngbuttons=0 in x64?

    why use SendMessage/SendMessageW64? not same?

    Win11 22H2 (10.0.22621) can't support TB_BUTTONCOUNT message of System Toolbar - Microsoft Q&A
    https://learn.microsoft.com/en-nz/an...-tb-buttoncoun

    Code:
     If SendMessage(hwnd, TVM_GETITEM, 0, ByVal pMemory) = 0 Then
                MsgBox "SendMessageW64 failed", vbCritical
                Exit Sub
            End If
            
            If ReadProcessMemory(hProcess, pMemory + 1024, ByVal StrPtr(sBuf), LenB(sBuf), 0) = 0 Then
                MsgBox "ReadProcessMemory failed", vbCritical
                Exit Sub
            End If
         
            
            h64Child = SendMessageW64(hwnd, TVM_GETNEXTITEM, TVGN_CHILD / 10000, h64Item)
    Well you'd need something far different from win32api.tlb for cross bitness work like this. The trick isn't simply calling user32.SendMessage here, he's reverse engineered it back to the undocumented native API calls plus a lot of other supporting work. There's no simple declares possible; every API it's possible to call this way would require tons of difficult reverse engineering work to discover them.

    If you use a tB proxy process for x64 work, you could use the normal APIs just with appropriate LongPtr and pointer size adjustments... And 99%+ of the Windows API you'd use can be made available just by checking a box for my Windows Development Library package, which supports both 32 and 64bit.

    Also you can't just treat the tray like a tree view.

  15. #15
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,040

    Re: [VB6] SendMessage - 64 bit compatible.

    Quote Originally Posted by fafalone View Post
    Well you'd need something far different from win32api.tlb for cross bitness work like this. The trick isn't simply calling user32.SendMessage here, he's reverse engineered it back to the undocumented native API calls plus a lot of other supporting work. There's no simple declares possible; every API it's possible to call this way would require tons of difficult reverse engineering work to discover them.

    If you use a tB proxy process for x64 work, you could use the normal APIs just with appropriate LongPtr and pointer size adjustments... And 99%+ of the Windows API you'd use can be made available just by checking a box for my Windows Development Library package, which supports both 32 and 64bit.

    Also you can't just treat the tray like a tree view.
    In the new version of the operating system, many controls in win11 have become WPF, and there is no way to get all the icons with Win32 API.I just tried it, and if the hidden icon that the mouse moved is clicked again, it will list some icons. In fact, this is for the blind. If you press the shortcut key or use the cursor up, down, left and right keys, it can switch to the next element. In fact, these methods cannot be implemented with the API at all

    For example, it used to be very complicated to get the URL in the task bar of Google Chrome, but it can also be obtained with this technology.
    https://www.vbforums.com/showthread....port-Container
    Can you try this latest source code, although not a few lines, right? But it took me nearly eight years.
    I used to use it like safe subclassing.
    If I unload the event for him in a custom space. I want to clean up this subclassed object. Vb6 form designer mode but often not triggered.
    If I place a breakpoint there, it will trigger, otherwise it will be forced to uninstall directly.
    But the security class, it can be implemented in the internal assembly, ah, to perform the unloading event.Thank you for your great efforts. How long have you been here? It's estimated that you have spent five or ten years.

    There is also a safe multithreading in the IDE.I use the method of copying the number of modules.
    Copy vb6 header memory information. If a project has three forms and two classes, there are five objects in total. 20 bytes need to be copied.

    But I failed to create a new window in VB6 IDE multithreading.
    This is already very good. Some Duoqingcheng can do a one-time run in the VB6 IDE.
    But I want to prevent accidentally clicking the pause button at any time. This will cause the collapse of idE.Even doing a debug. Print in multiple threads or sending some text message to my addin plugin will crash.
    I compile it into ah, and it is no problem for the application to run.
    Last edited by xiaoyao; Jan 27th, 2025 at 01:00 PM.

  16. #16

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width