VB.net use callback managed from dll unmanaged - vb.net

I want to use a function from a dll :
<DllImport("netXTransport.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto, ExactSpelling:=True)> _
Public Shared Function xSysdeviceUpload(ByVal hSysdevice As IntPtr, ByVal ulChannel As UInt32, ByVal ulMode As UInt32, ByVal pszFileName As IntPtr, ByVal pabFileData As IntPtr, ByVal pulFileSize As IntPtr, ByVal pfnCallback As PFN_NXAPI_PROGRESS_CALLBACK, ByVal pfnRecvPktCallback As PFN_NXAPI_BROWSE_CALLBACK, ByVal pvUser As IntPtr) As Int32
End Function
with
Public Delegate Sub PFN_NXAPI_PROGRESS_CALLBACK(ByVal ulStep As UInt32, ByVal ulMaxStep As UInt32, ByVal pvUser As IntPtr, ByVal bFinished As Char, ByVal lError As Int32)
(for information the C interface is :
int32_t APIENTRY xSysdeviceUpload(CIFXHANDLE hSysdevice, uint32_t ulChannel, uint32_t ulMode, char* pszFileName, uint8_t* pabFileData, uint32_t* pulFileSize, PFN_PROGRESS_CALLBACK pfnCallback, PFN_RECV_PKT_CALLBACK pfnRecvPktCallback, void* pvUser)`;)
My pfnCallback function is done in managed memory (vb.net) :
<AllowReversePInvokeCalls()>
Public Shared Sub TCPRenderProgressBar(ByVal ulStep As UInt32, ByVal ulMaxStep As UInt32, ByVal pvUser As IntPtr, ByVal bFinished As Char, ByVal lError As Int32)
End Sub
therefore I did this in my code to use the function :
Dim pFile As IntPtr = Marshal.AllocHGlobal(CInt(FileLength))
Dim pFileLength As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(FileLength))
Dim pszFileName As IntPtr = Marshal.AllocHGlobal(szFileName.Length)
Dim Temp() As Byte = g_encoding.GetBytes(szFileName & " ")
Temp(szFileName.Length) = 0
Marshal.Copy(Temp, 0, pszFileName, (szFileName.Length + 1))
iResult = xSysdeviceUpload(g_hSysdevice, 0, DOWNLOAD_MODE_FILE, pszFileName, pFile, pFileLength, AddressOf TCPRenderProgressBar, Nothing, Nothing)
All run good if no callback is declared (AddressOf TCPRenderProgressBar replaced by anything), but if I declare (AddressOf) TCPRenderProgressBar, I saw that I pass in function TCPRenderProgressBar but I an error AccessViolationException after...
What is the problem ?
Thank you for your help

Related

CryptAcquireContext "The Keyset is not defined" Error

CryptAcquireContext function returns FALSE with The Keyset is not defined error message. Here is my code.
<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function CryptAcquireContext(ByRef hProv As IntPtr, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Int32, ByVal dwFlags As UInt32) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)>
Public Shared Function CryptCreateHash(ByVal hProv As IntPtr, ByVal Algid As Int32, ByVal hKey As IntPtr, ByVal dwFlags As Int32, ByRef phHash As IntPtr) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)>
Public Shared Function CryptHashData(ByVal hHash As IntPtr, ByVal pbData() As Byte, ByVal dwDataLen As Int32, ByVal dwFlags As Int32) As Boolean
End Function
Public Const PROV_RSA_FULL As Int32 = 1
Private Const CRYPT_VERIFYCONTEXT As UInt32 = &HF0000000UI
Private Function GetHash(ByVal text As String) As Boolean
Dim bResult As Boolean = False
Dim hProv As IntPtr
Dim hHash As IntPtr
If CryptAcquireContext(hProv, vbNull, vbNull, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then
If CryptCreateHash(hProv, CALG_SHA1, 0, 0, hHash) Then
If CryptHashData(hHash, Encoding.ASCII.GetBytes(text), text.Length, 0) Then
Dim bHash(20) As Byte
Dim dwHashLen As Int32 = Marshal.SizeOf(bHash)
bResult = CryptGetHashParam(hHash, HP_HASHVAL, bHash, dwHashLen, 0)
If bResult = True Then
//Rest of string operations
End If
End If
End If
End If
Dim errorMessage As String = New Win32Exception(Marshal.GetLastWin32Error()).Message
MsgBox(errorMessage)
Return bResult
End Function
Do you have any idea about what i'm doing wrong?
Thanks

System.ArgumentException: Win32 handle that was passed to Icon is not valid or is the wrong type

I have the below code to load an icon using Shell32 dll. It works fine on my machine. But one of the systems in production environment got an exception saying "System.ArgumentException: Win32 handle that was passed to Icon is not valid or is the wrong type".
Any idea why we get this error? Thank you!
Public Function GetExecutableIcon() As Icon
Dim large As IntPtr
Dim small As IntPtr
ExtractIconEx(Application.ExecutablePath, 0, large, small, 1)
Return Icon.FromHandle(small)
End Function
<DllImport("Shell32")> _
Public Shared Function ExtractIconEx(ByVal sFile As String, ByVal iIndex As Integer,
ByRef piLargeVersion As IntPtr, ByRef piSmallVersion As IntPtr,
ByVal amountIcons As Integer) As Integer
End Function
Try this:
<DllImport("Shell32")> _
Public Shared Function ExtractIconEx(ByVal sFile As String, ByVal iIndex As Integer,
ByRef piLargeVersion As IntPtr, ByRef piSmallVersion As IntPtr,
ByVal amountIcons As Integer) As Integer
Public Function GetExecutableIcon() As Icon
Dim num As Integer = 10
Dim large(num - 1) As IntPtr
Dim small(num - 1) As IntPtr
ExtractIconEx("C:\Windows\System32\Shell32.dll", 0, large(0), small(0), num)
Return Icon.FromHandle(small(6)) 'change the index accordingly
End Function
Is your declaration correct? http://www.pinvoke.net/default.aspx/shell32.ExtractIconEx shows
<DllImport("shell32.dll", CharSet:=CharSet.Auto)> _
Shared Function ExtractIconEx(ByVal szFileName As String, _
ByVal nIconIndex As Integer, _
ByVal phiconLarge() As IntPtr, _
ByVal phiconSmall() As IntPtr, _
ByVal nIcons As UInteger) As UInteger
End Function

CryptEncrypt/CryptDecrypt WinAPI functions fail when called from vb.net

Any help with the following greatly appreciated.....
I have some C++ code I've inherited which decrypts certain structures/byte arrays; I've been trying to write a test program in VB.net which exactly mimics the C++ decryption routine using the same functions, ie. using the WinAPI Crypto calls; in testing, CryptAcquireContext, CryptCreateHash, CryptHashData and CryptDeriveKey all succeed;
However, both the CryptEncrypt and CryptDecrypt functions fail with the Invalid Parameter error, even in the most simple scenario;
(I am aware of the System.Security.Cryptography namespace...and I will resort to this...but the C++ code includes structures with unions, and for testing, it seemed better to try the WinAPI route first)
the sample code is below...I am on Win7x64 sp1, vs 2010 sp1...
Private Sub cmdTest(sender As System.Object, e As System.EventArgs) Handles cmdtest.Click
Dim hCrypt As IntPtr
Dim hSecretHash, hUserHash As IntPtr
Dim hSecretKey As IntPtr
Dim success As Boolean
If CryptAcquireContext(hCrypt, vbNullString, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then
'create hash
success = CryptCreateHash(hCrypt, CALG_MD5, 0, 0, hSecretHash)
'hash stage 1
success = CryptHashData(hSecretHash, Encoding.ASCII.GetBytes("yyyyyy"), "xxxxxx".length, 0)
success = CryptHashData(hSecretHash, Encoding.ASCII.GetBytes("yyyyyy"), "yyyyyy".length, 0)
'derive key
success = CryptDeriveKey(hCrypt, CALG_RC4, hSecretHash, 0, hSecretKey)
Dim newb(127) As Byte
Dim teststring As String = "Testing"
Dim testbytes() As Byte = Encoding.ASCII.GetBytes(teststring)
Buffer.BlockCopy(testbytes, 0, newb, 0, testbytes.Length)
Dim inputlength As UShort = Convert.ToUInt16(testbytes.Length)
Dim newblength As UShort = CUShort(newb.Length)
Dim bufferlength As UShort = newblength
'---------------BOTH THESE FAIL (all above OK)
success = CryptEncrypt(hSecretKey, 0, True, 0, newb, newblength, inputlength)
success = CryptDecrypt(hSecretKey, 0, True, 0, newb, newblength)
'--------------------------------------------
'Destroy the user keycode
CryptDestroyHash(hUserHash)
'Destroy the secret key
CryptDestroyKey(hSecretKey)
CryptDestroyHash(hSecretHash)
'Release the provider
CryptReleaseContext(hCrypt, 0)
End If
End Sub
Public Const ALG_CLASS_DATA_ENCRYPT As Int32 = 24576
Public Const ALG_CLASS_HASH As Int32 = 32768
Public Const ALG_TYPE_ANY As Int32 = 0
Public Const ALG_SID_RC4 As Int32 = 1
Public Const ALG_SID_RC2 As Int32 = 2
Public Const ALG_SID_MD5 As Int32 = 3
Public Const ALG_SID_SHA1 As Int32 = 4
Public Const ALG_SID_MAC As Int32 = 5
Public Const ALG_SID_HMAC As Int32 = 9
Public Const ALG_TYPE_BLOCK As Int32 = 1536
Public Const ALG_TYPE_STREAM As Int32 = 2048
Public Const CALG_MD5 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MD5
Public Const CALG_RC2 As Int32 = ALG_CLASS_DATA_ENCRYPT + ALG_TYPE_BLOCK + ALG_SID_RC2
Public Const CALG_RC4 As Int32 = ALG_CLASS_DATA_ENCRYPT + ALG_TYPE_STREAM + ALG_SID_RC4
Public Const CALG_SHA1 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA1
Public Const CALG_MAC As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MAC
Public Const CALG_HMAC As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_HMAC
Public Const PROV_RSA_FULL As Int32 = &H1
Public Const CRYPT_VERIFYCONTEXT As Int32 = &HF0000000
Public Const HP_ALGID As Int32 = 1
Public Const HP_HASHVAL As Int32 = 2
Public Const HP_HASHSIZE As Int32 = 4
Public Const HP_HMAC_INFO As Int32 = 5
Public Const MS_DEF_PROV As String = "Microsoft Base Cryptographic Provider v1.0"
'Imported Functions:
<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function CryptAcquireContext( _
ByRef hProv As IntPtr, _
ByVal pszContainer As String, _
ByVal pszProvider As String, _
ByVal dwProvType As Int32, _
ByVal dwFlags As Int32 _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)>
Public Shared Function CryptEncrypt( _
ByVal hKey As IntPtr, _
ByVal hHash As IntPtr, _
ByVal Final As Boolean, _
ByVal dwFlags As UShort, _
pbData() As Byte, _
pdwDataLen As UShort, _
ByVal dwBufLen As UShort) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function CryptDecrypt( _
ByVal hKey As IntPtr, _
ByVal hHash As IntPtr, _
ByVal Final As Boolean, _
ByVal dwFlags As UShort, _
pbData() As Byte, _
pdwDataLen As UShort _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Public Shared Function CryptCreateHash( _
ByVal hProv As IntPtr, _
ByVal Algid As Int32, _
ByVal hKey As IntPtr, _
ByVal dwFlags As Int32, _
ByRef phHash As IntPtr _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Public Shared Function CryptDestroyHash( _
ByVal hHash As IntPtr _
) As Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Public Shared Function CryptHashData( _
ByVal hHash As IntPtr, _
ByVal pbData() As Byte, _
ByVal dwDataLen As Int32, _
ByVal dwFlags As Int32 _
) As Boolean
End Function
<DllImport("advapi32.dll", setlasterror:=True)> _
Public Shared Function CryptDeriveKey( _
ByVal hProv As IntPtr, _
ByVal Algid As Integer, _
ByVal hBaseData As IntPtr, _
ByVal dwflags As Integer, _
ByRef phKey As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("advapi32.dll", SetLastError:=True)> _
Public Shared Function CryptDestroyKey( _
ByVal hKey As IntPtr _
) As Boolean
End Function
The Final parameter of CryptEncrypt is a BOOL, which is a 32-bit int. Try changing the parameter to Final as int32,or use MarshalAs(UnmanagedType.Bool)
Could be more things, but immediately ByVal dwFlags As UShort looks off to me.
The msdn lists that parameter as:
DWORD dwFlags,
A DWORD is 4 bytes, so would be an Int32 or Integer (in VB.NET)

Write text to Win32 Resources

I am trying to write text to Win32 resources, but I have failed with it.
Here it is after writing the text:
And here is how it should look like:
Here's my code:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
WriteResourceStr(Target.Text, "hello")
End Sub
#Region "Second"
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, ByVal lpType As String, ByVal lpName As String, ByVal wLanguage As UShort, ByVal lpData As IntPtr, ByVal cbData As UInteger) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function BeginUpdateResource(ByVal pFileName As String, <MarshalAs(UnmanagedType.Bool)> ByVal bDeleteExistingResources As Boolean) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function EndUpdateResource(ByVal hUpdate As IntPtr, ByVal fDiscard As Boolean) As Boolean
End Function
Public Function WriteResourceStr(ByVal filename As String, ByVal bytes As String) As Boolean
Try
Dim handle As IntPtr = BeginUpdateResource(filename, False)
Dim file1 As String = bytes
Dim fileptr As IntPtr = ToPtr(file1)
Dim res As Boolean = UpdateResource(handle, "RCData", "CONFIG", 1, fileptr, System.Convert.ToUInt16(file1.Length))
EndUpdateResource(handle, False)
Catch ex As Exception
Return False
End Try
Return True
End Function
Private Function ToPtr(ByVal data As Object) As IntPtr
Dim h As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
Dim ptr As IntPtr
Try
ptr = h.AddrOfPinnedObject()
Finally
h.Free()
End Try
Return ptr
End Function
#End Region
So seems like it doesn't write ANSI, but in Unicode. How to change that?
Hopefully somebody replies.
The simplest way to get this is to just overload UpdateResource and let Windows make the Unicode to ANSI conversion for you:
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, _
ByVal lpType As String, ByVal lpName As String, ByVal wLanguage As UShort,
ByVal lpData As String, ByVal cbData As Integer) As Boolean
End Function
Note the changed lpData type and the changed CharSet. The call now simply becomes:
Dim handle As IntPtr = BeginUpdateResource(filename, False)
If handle = IntPtr.Zero Then Throw New Win32Exception
Dim res As Boolean = UpdateResource(handle, "RCData", "CONFIG", 1, _
bytes, bytes.Length)
If Not EndUpdateResource(handle, False) Then Throw New Win32Exception
I'll have to restate the nonsensical nature of the call. RCData is a numbered resource type and not a string. Using a language ID of 1 makes little sense, that's Arabic so you wouldn't expect a Latin string in the resource. Whatever app reads this resource is unlikely to find it back.
Doing this correctly would require an overload that declares lpType as IntPtr so you can pass CType(10, IntPtr) for the RT_RCData resource type. The ToPtr() function is extremely evil, it returns a dangling pointer that will cause random data corruption. Just let the pinvoke marshaller generate the pointer by declaring the lpData argument as Byte(). You'd then use Encoding.GetBytes() to use the proper ANSI conversion. Thus:
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function UpdateResource(ByVal hUpdate As IntPtr, _
ByVal lpType As IntPtr, ByVal lpName As String, ByVal wLanguage As UShort,
ByVal lpData As Byte(), ByVal cbData As Integer) As Boolean
End Function
With an additional overload required if lpName is a numbered instead of a named resource, use IntPtr.

Get Text From Specific Textboxes From External Application - Visual Basic .Net

I can get text from external application text box but now I want to get text from my desired text box from external application.
My English is not so good that's why see Image Below.
The Below Code Return The First Text Box Value Only.
Imports System.Runtime.InteropServices
Public Class Form1
Private Const WM_GETTEXT As Integer = &HD
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Find the running notepad window
Dim Hwnd As IntPtr = FindWindow(Nothing, TextBox1.Text)
'Alloc memory for the buffer that recieves the text
Dim Handle As IntPtr = Marshal.AllocHGlobal(100)
'send WM_GWTTEXT message to the notepad window
Dim NumText As Integer = SendMessage(Hwnd, WM_GETTEXT, 50, Handle)
'copy the characters from the unmanaged memory to a managed string
Dim Text As String = Marshal.PtrToStringUni(Handle)
'Display the string using a label
Label1.Text = Text
'Find the Edit control of the Running Notepad
Dim ChildHandle As IntPtr = FindWindowEx(Hwnd, IntPtr.Zero, "Edit", Nothing)
'Alloc memory for the buffer that recieves the text
Dim Hndl As IntPtr = Marshal.AllocHGlobal(200)
'Send The WM_GETTEXT Message
NumText = SendMessage(ChildHandle, WM_GETTEXT, 200, Hndl)
'copy the characters from the unmanaged memory to a managed string
Text = Marshal.PtrToStringUni(Hndl)
'Display the string using a label
Label2.Text = Text
End Sub
End Class
You'll have to loop through children of the main window (External Application) and get their properties.
You'll use the following:
<DllImport("User32.dll")> _
Public Function EnumChildWindows _
(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
ByVal lParam As IntPtr) As Boolean
End Function
Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
Public Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
Dim ChildrenList As New List(Of IntPtr)
Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
Try
EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
Finally
If ListHandle.IsAllocated Then ListHandle.Free()
End Try
Return ChildrenList.ToArray
End Function
For for details, check this How can I get properties of controls contained in a popup message box using VB.Net
' try this on excel vbe
External_application_handle=findwindow(vbNullString,"External_application")
textbox_1_handle=findwindowex(External_application_handle,0&,"Edit",vbNullString)
next_handle=textbox_1_handle
textbox_2_handle=findwindowex(External_application_handle,next_handle,"Edit",vbNullString")
Length = SendMessage(textbox_2_handle, WM_GETTEXTLENGTH, 0,0)
buffer$=space(Length)
call sendmessage(textbox_2_handle,Length+1,buffer$)
msgbox buffer