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