views:

295

answers:

3

I want to get the ControlName of .NET properties in VB6 code, just like described in this article. But unfortunately, it doesn't work for me. I always got 0 for bufferMem.

        bufferMem = VirtualAllocEx(processHandle, 0, size, 
        MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
        If bufferMem = 0 Then
            Error Err, "VirtualAllocEx API Failed"
        End If

What am I doing wrong?

+1  A: 

Do you set the size beforehand?

size = 65536
DJ
A: 

Yes. But the buffer only can be defined up to 65526.

' Define the buffer that will eventually contain the desired
' component's name.
Dim bytearray As String * 65535

More than that there will be an error:

Compile error:

Invalid length for fixed-length string

Well we're not using bytearray yet before calling VirtualAllocEx, but still the output of that function is empty.

oliverikawood
A: 

Hi All,

I have managed VirtualAllocEx. Before I declared this function as Private. Then when I moved it to Module file and changed it to Public, I don't get 0 anymore for bufferMem. Also I need to set lpAddress as ByVal. Otherwise, the length of controlName that given is twice than correct length (I don't know exactly how this happens).

Declare Function VirtualAllocEx Lib "kernel32" _
                             (ByVal hProcess As Long, _
                             ByVal lpAddress As Long, _
                             ByVal dwSize As Long, _
                             ByVal flAllocationType As Long, _
                             ByVal flProtect As Long) As Long

Now I got the correct retLength, but unfortunately retVal is 0, return the error description: Invalid procedure call or argument.

If retLength <> 0 Then
          'Now read the component's name from the shared memory location.
              retVal = ReadProcessMemory(processHandle, bufferMem, bytearray, size, VarPtr(written))
              If retVal = 0 Then
                   Error Err 'ReadProcessMemory API Failed
              End If
          End If

My declaration of ReadProcessMemory is:

Declare Function ReadProcessMemory Lib "kernel32" _
                             (ByVal hProcess As Long, _
                             ByVal lpBaseAddress As Long, _
                             lpBuffer As Any, _
                             ByVal nSize As Long, _
                             lpNumberOfBytesRead As Long) As Long

And when I run the whole thing (ignore the retVal value), I got error in WideCharToMultiByte:

Function ByteArrayToString(bytes As String, length As Long) As String
   Dim retValStr As String
   Dim l As Long

   If IsWin9x() Then
       retValStr = Left(bytes, InStr(1, bytes, Chr(0)) - 1)
   Else
       retValStr = String$(length + 1, Chr(0))
       l = WideCharToMultiByte(CP_ACP, 0, bytes, -1, retValStr, length + 1, Null, Null)
   End If

   ByteArrayToString = retValStr
End Function

The error is saying:

Run-time error '94':

Invalid use of Null

Any idea?

Here is the code:

Function GetWindowsFormsID(ByVal wnd As Long) As String
    Dim PID As Long 'pid of the process that contains the control
    Dim msg As Long

    ' Define the buffer that will eventually contain the desired
    ' component's name.
    Dim bytearray As String * 65526

    ' Allocate space in the target process for the buffer as shared
    ' memory.
    Dim bufferMem As Long
    ' Base address of the allocated region for the buffer.
    Dim size As Long
    ' The amount of memory to be allocated.
    Dim written As Long
    ' Number of bytes written to memory.
    Dim retLength As Long
    Dim retVal As Long
    Dim errNum As Integer
    Dim errDescription As String

    size = 65527 'Len(bytearray)

    ' Creating and reading from a shared memory region is done
    ' differently in Win9x than in newer Oss.
    Dim processHandle As Long
    Dim fileHandle As Long

    msg = RegisterWindowMessage("WM_GETCONTROLNAME")

    If Not IsWin9x() Then
        On Local Error GoTo Error_Handler_NT
            Dim dwResult As Long
            Call GetWindowThreadProcessId(wnd, PID)

            processHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, PID)
            If processHandle = 0 Then
                Error Err 'OpenProcess API Failed
            End If

            bufferMem = VirtualAllocEx(processHandle, 0, size, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
            If bufferMem = 0 Then
                Error Err 'VirtualAllocEx API Failed
            End If

            ' Send message to the control's HWND for getting the
            ' Specified control name.
            retLength = SendMessage(wnd, msg, size, ByVal bufferMem)

            If retLength <> 0 Then
            ' Now read the component's name from the shared memory location.
                retVal = ReadProcessMemory(processHandle, bufferMem, bytearray, size, VarPtr(written))
                If retVal = 0 Then
                     Error Err 'ReadProcessMemory API Failed
                End If
            End If

Error_Handler_NT:
            errNum = Err
            errDescription = Error$
            ' Free the memory that was allocated.
            retVal = VirtualFreeEx(processHandle, bufferMem, 0, MEM_RELEASE)
            If retVal = 0 Then
                Error Err 'VirtualFreeEx API Failed
            End If
            CloseHandle (processHandle)
            If errNum <> 0 Then
                On Local Error GoTo 0
                Error errNum 'errDescription
            End If
        On Local Error GoTo 0


    Else
       On Local Error GoTo Error_Handler_9x

            Dim SA As SECURITY_ATTRIBUTES

            fileHandle = CreateFileMapping(INVALID_HANDLE_VALUE, SA, PAGE_READWRITE, 0, size, Null)
            If fileHandle = 0 Then
                Error Err 'CreateFileMapping API Failed
            End If
            bufferMem = MapViewOfFile(fileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
            If bufferMem = 0 Then
                Error Err 'MapViewOfFile API Failed
            End If

            Call CopyMemory(bufferMem, bytearray, size)

            ' Send message to the treeview control's HWND for
            ' getting the specified control's name.
            retLength = SendMessage(wnd, msg, size, bufferMem)

            ' Read the control's name from the specific shared memory
            ' for the buffer.
            Call CopyMemoryA(bytearray, bufferMem, 1024)

Error_Handler_9x:
            errNum = Err
            errDescription = Error$

            ' Unmap and close the file.
            UnmapViewOfFile (bufferMem)
            CloseHandle (fileHandle)

            If errNum <> 0 Then
                On Local Error GoTo 0
                Error errNum 'errDescription
            End If
        On Local Error GoTo 0

    End If

    If retLength <> 0 Then
    ' Get the string value for the Control name.
    GetWindowsFormsID = ByteArrayToString(bytearray, retLength)
    End If

End Function
oliverikawood