首页 > 解决方案 > 指向字符串的长指针

问题描述

CredUnPackAuthenticationBuffer根据这个问题打电话:

Public Declare PtrSafe Function CredUnPackAuthenticationBuffer Lib "credui" Alias "CredUnPackAuthenticationBufferW" ( _
ByVal dwFlags As LongPtr, _
ByVal pAuthBuffer As LongPtr, _
ByVal cbAuthBuffer As LongPtr, _
ByRef pszUserName As LongPtr, _
ByRef pcchMaxUserName As LongPtr, _
ByRef pszDomainName As LongPtr, _
ByRef pcchMaxDomainName As LongPtr, _
ByRef pszPassword As LongPtr, _
ByRef pcchMaxPassword As LongPtr) _
As LongPtr

Dim res As LongPtr
        Dim usernameBuf As LongPtr
        Dim domainBuf As LongPtr
        Dim passwordBuf As LongPtr
        Dim max As Long
        max = 100
        Dim flags As Long
        flags = CRED_PACK_GENERIC_CREDENTIALS
        
        res = CredUnPackAuthenticationBuffer(flags, ppvOutAuthBuffer, pulOutAuthBufferSize, usernameBuf, MAX_USER_NAME, domainBuf, MAX_DOMAIN, passwordBuf, MAX_PASSWORD)
        Dim error As Long
        error = Err.LastDllError

此调用成功,error 为 0,并且 usernameBuf、domainBuf 和 passwordBuf 都有值。

我正在尝试从这些指针中获取文本。从 MSDN,我知道这些值是指向以 null 结尾的字符串的指针。我尝试调用以下代码(从这里)来获取字符串数据,但byteCount始终为 0。

Private Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
 (ByVal Destination As LongPtr, ByVal Source As LongPtr, ByVal Length As Long)

Private Declare PtrSafe Function lstrlenW Lib "kernel32.dll" (ByVal lpString As LongPtr) As Long


Public Function StringFromPointerW(ByVal pointerToString As LongPtr) As String

    Const BYTES_PER_CHAR As Integer = 2

    Dim tmpBuffer()    As Byte
    Dim byteCount      As Long
 
    ' determine size of source string in bytes
    byteCount = lstrlenW(pointerToString) * BYTES_PER_CHAR
    
    If byteCount > 0 Then
        ' Resize the buffer as required
        ReDim tmpBuffer(0 To byteCount - 1) As Byte
        
        ' Copy the bytes from pointerToString to tmpBuffer
        Call CopyMemory(VarPtr(tmpBuffer(0)), pointerToString, byteCount)
    End If
 
    ' Straigth assigment Byte() to String possible - Both are Unicode!
    StringFromPointerW = tmpBuffer

End Function

我究竟做错了什么?我尝试将缓冲区作为字符串传递,而 StrPtr() 会导致 Word 崩溃。

标签: vbawinapims-word

解决方案


该函数需要LPWSTR,pszUserNamepszDomainNamepszPassword这意味着,并且您必须传递已经分配了相应字符数的字符串ByVal As LongPtr的值s 。 相应的三个缓冲区长度参数是,不是。,函数返回值也是. 您也不应该直接传递常量,因为这些参数应该是可写的。StrPtr
ByRef As LongAs LongPtrdwFlagscbAuthBufferLong
MAX_

Public Declare PtrSafe Function CredUnPackAuthenticationBuffer Lib "credui" Alias "CredUnPackAuthenticationBufferW" ( _
    ByVal dwFlags As Long, _
    ByVal pAuthBuffer As LongPtr, _
    ByVal cbAuthBuffer As Long, _
    ByVal pszUserName As LongPtr, _
    ByRef pcchMaxUserName As Long, _
    ByVal pszDomainName As LongPtr, _
    ByRef pcchMaxDomainName As Long, _
    ByVal pszPassword As LongPtr, _
    ByRef pcchMaxPassword As Long) _
As Long
Dim res As Long
Dim usernameBuf As String
Dim domainBuf As String
Dim passwordBuf As String

Dim flags As Long
flags = CRED_PACK_GENERIC_CREDENTIALS

Dim usernameBufLen As Long : usernameBufLen = MAX_USER_NAME
Dim domainBufLen As Long : domainBufLen = MAX_DOMAIN
Dim passwordBufLen As Long : passwordBufLen = MAX_PASSWORD

usernameBuf = String$(usernameBufLen, vbNullChar)
domainBuf = String$(domainBufLen, vbNullChar)
passwordBuf = String$(passwordBufLen, vbNullChar)

res = CredUnPackAuthenticationBuffer( _
    flags, _
    ppvOutAuthBuffer, _
    pulOutAuthBufferSize, _
    StrPtr(usernameBuf), _
    usernameBufLen, _
    StrPtr(domainBuf), _
    domainBufLen, _
    StrPtr(passwordBuf), _
    passwordBufLen _
)

你不需要一个StringFromPointerW. 缓冲区已经包含可用数据。


推荐阅读