Почему долго тип данных работает для этого сортировки?
Мои знания за пределами.Net очень ограничены - но я потратил много времени на чтение многих связанных статей.
Документация типа данных HCRYPTPROV говорит, что это тип ULONG_PTR
,
Следующие ссылки предлагают использовать IntPtr
в соответствии с этим.
- Существует ли полное руководство по кроссплатформенным (x86 и x64) типам данных PInvoke и windows?
- Использование криптографической библиотеки MS на сервере 2012 - код ошибки CryptCreateHash 87: ERROR_INVALID_PARAMETER
- Вызов AuditQuerySystemPolicy() (advapi32.dll) из C# возвращает "Неверный параметр"
Но в следующем коде я использую long
Тип данных, и он работает просто отлично. Есть ли сценарий, который даст неверный результат? С чем это связано? long
?
Фреймворк: .Net 2.0;
Архитектура: 64 бит;
ОС: 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
1 ответ
Архитектура: 64 бит;
Это то, что, скорее всего, удерживает вас от неприятностей. ULONG_PTR - это целочисленный тип, размер которого зависит от разрядности процесса. В 32-битном процессе это 32-битный, в 64-битном процессе это 64-битный. Наиболее прямым эквивалентом типа.NET является UIntPtr
,
Его использование здесь в качестве ручки, фактическое значение не имеет значения. Вы не выполняете арифметику со значением, вы получаете его из CryptAcquireContext() и просто передаете его в CryptCreateHash(). Таким образом, не имеет значения, является ли тип, выбранный в объявлении pinvoke, подписанным или неподписанным. Причина того, что IntPtr
это более распространенный совет, это тип [CLSCompliant].
Long
в VB.NET используется 64-разрядное целое число со знаком. Так что соответствует ULONG_PTR, когда ваша программа работает как 64-битный процесс.
Вы можете попасть в беду, когда это не так. Либо потому, что ваша программа работает на компьютере с 32-разрядной операционной системой, либо когда вы используете настройки по умолчанию для нового проекта на VS2013. Соответствующий параметр - "Проект"> "Свойства"> вкладка "Компиляция"> "Целевой процессор". Измените его с AnyCPU на x86, чтобы попасть в неприятности. Обратите внимание, что есть также флажок "Предпочитать 32-разрядный", он отключен, потому что вы нацелены на.NET 2.0
Когда вы запустите свою программу после внесения этого изменения, вы должны получить разрыв отладчика при вызове CryptCreateHash(). Существует специальный Managed Debugging Assistant с именем PInvokeStackImbalance, который должен заметить, что стек вышел из строя на 4, когда функция возвращается. И вызывает перерыв в отладчике, чтобы рассказать вам об этом. Дисбаланс стека - очень неприятная проблема, которая может вызвать произвольный сбой программы, включая, помимо прочего, проблему, для которой этот сайт назван, особенно в сборке Release. Очень трудно отлаживать без помощи MDA.
Нет смысла делать это неправильно намеренно, используйте IntPtr
вместо этого, это соответствует нативному типу. Еще правильнее, когда ты это заявляешь HandleRef
вместо. Это оболочка, которая гарантирует, что дескриптор не может быть уничтожен, пока нативный код занят выполнением, и его следует использовать, если у вас есть метод Finalize(), который вызывает CryptReleaseContext(). Еще более правильно использовать безопасный тип дескриптора дескриптора, как в .NET Framework, он имеет критический финализатор, который запускается, даже если программа бомбит плохо. Только действительно необходимо, если ваш код выполняется внутри неуправляемой хостинговой программы, SQL Server как типичный пример.