/**
 * Retrieves and clears the user credentials for logging into the guest OS.
 * UTF-16 version.
 *
 * @returns IPRT status value
 * @param   ppwszUser       Receives pointer of allocated user name string.
 *                          The returned pointer must be freed using VbglR3CredentialsDestroyUtf16().
 * @param   ppswzPassword   Receives pointer of allocated user password string.
 *                          The returned pointer must be freed using VbglR3CredentialsDestroyUtf16().
 * @param   ppwszDomain     Receives pointer of allocated domain name string.
 *                          The returned pointer must be freed using VbglR3CredentialsDestroyUtf16().
 */
VBGLR3DECL(int) VbglR3CredentialsRetrieveUtf16(PRTUTF16 *ppwszUser, PRTUTF16 *ppwszPassword, PRTUTF16 *ppwszDomain)
{
    AssertPtrReturn(ppwszUser, VERR_INVALID_POINTER);
    AssertPtrReturn(ppwszPassword, VERR_INVALID_POINTER);
    AssertPtrReturn(ppwszDomain, VERR_INVALID_POINTER);

    char *pszUser, *pszPassword, *pszDomain;
    int rc = VbglR3CredentialsRetrieve(&pszUser, &pszPassword, &pszDomain);
    if (RT_SUCCESS(rc))
    {
        PRTUTF16 pwszUser = NULL;
        PRTUTF16 pwszPassword = NULL;
        PRTUTF16 pwszDomain = NULL;

        rc = RTStrToUtf16(pszUser, &pwszUser);
        if (RT_SUCCESS(rc))
        {
            rc = RTStrToUtf16(pszPassword, &pwszPassword);
            if (RT_SUCCESS(rc))
                rc = RTStrToUtf16(pszDomain, &pwszDomain);
        }

        if (RT_SUCCESS(rc))
        {
            *ppwszUser     = pwszUser;
            *ppwszPassword = pwszPassword;
            *ppwszDomain   = pwszDomain;
        }
        else
            VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* Passes */);
        VbglR3CredentialsDestroy(pszUser, pszPassword, pszDomain, 3 /* Passes */);
    }

    return rc;
}
/**
 * Checks for credentials provided by the host / HGCM.
 *
 * @return  IPRT status code. VERR_NOT_FOUND if no credentials are available,
 *          VINF_SUCCESS on successful retrieval or another IPRT error.
 * @param   hPAM                    PAM handle.
 */
static int pam_vbox_check_creds(pam_handle_t *hPAM)
{
    int rc = VbglR3CredentialsQueryAvailability();
    if (RT_FAILURE(rc))
    {
        if (rc != VERR_NOT_FOUND)
            pam_vbox_error(hPAM, "pam_vbox_check_creds: could not query for credentials! rc=%Rrc. Aborting\n", rc);
#ifdef DEBUG
        else
            pam_vbox_log(hPAM, "pam_vbox_check_creds: no credentials available\n");
#endif
    }
    else
    {
        char *pszUsername;
        char *pszPassword;
        char *pszDomain;

        rc = VbglR3CredentialsRetrieve(&pszUsername, &pszPassword, &pszDomain);
        if (RT_FAILURE(rc))
        {
            pam_vbox_error(hPAM, "pam_vbox_check_creds: could not retrieve credentials! rc=%Rrc. Aborting\n", rc);
        }
        else
        {
#ifdef DEBUG
            pam_vbox_log(hPAM, "pam_vbox_check_creds: credentials retrieved: user=%s, password=%s, domain=%s\n",
                         pszUsername, pszPassword, pszDomain);
#else
            /* Don't log passwords in release mode! */
            pam_vbox_log(hPAM, "pam_vbox_check_creds: credentials retrieved: user=%s, password=XXX, domain=%s\n",
                         pszUsername, pszDomain);
#endif
            /* Fill credentials into PAM. */
            int pamrc = pam_set_item(hPAM, PAM_USER, pszUsername);
            if (pamrc != PAM_SUCCESS)
            {
                pam_vbox_error(hPAM, "pam_vbox_check_creds: could not set user name! pamrc=%d, msg=%s. Aborting\n",
                               pamrc, pam_strerror(hPAM, pamrc));
            }
            else
            {
                pamrc = pam_set_item(hPAM, PAM_AUTHTOK, pszPassword);
                if (pamrc != PAM_SUCCESS)
                    pam_vbox_error(hPAM, "pam_vbox_check_creds: could not set password! pamrc=%d, msg=%s. Aborting\n",
                                   pamrc, pam_strerror(hPAM, pamrc));

            }
            /** @todo Add handling domains as well. */
            VbglR3CredentialsDestroy(pszUsername, pszPassword, pszDomain,
                                     3 /* Three wipe passes */);
            pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with pamrc=%d, msg=%s\n",
                         pamrc, pam_strerror(hPAM, pamrc));
        }
    }

#ifdef DEBUG
    pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with rc=%Rrc\n", rc);
#endif
    return rc;
}