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
Related
Hi currently I'm having this code below.
It retrieves the filename of open excel document from process and displays it.
For now it can retrieve it from my own pc, but when I wanted to remotely retrieves it from other pc, it doesn't work.
I have authorized access and I could actually get the process id and name of remote pcs only.
Dim w As Object
Dim processQ As String
Dim processes As Object
Dim processA As Object
Dim pname As String
w = GetObject("winmgmts:{impersonationLevel=impersonate}\\" & pc & "\root\cimv2")
processQ = "SELECT * FROM win32_process WHERE name = 'EXCEL.EXE'"
processes = w.execquery(processQ)
For Each processA In processes
activeprocess = Process.GetProcessById(processA.processid)
MsgBox(processA.processid & processA.name)
Dim windows As IDictionary(Of IntPtr, String) = GetOpenWindowsFromPID(processA.processid)
MsgBox(windows.Count())
For Each kvp As KeyValuePair(Of IntPtr, String) In windows
Dim value As String = kvp.Value.ToString
If InStr(value, "Excel") = False Then
MsgBox(value)
End If
Next
Next
Can anyone tell me what should I do and what's wrong with this?
<DllImport("USER32.DLL")>
Private Shared Function GetShellWindow() As IntPtr
End Function
<DllImport("USER32.DLL")>
Private Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function
<DllImport("USER32.DLL")>
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function
<DllImport("USER32.DLL", SetLastError:=True)>
Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, <Out()> ByRef lpdwProcessId As UInt32) As UInt32
End Function
<DllImport("USER32.DLL")>
Private Shared Function IsWindowVisible(ByVal hwnd As IntPtr) As Boolean
End Function
Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
<DllImport("USER32.DLL")>
Private Shared Function EnumWindows(ByVal enumFunc As EnumWindowsProc, ByVal lParam As Integer) As Boolean
End Function
Private hShellWindow As IntPtr = GetShellWindow()
Private dictWindows As New Dictionary(Of IntPtr, String)
Private currentProcessID As Integer
Public Function GetOpenWindowsFromPID(ByVal processID As Integer) As IDictionary(Of IntPtr, String)
dictWindows.Clear()
currentProcessID = processID
EnumWindows(AddressOf enumWindowsInternal, 0)
Return dictWindows
End Function
Public Function enumWindowsInternal(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
If (hwnd <> hShellWindow) Then
Dim windowPid As UInt32
If Not IsWindowVisible(hwnd) Then
Return True
End If
Dim length As Integer = GetWindowTextLength(hwnd)
If (length = 0) Then
Return True
End If
GetWindowThreadProcessId(hwnd, windowPid)
If (windowPid <> currentProcessID) Then
Return True
End If
Dim stringBuilder As New StringBuilder(length)
GetWindowText(hwnd, stringBuilder, (length + 1))
dictWindows.Add(hwnd, stringBuilder.ToString)
End If
Return True
End Function
Sorry I'm quite new to vb.net.. but I'm learning thanks!
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
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)
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.
OK, this problem has been bugging me for a long time.
I have the code for the service which communicates a string to the client via PostMessage:
Public Sub SendToClient(msgs As String, types As Integer, hwnd As Long)
postMessage(hwnd, 0, Nothing, msgs)
End Sub
Then I have the client that receives the string:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If (m.Msg = 0) Then
Dim a as string
a = Marshal.PtrToStringAuto(m.LParam)
end if
MyBase.WndProc(m)
End Sub
However, the client sends an error, or some jumble of binary data or even just a blank string sometimes. By the way, the m.LParam is a number.
Can someone tell me what is the right way to send/receive strings via postmessage.
I do it like this:
Public Sub SendMessageToApp(ByVal NombreVentana As String, ByVal Mensaje As String, ByVal sender As Form)
Dim hWnd As IntPtr
Dim mCopyData As COPYDATASTRUCT
hWnd = CType(FindWindow(Nothing, NombreVentana), IntPtr)
Dim message As New System.Text.StringBuilder
If (CInt(hWnd) <> 0) Then
message.Append(Mensaje)
Dim pCopyData As IntPtr = Marshal.AllocHGlobal(message.Length() + 40)
mCopyData.lpData = Marshal.StringToHGlobalAnsi(message.ToString)
mCopyData.cbData = message.Length
mCopyData.dwData = CType(_messageID, IntPtr)
Marshal.StructureToPtr(mCopyData, pCopyData, False)
SendMessage(hWnd, WM_COPYDATA, CInt(sender.Handle), pCopyData)
Marshal.FreeHGlobal(mCopyData.lpData)
Marshal.FreeHGlobal(pCopyData)
End If
End Sub
Receiver window:
Declarations and definitions:
Const WM_COPYDATA As Integer = 74
Const SIG_LENGTH As Integer = 36
Const MAX_COPY_LENGTH As Integer = 128
Const SigConnect As String = "F7B82657-BD18-4ee6-B182-78721293821C"
Dim CDCount As Integer
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As IntPtr) As Integer
Dim hWndSender As Integer
Private Const _messageID As Integer = 10
'Estructura obligatoria para poder utilizar el API CopyData
<StructLayout(LayoutKind.Sequential)> _
Private Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cbData As Integer
Public lpData As IntPtr
End Structure
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_COPYDATA Then
Dim Estructura As COPYDATASTRUCT
Dim tipo As Type = Estructura.GetType
Dim message As String
Estructura = CType(m.GetLParam(GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
'Here you get the message
message = Marshal.PtrToStringAnsi(Estructura.lpData, Estructura.cbData)
End If