0

I am trying to call the Win32 API Function CredUnPackAuthenticationBufferW() but have not been able to get the username/password values.

I'm using the code from this question, which creates the CredUIPromptForWindowsCredentialsW() prompt. I'm now trying to unpack those values.

I have the following code (lots of this is from the linked question, I've included it here for completeness)

Public Type CREDUI_INFO
    cbSize As Long
    hwndParent As Long
    pszMessageText As LongPtr
    pszCaptionText As LongPtr
    hbmBanner As Long
End Type

Public Enum CREDUI_FLAGS
    INCORRECT_PASSWORD = &H1
    DO_NOT_PERSIST = &H2
    REQUEST_ADMINISTRATOR = &H4
    EXCLUDE_CERTIFICATES = &H8
    REQUIRE_CERTIFICATE = &H10
    SHOW_SAVE_CHECK_BOX = &H40
    ALWAYS_SHOW_UI = &H80
    REQUIRE_SMARTCARD = &H100
    PASSWORD_ONLY_OK = &H200
    VALIDATE_USERNAME = &H400
    COMPLETE_USERNAME = &H800
    PERSIST = &H1000
    SERVER_CREDENTIAL = &H4000
    EXPECT_CONFIRMATION = &H20000
    GENERIC_CREDENTIALS = &H40000
    USERNAME_TARGET_CREDENTIALS = &H80000
    KEEP_USERNAME = &H100000
End Enum


Public Declare PtrSafe Function CredUIPromptForWindowsCredentials Lib "credui" Alias "CredUIPromptForWindowsCredentialsW" ( _
ByRef pUiInfo As CREDUI_INFO, _
ByVal dwAuthError As Long, _
ByRef pulAuthPackage As LongPtr, _
ByVal pvInAuthBuffer As Any, _
ByVal ulInAuthBufferSize As Long, _
ByRef ppvOutAuthBuffer As Any, _
pulOutAuthBufferSize As LongPtr, _
ByRef iSave As Long, _
ByVal dwFlags As Long) _
As Long

Public Declare PtrSafe Function CredUnPackAuthenticationBuffer Lib "credui" Alias "CredUnPackAuthenticationBufferW" ( _
ByRef dwFlags As LongPtr, _
ByRef pAuthBuffer As LongPtr, _
ByRef 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

Declare Function GetLastError Lib "kernel32" _
() As Long

Private Const BUFFER_SIZE As Integer = &H100
Private Const ERROR_CANCELLED As Integer = &H4C7
Private Const CREDUIWIN_GENERIC As Integer = &H1
Private Const CREDUIWIN_CHECKBOX As Integer = &H2
Private Const CREDUIWIN_ENUMERATE_CURRENT_USER As Integer = &H200
Private Const CREDUIWIN_IN_CRED_ONLY As Integer = &H20
Private Const CREDUIWIN_AUTHPACKAGE_ONLY As Integer = &H10
Private Const CREDUIWIN_ENUMERATE_ADMINS As Integer = &H100
Private Const CRED_PACK_PROTECTED_CREDENTIALS As Integer = &H1
Private Const CRED_PACK_GENERIC_CREDENTIALS As Integer = &H4
Private Const MAX_USER_NAME As Integer = 100
Private Const MAX_PASSWORD As Integer = 100
Private Const MAX_DOMAIN As Integer = 100

Sub Test()
    Dim pUiInfo As CREDUI_INFO

    Dim pulAuthPackage As LongPtr
    Dim iSave As Long
    Dim result As Long
    Dim dwFlags As Long
    Dim ulInAuthBufferSize As Long
    Dim pulOutAuthBufferSize As LongPtr
    Dim pvInAuthBuffer As LongPtr
    Dim ppvOutAuthBuffer As LongPtr

    pUiInfo.cbSize = LenB(pUiInfo)
    pUiInfo.hwndParent = 0
    pUiInfo.pszMessageText = StrPtr("Microsoft Word")
    pUiInfo.pszCaptionText = StrPtr("Credentials required")

    pulAuthPackage = 0
    iSave = 0
    dwFlags = CREDUIWIN_CHECKBOX + CREDUIWIN_ENUMERATE_CURRENT_USER + CREDUIWIN_ENUMERATE_ADMINS

    ppvOutAuthBuffer = 0
    pvInAuthBuffer = 0

    ulInAuthBufferSize = 0
    pulOutAuthBufferSize = 0    

    result = CredUIPromptForWindowsCredentials( _
    pUiInfo, _
    0, _
    authPackage, _
    pvInAuthBuffer, _
    ulInAuthBufferSize, _
    ppvOutAuthBuffer, _
    pulOutAuthBufferSize, _
    iSave, _
    dwFlags)

    If result = 0 Then
        Dim res As LongPtr
        Dim usernameBuf As LongPtr
        Dim domainBuf As LongPtr
        Dim passwordBuf As LongPtr
        Dim max As Long
        max = 100
        res = CredUnPackAuthenticationBuffer(CRED_PACK_PROTECTED_CREDENTIALS, ppvOutAuthBuffer, pulOutAuthBufferSize, usernameBuf, MAX_USER_NAME, domainBuf, MAX_DOMAIN, passwordBuf, MAX_PASSWORD)
        Dim error As Long
        error = GetLastError()
        MsgBox (res)
    
    End If   
End Sub

After entering credentials, result is 0. The call to CredUnPackAuthenticationBuffer returns 0, but usernameBuf, domainBuf and passwordBuf are 0. The result of GetLastError() is also 0.

What am I doing wrong? I've tried changing the function parameters to be Strings for the username/domain/password buffer parameters, I've also tried various values for the dwFlags param and changing the flags passed to the CredUIPromptForWindowsCredentials call but none of these changes have any impact.

EDIT: I've switched to calling Err.LastDllError, which gives "ERROR_NOT_SUPPORTED".

Jay
  • 2,077
  • 5
  • 24
  • 39
  • try remove `CRED_PACK_PROTECTED_CREDENTIALS` – RbMm Oct 26 '20 at 10:55
  • Tried with 0,1, and 4, still get ERROR_NOT_SUPPORTED. – Jay Oct 26 '20 at 11:15
  • your declaration of `CredUnPackAuthenticationBuffer` is wrong - first parameter `dwFlags` is `DWORD` (4 bytes) and not `ByRef`, the size of buffer `cbAuthBuffer` - again `DWORD` and not `ByRef`, `pAuthBuffer` again `ByVal` but not `ByRef` – RbMm Oct 26 '20 at 11:37
  • maybe a daft question, but how do you pass DWORD in vba? – Jay Oct 26 '20 at 12:34
  • i dont know VBA, but look for declaration of `CredUIPromptForWindowsCredentials` - `ByVal dwAuthError As Long` for example – RbMm Oct 26 '20 at 12:47
  • great, thanks. changing to ByVal as above got the call to return some data, just need to get the actual string out of it. – Jay Oct 26 '20 at 12:51
  • is this a duplicate post where you reposted later? If so, please delete this one as other got answered. Looks like might be slightly different. – QHarr Oct 26 '20 at 16:34

0 Answers0