为什么长数据类型适用于此编组?
Why long datatype work for this marshalling?
我对 .Net 以外的知识非常有限 - 但我花了很多时间阅读许多相关文章。
HCRYPTPROV datatype documentaion 表示它是 ULONG_PTR
.
类型
以下参考文献建议使用与此对应的IntPtr
。
- Is there a definitive guide to cross platform (x86 and x64) PInvoke and windows data types?
- Using MS crypto library on server 2012 - CryptCreateHash error code 87: ERROR_INVALID_PARAMETER
- Calling AuditQuerySystemPolicy() (advapi32.dll) from C# returns "The parameter is incorrect"
但是,在下面的代码中我使用了 long
数据类型并且它工作得很好。是否有任何情况会给出不正确的结果?它与 long
一起工作的原因是什么?
Framework: .Net 2.0;
Architecture: 64 Bit;
OS: Windows Server 2012 R2;
Visual Studio: 2013
代码
Module Module1
Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" ( _
ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, _
ByVal dwProvType As Integer, ByVal dwFlags As Integer) As Integer
Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, _
ByVal Algid As Integer, ByVal hKey As Integer, ByVal dwFlags As Integer, _
ByRef phHash As Integer) As Integer
Private Declare Function GetLastError Lib "kernel32" () As Integer
Sub Main()
Dim sClearText As String
sClearText = "test1"
Dim lHCryptprov As Long
Dim sProvider As String
Const MS_DEF_PROV As String = "Microsoft Base Cryptographic Provider v1.0"
Dim lHHash As Integer
Dim sInputBuffer As String
Const ALG_CLASS_HASH As Integer = 32768
Const ALG_TYPE_ANY As Integer = 0
Const ALG_SID_MD5 As Integer = 3
Const PROV_RSA_FULL As Integer = 1
Const CRYPT_MACHINE_KEYSET As Integer = &H20
Const CALG_MD5 As Integer = ((ALG_CLASS_HASH Or ALG_TYPE_ANY) Or ALG_SID_MD5)
sInputBuffer = sClearText
'Get handle to the default CSP
sProvider = MS_DEF_PROV & vbNullChar
Dim errorCode As Integer
Dim r As Long
r = CryptAcquireContext(lHCryptprov, "", sProvider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)
errorCode = GetLastError()
Dim hashResult As Boolean
hashResult = CBool(CryptCreateHash(lHCryptprov, CALG_MD5, 0, 0, lHHash))
errorCode = GetLastError()
Console.WriteLine(hashResult)
Console.ReadLine()
End Sub
End Module
Architecture: 64 Bit;
这最有可能让您远离麻烦。 ULONG_PTR 是一个整数类型,其大小取决于进程的位数。在 32 位进程中它是 32 位,在 64 位进程中它是 64 位。最直接的 .NET 等效类型是 UIntPtr
.
这里的用法是作为句柄,实际值无所谓。您不对该值进行任何算术运算,您从 CryptAcquireContext() 获取它并简单地将它传递给 CryptCreateHash()。因此,您在 pinvoke 声明中 select 的类型是有符号的还是无符号的都没有关系。 IntPtr
是更常见的建议的原因,它是 [CLSCompliant] 类型。
VB.NET中的一个Long
是64位有符号整数类型。因此当您的程序作为 64 位进程运行时匹配 ULONG_PTR。
如果没有,您可能会遇到麻烦。要么因为你的程序运行在 32 位操作系统的机器上,要么当你在 VS2013 上使用默认设置新建项目时。相关的设置是Project > Properties > Compile tab > Target CPU。将其从 AnyCPU 更改为 x86 会遇到麻烦。请注意还有 "Prefer 32-bit" 复选框,它被禁用是因为您的目标是 .NET 2.0
当您在进行此更改后启动您的程序时,您现在应该在调用 CryptCreateHash() 时获得调试器中断。有一个名为 PInvokeStackImbalance 的专用托管调试助手,它应该会注意到当函数 returns 时堆栈失调了 4 个。并调用调试器中断来告诉您它。堆栈不平衡是一个非常严重的问题,可能导致任意程序失败,包括但不限于此站点命名的问题,尤其是在发布版本中。没有 MDA 帮助很难调试。
没有必要故意弄错,请改用 IntPtr
以使其与本机类型匹配。更正确的是当你声明它 HandleRef
instead. That's a wrapper that ensures that the handle cannot be destroyed while the native code is busy executing and should be used if you have a Finalize() method that calls CryptReleaseContext(). Even more correct is to use a safe handle wrapper type, like the .NET Framework does 时,它有一个关键的终结器,即使程序严重崩溃也会运行。仅当您的代码在非托管托管程序内部运行时才是真正必要的,SQL 服务器作为常见示例。
我对 .Net 以外的知识非常有限 - 但我花了很多时间阅读许多相关文章。
HCRYPTPROV datatype documentaion 表示它是 ULONG_PTR
.
以下参考文献建议使用与此对应的IntPtr
。
- Is there a definitive guide to cross platform (x86 and x64) PInvoke and windows data types?
- Using MS crypto library on server 2012 - CryptCreateHash error code 87: ERROR_INVALID_PARAMETER
- Calling AuditQuerySystemPolicy() (advapi32.dll) from C# returns "The parameter is incorrect"
但是,在下面的代码中我使用了 long
数据类型并且它工作得很好。是否有任何情况会给出不正确的结果?它与 long
一起工作的原因是什么?
Framework: .Net 2.0;
Architecture: 64 Bit;
OS: Windows Server 2012 R2;
Visual Studio: 2013
代码
Module Module1
Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
Alias "CryptAcquireContextA" ( _
ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, _
ByVal dwProvType As Integer, ByVal dwFlags As Integer) As Integer
Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, _
ByVal Algid As Integer, ByVal hKey As Integer, ByVal dwFlags As Integer, _
ByRef phHash As Integer) As Integer
Private Declare Function GetLastError Lib "kernel32" () As Integer
Sub Main()
Dim sClearText As String
sClearText = "test1"
Dim lHCryptprov As Long
Dim sProvider As String
Const MS_DEF_PROV As String = "Microsoft Base Cryptographic Provider v1.0"
Dim lHHash As Integer
Dim sInputBuffer As String
Const ALG_CLASS_HASH As Integer = 32768
Const ALG_TYPE_ANY As Integer = 0
Const ALG_SID_MD5 As Integer = 3
Const PROV_RSA_FULL As Integer = 1
Const CRYPT_MACHINE_KEYSET As Integer = &H20
Const CALG_MD5 As Integer = ((ALG_CLASS_HASH Or ALG_TYPE_ANY) Or ALG_SID_MD5)
sInputBuffer = sClearText
'Get handle to the default CSP
sProvider = MS_DEF_PROV & vbNullChar
Dim errorCode As Integer
Dim r As Long
r = CryptAcquireContext(lHCryptprov, "", sProvider, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)
errorCode = GetLastError()
Dim hashResult As Boolean
hashResult = CBool(CryptCreateHash(lHCryptprov, CALG_MD5, 0, 0, lHHash))
errorCode = GetLastError()
Console.WriteLine(hashResult)
Console.ReadLine()
End Sub
End Module
Architecture: 64 Bit;
这最有可能让您远离麻烦。 ULONG_PTR 是一个整数类型,其大小取决于进程的位数。在 32 位进程中它是 32 位,在 64 位进程中它是 64 位。最直接的 .NET 等效类型是 UIntPtr
.
这里的用法是作为句柄,实际值无所谓。您不对该值进行任何算术运算,您从 CryptAcquireContext() 获取它并简单地将它传递给 CryptCreateHash()。因此,您在 pinvoke 声明中 select 的类型是有符号的还是无符号的都没有关系。 IntPtr
是更常见的建议的原因,它是 [CLSCompliant] 类型。
VB.NET中的一个Long
是64位有符号整数类型。因此当您的程序作为 64 位进程运行时匹配 ULONG_PTR。
如果没有,您可能会遇到麻烦。要么因为你的程序运行在 32 位操作系统的机器上,要么当你在 VS2013 上使用默认设置新建项目时。相关的设置是Project > Properties > Compile tab > Target CPU。将其从 AnyCPU 更改为 x86 会遇到麻烦。请注意还有 "Prefer 32-bit" 复选框,它被禁用是因为您的目标是 .NET 2.0
当您在进行此更改后启动您的程序时,您现在应该在调用 CryptCreateHash() 时获得调试器中断。有一个名为 PInvokeStackImbalance 的专用托管调试助手,它应该会注意到当函数 returns 时堆栈失调了 4 个。并调用调试器中断来告诉您它。堆栈不平衡是一个非常严重的问题,可能导致任意程序失败,包括但不限于此站点命名的问题,尤其是在发布版本中。没有 MDA 帮助很难调试。
没有必要故意弄错,请改用 IntPtr
以使其与本机类型匹配。更正确的是当你声明它 HandleRef
instead. That's a wrapper that ensures that the handle cannot be destroyed while the native code is busy executing and should be used if you have a Finalize() method that calls CryptReleaseContext(). Even more correct is to use a safe handle wrapper type, like the .NET Framework does 时,它有一个关键的终结器,即使程序严重崩溃也会运行。仅当您的代码在非托管托管程序内部运行时才是真正必要的,SQL 服务器作为常见示例。