|
Hello,
I have an unmanaged API function and it's working great, just like it's suppose to return values. However, the API function only seems to be returning Strings in 32-bit versions of Windows. If I use the exact same API function and same code for calling the functions, it fails to return a String back in 64-bit Windows, even if I compile it with VS2008 on the 64-bit machine.The32-bit computer is Vista (NT 6), the 64-bit is Windows Server 2008 (NT 6). What are some possible reasons of why an API can return on one system, but not the other?
Regards, Adjutor - Moved byMartin Xie - MSFTMSFT, ModeratorThursday, August 13, 2009 2:23 AMMove it to 64-bit NETFx forum for better support. (From:Visual Basic General)
-
| | Adjutor | Hi Adjutor,
Maybe, the unmanaged API is not supported in 64-bit machine. However, a 32-bit application can run under WOW64 mode on 64-bit machine.
In order to make your 32-bit application work on a 64 bit system, the processor must be an X86.
Thus, please try the following settings:
Go to Project menu -> Properties -> Compile tab -> Select "Advanced Compile Options" -> Select "x86" instead of "AnyCPU"
Or go toBuild menu -> Configuration Manager -> Change Build Platform to X86. Then it will compile your project for 32-bit platform. Case:http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/22a7474c-b54d-4be0-928b-acc8b0a5a091
WOW64 is the x86 emulator that allows 32-bit Windows-based applications to run seamlessly on 64-bit Windows. Tutorial: http://msdn.microsoft.com/en-us/library/aa384249(VS.85).aspx
FAQ: Can I run 32-bit programs on a 64-bit computer? Most programs designed for a computer running a 32-bit version of Windows will work on a computer running 64-bit versions of Windows. Notable exceptions are many antivirus programs, and some hardware drivers.
Drivers designed for 32-bit versions of Windows do not work on computers running a 64-bit version of Windows. If you're trying to install a printer or other device that only has 32-bit drivers available, it won't work correctly on a 64-bit version of Windows. If you are unsure whether there is a 64-bit driver available for your device, go online to the Windows Vista Compatibility Center. Check this link about more 32-bit and 64-bit FAQs: http://windowshelp.microsoft.com/Windows/en-US/help/41531554-d5ef-4f2c-8fb9-149bdc5c8a701033.mspx
Best regards, Martin Xie
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback on our support, please contact msdnmg@microsoft.com | | Martin Xie - MSFT | Hello Martin!,
Thank you for the reply. I tried "Go to Project menu -> Properties -> Compile tab -> Select "Advanced Compile Options" -> Select "x86" instead of "AnyCPU"", doing this made the application get the returned values with API on x64! However, let's say I want this to be a 64-bit specific application, can I make my API work then? The API flag I am using is "LVM_GETITEMTEXT", is this x86 only?
Regards, Adjutor
| | Adjutor | That requires a declaration for the LVITEM structure. You probably got it wrong, pointers are 8 bytes instead of 4 on x64. Post your code.
Hans Passant. | | nobugz | Hello nobugz!, Thanks for the reply. Here is the code that I am using, it adds the text from a ListView into a TextBox named "info":
Private Sub GetListViewText(ByVal sender As Object, ByVal e As System.EventArgs)
Dim subitem As Integer
listviewHandle = Int32.Parse(txtHandle.Text)
Dim itemCount As Integer = SendMessage(listviewHandle, LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero)
' Aquire the amount of rows in the listview
Dim headerhandle As IntPtr = SendMessage(listviewHandle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero)
' Aquire the handle of the listviews header
Dim coloumcount As Integer = SendMessage(headerhandle, HDM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero)
' Aquire the amount of coloumns in the listview header
Dim id As Integer = -1
Dim p As Process
For Each p In Process.GetProcessesByName("testapplication")
id = p.Id
Next
Dim hProcess As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE Or &H8, False, id)
For index As Integer = 0 To itemCount - 1
' For each of the rows do the following :
For subitem = 0 To coloumcount
' For each of the columns do the following :
Dim lvi As New LV_ITEM
lvi.cchTextMax = 260
lvi.iSubItem = subitem
lvi.mask = 1
lvi.iItem = index
Dim pString As IntPtr = VirtualAllocEx(hProcess, IntPtr.Zero, 260, MEM_COMMIT, PAGE_READWRITE)
lvi.pszText = pString
Dim pLvItem As IntPtr = VirtualAllocEx(hProcess, IntPtr.Zero, Marshal.SizeOf(lvi), MEM_COMMIT, PAGE_READWRITE)
Dim success As Boolean = WriteProcessMemory(hProcess, pLvItem, lvi, Marshal.SizeOf(lvi), 0)
Dim result As Integer = SendMessage(listviewHandle, LVM_GETITEMTEXT, index, pLvItem)
Dim s As New StringBuilder(260)
success = ReadProcessMemory(hProcess, pString, s, 260, 0)
success = ReadProcessMemory(hProcess, pLvItem, lvi, Marshal.SizeOf(lvi), 0)
success = VirtualFreeEx(hProcess, pString, 0, MEM_RELEASE)
success = VirtualFreeEx(hProcess, pLvItem, 0, MEM_RELEASE)
s.AppendLine()
info.AppendText(s.ToString)
Next
Next
CloseHandle(hProcess)
End Sub
Regards, Adjutor | | Adjutor | You didn't post the crucial LVITEM declaration. Hacking an old 32-bit program like this with 64-bit code is kinda pointless and cannot work. You are not finding out because you do no error checking at all.
Hans Passant. | | nobugz | Hello nobugz, Alright, I'll post the LV_ITEM declaration:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure LV_ITEM
Public mask As UInteger
Public iItem As Integer
Public iSubItem As Integer
Public state As UInteger
Public stateMask As UInteger
Public pszText As IntPtr
Public cchTextMax As Integer
Public iImage As Integer
Public lParam As IntPtr
Public iIndent As Integer
Public iGroupId As Integer
Public cColumns As Integer
Public puColumns As IntPtr
Public piColFmt As IntPtr
Public iGroup As Integer
End Structure
I am not sure how it's "pointless", I need to view text on external application's ListView. If you have a suggestion of a better approach, then please say. Regards, Adjutor | | Adjutor | It's okay. Check the return value of VirtualAllocEx(), it is probably zero.
Hans Passant. | | nobugz | Hello,
Alright, I just checked the return values of both VirtualAllocEx() on lines pString and pLvItem. Both lines I get a value that is greater than 0, in the thousands.
Regards, Adjutor | | Adjutor | Hello nobugz,
Could this be an error in the 64-bit API? I stepped through each line today and it seems I do get valid pointer addresses returned. Does my LV_ITEM Structure need to be changed with Int64's?
Regards, Adjutor | | Adjutor | You shot down ever theory I had, I have none left. Why exactly does this need to be an x64 program?
Hans Passant. | | nobugz | Hello nobugz,
The computer that will be running this application is an x64 computer. I could of course compile as a 32-bit application using the WOW64 emulation method of 64-bit Windows as Martin suggested, but I just don't see why an API function that is suppose to be universal across Windows platforms would fail. It seemsI have found a bug in 64-bit API:).
Regards, Adjutor | | Adjutor | Hello nobugz,
Is there anyone else that might know why I get empty Strings back as a returned value?
Regards, Adjutor | | Adjutor |
|