/**
 * Clears and frees the three strings. UTF-16 version.
 *
 * @param   pwszUser       Receives pointer of the user name string to destroy.
 *                         Optional.
 * @param   pwszPassword   Receives pointer of the password string to destroy.
 *                         Optional.
 * @param   pwszDomain     Receives pointer of allocated domain name string.
 *                         Optional.
 * @param   cPasses        Number of wipe passes.  The more the better + slower.
 */
VBGLR3DECL(void) VbglR3CredentialsDestroyUtf16(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
                                               uint32_t cPasses)
{
    /* wipe first */
    if (pwszUser)
        RTMemWipeThoroughly(pwszUser,     (RTUtf16Len(pwszUser)     + 1) * sizeof(RTUTF16), cPasses);
    if (pwszPassword)
        RTMemWipeThoroughly(pwszPassword, (RTUtf16Len(pwszPassword) + 1) * sizeof(RTUTF16), cPasses);
    if (pwszDomain)
        RTMemWipeThoroughly(pwszDomain,   (RTUtf16Len(pwszDomain)   + 1) * sizeof(RTUTF16), cPasses);

    /* then free. */
    RTUtf16Free(pwszUser);
    RTUtf16Free(pwszPassword);
    RTUtf16Free(pwszDomain);
}
Example #2
0
/**
 * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns
 * E_OUTOFMEMORY instead.
 *
 * @param   a_pbstr         The source string.
 * @returns S_OK or E_OUTOFMEMORY.
 */
HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr)
{
    if (a_pbstr && *a_pbstr)
    {
        int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
                                  RTSTR_MAX,        // size_t cwcString: translate entire string
                                  &m_psz,           // char **ppsz: output buffer
                                  0,                // size_t cch: if 0, func allocates buffer in *ppsz
                                  &m_cch);          // size_t *pcch: receives the size of the output string, excluding the terminator.
        if (RT_SUCCESS(vrc))
            m_cbAllocated = m_cch + 1;
        else
        {
            if (   vrc != VERR_NO_STR_MEMORY
                && vrc != VERR_NO_MEMORY)
            {
                /* ASSUME: input is valid Utf-16. Fake out of memory error. */
                AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len((PCRTUTF16)a_pbstr) * sizeof(RTUTF16), a_pbstr));
            }

            m_cch = 0;
            m_cbAllocated = 0;
            m_psz = NULL;

            return E_OUTOFMEMORY;
        }
    }
    else
    {
        m_cch = 0;
        m_cbAllocated = 0;
        m_psz = NULL;
    }
    return S_OK;
}
Example #3
0
/**
 * Gets the user home directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Buffer where to store the path.
 * @param   cchPath     Buffer size in bytes.
 */
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
    RTUTF16 wszPath[RTPATH_MAX];
    DWORD   dwAttr;

    /*
     * There are multiple definitions for what WE think of as user home...
     */
    if (    !GetEnvironmentVariableW(L"HOME", &wszPath[0], RTPATH_MAX)
        ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
        ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
    {
        if (    !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX)
            ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
            ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX))
                return VERR_PATH_NOT_FOUND;
            size_t const cwc = RTUtf16Len(&wszPath[0]);
            if (    !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc)
                ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
                ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                return VERR_PATH_NOT_FOUND;
        }
    }

    /*
     * Convert and return.
     */
    return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
}
Example #4
0
RTDECL(int) RTPathSetCurrent(const char *pszPath)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);

    /*
     * This interface is almost identical to the Windows API.
     */
    PRTUTF16 pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (RT_SUCCESS(rc))
    {
        /** @todo improve the slash stripping a bit? */
        size_t cwc = RTUtf16Len(pwszPath);
        if (    cwc >= 2
            &&  (   pwszPath[cwc - 1] == L'/'
                 || pwszPath[cwc - 1] == L'\\')
            &&  pwszPath[cwc - 2] != ':')
            pwszPath[cwc - 1] = L'\0';

        if (!SetCurrentDirectoryW(pwszPath))
            rc = RTErrConvertFromWin32(GetLastError());

        RTUtf16Free(pwszPath);
    }
    return rc;
}
/**
 * Assigns or copies a RTUTF16 string to a UNICODE_STRING.
 *
 * When fCopy is false, this does *not* copy its contents
 * and only assigns its code points to the destination!
 * When fCopy is true, the actual string buffer gets copied.
 *
 * Does not take terminating \0 into account.
 *
 * @return  HRESULT
 * @param   pUnicodeDest            Unicode string assigning the UTF16 string to.
 * @param   pwszSource              UTF16 string to assign.
 * @param   fCopy                   Whether to just assign or copy the actual buffer
 *                                  contents from source -> dest.
 */
HRESULT VBoxCredProvCredential::RTUTF16ToUnicode(PUNICODE_STRING pUnicodeDest, PRTUTF16 pwszSource, bool fCopy)
{
    AssertPtrReturn(pUnicodeDest, E_POINTER);
    AssertPtrReturn(pwszSource, E_POINTER);

    size_t cbLen = RTUtf16Len(pwszSource) * sizeof(RTUTF16);
    AssertReturn(cbLen <= USHORT_MAX, E_INVALIDARG);

    HRESULT hr;

    if (fCopy)
    {
        if (cbLen <= pUnicodeDest->MaximumLength)
        {
            memcpy(pUnicodeDest->Buffer, pwszSource, cbLen);
            pUnicodeDest->Length = (USHORT)cbLen;
            hr = S_OK;
        }
        else
            hr = E_INVALIDARG;
    }
    else /* Just assign the buffer. */
    {
        pUnicodeDest->Buffer = pwszSource;
        pUnicodeDest->Length = (USHORT)cbLen;
        hr = S_OK;
    }

    return hr;
}
Example #6
0
RTDECL(PRTUTF16) RTUtf16DupTag(PCRTUTF16 pwszString, const char *pszTag)
{
    Assert(pwszString);
    size_t cb = (RTUtf16Len(pwszString) + 1) * sizeof(RTUTF16);
    PRTUTF16 pwsz = (PRTUTF16)RTMemAllocTag(cb, pszTag);
    if (pwsz)
        memcpy(pwsz, pwszString, cb);
    return pwsz;
}
/**
 * Gets the user home directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Buffer where to store the path.
 * @param   cchPath     Buffer size in bytes.
 */
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
    /*
     * Validate input
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(cchPath, VERR_INVALID_PARAMETER);

    RTUTF16 wszPath[RTPATH_MAX];
    bool    fValidFolderPath = false;

    /*
     * Try with Windows XP+ functionality first.
     */
    RTLDRMOD hShell32;
    int rc = RTLdrLoadSystem("Shell32.dll", true /*fNoUnload*/, &hShell32);
    if (RT_SUCCESS(rc))
    {
        PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
        rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW);
        if (RT_SUCCESS(rc))
        {
            HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, wszPath);
            fValidFolderPath = (hrc == S_OK);
        }
        RTLdrClose(hShell32);
    }

    DWORD   dwAttr;
    if (    !fValidFolderPath
        ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
        ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
    {
        /*
         * Fall back to Windows specific environment variables. HOME is not used.
         */
        if (    !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX)
            ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
            ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX))
                return VERR_PATH_NOT_FOUND;
            size_t const cwc = RTUtf16Len(&wszPath[0]);
            if (    !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc)
                ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
                ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                return VERR_PATH_NOT_FOUND;
        }
    }

    /*
     * Convert and return.
     */
    return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
}
Example #8
0
RTDECL(int) RTUtf16DupExTag(PRTUTF16 *ppwszString, PCRTUTF16 pwszString, size_t cwcExtra, const char *pszTag)
{
    Assert(pwszString);
    size_t cb = (RTUtf16Len(pwszString) + 1) * sizeof(RTUTF16);
    PRTUTF16 pwsz = (PRTUTF16)RTMemAllocTag(cb + cwcExtra * sizeof(RTUTF16), pszTag);
    if (pwsz)
    {
        memcpy(pwsz, pwszString, cb);
        *ppwszString = pwsz;
        return VINF_SUCCESS;
    }
    return VERR_NO_MEMORY;
}
Example #9
0
/**
 * Finds the root of the specified volume.
 *
 * @returns iprt status code.
 * @param   pszFsPath       Path within the filesystem. Verified as one byte or more.
 * @param   ppwszFsRoot     Where to store the returned string. Free with rtFsFreeRoot(),
 */
static int rtFsGetRoot(const char *pszFsPath, PRTUTF16 *ppwszFsRoot)
{
    /*
     * Do straight forward stuff first,
     */
    if (rtFsIsRoot(pszFsPath))
        return RTStrToUtf16(pszFsPath, ppwszFsRoot);

    /*
     * Expand and add slash (if required).
     */
    char szFullPath[RTPATH_MAX];
    int rc = RTPathAbs(pszFsPath, szFullPath, sizeof(szFullPath));
    if (RT_FAILURE(rc))
        return rc;
    size_t cb = strlen(szFullPath);
    if (!RTPATH_IS_SLASH(szFullPath[cb - 1]))
    {
        AssertReturn(cb + 1 < RTPATH_MAX, VERR_FILENAME_TOO_LONG);
        szFullPath[cb] = '\\';
        szFullPath[++cb] = '\0';
    }

    /*
     * Convert the path.
     */
    rc = RTStrToUtf16(szFullPath, ppwszFsRoot);
    if (RT_FAILURE(rc))
        return rc == VERR_BUFFER_OVERFLOW ? VERR_FILENAME_TOO_LONG : rc;

    /*
     * Walk the path until our proper API is happy or there is no more path left.
     */
    PRTUTF16 pwszStart = *ppwszFsRoot;
    if (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0))
    {
        PRTUTF16 pwszEnd = pwszStart + RTUtf16Len(pwszStart);
        PRTUTF16 pwszMin = pwszStart + 2;
        do
        {
            /* Strip off the last path component. */
            while (pwszEnd-- > pwszMin)
                if (RTPATH_IS_SLASH(*pwszEnd))
                    break;
            AssertReturn(pwszEnd >= pwszMin, VERR_INTERNAL_ERROR); /* leaks, but that's irrelevant for an internal error. */
            pwszEnd[1] = '\0';
        } while (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0));
    }

    return VINF_SUCCESS;
}
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
{
    /*
     * Convert the filter to UTF-16.
     */
    int rc;
    pDir->pNtFilterStr = NULL;
    if (   pDir->cchFilter > 0
        && pDir->enmFilter == RTDIRFILTER_WINNT)
    {
        PRTUTF16 pwszTmp;
        rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp);
        if (RT_FAILURE(rc))
            return rc;
        pDir->NtFilterStr.Buffer = pwszTmp;
        pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16));
        pDir->pNtFilterStr = &pDir->NtFilterStr;
    }

    /*
     * Try open the directory
     */
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
    bool fObjDir;
#endif
    rc = rtNtPathOpenDir(pszPathBuf,
                         FILE_READ_DATA | SYNCHRONIZE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                         FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
                         OBJ_CASE_INSENSITIVE,
                         &pDir->hDir,
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
                         &fObjDir
#else
                         NULL
#endif
                         );
    if (RT_SUCCESS(rc))
    {
        /*
         * Init data.
         */
        pDir->fDataUnread = false; /* spelling it out */
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
        if (fObjDir)
            pDir->enmInfoClass = FileMaximumInformation; /* object directory. */
#endif
    }
    return rc;
}
/**
 * Copies an UTF16 string into a PUNICODE_STRING by allocating space for it.
 *
 * @return  HRESULT
 * @param   pUnicodeDest        Where to store the copied (allocated) unicode string.
 * @param   pwszSource          UTF16 string to copy.
 */
HRESULT VBoxCredProvCredential::RTUTF16ToUnicodeA(PUNICODE_STRING pUnicodeDest, PRTUTF16 pwszSource)
{
    AssertPtrReturn(pUnicodeDest, E_POINTER);
    AssertPtrReturn(pwszSource,   E_POINTER);

    size_t cbLen = RTUtf16Len(pwszSource) * sizeof(RTUTF16);

    pUnicodeDest->Buffer = (LPWSTR)CoTaskMemAlloc(cbLen);

    if (!pUnicodeDest->Buffer)
        return E_OUTOFMEMORY;

    pUnicodeDest->MaximumLength = (USHORT)cbLen;
    pUnicodeDest->Length        = 0;

    return RTUTF16ToUnicode(pUnicodeDest, pwszSource, true /* fCopy */);
}
/**
 * Sets a credential provider field by first zero'ing out its current content in a (hopefully) secure manner,
 * then applying either the field's default or a new value.
 *
 * @return  HRESULT
 * @param   dwFieldID           Field ID of the credential provider field to reset.
 * @param   pcwszString         String to set for the given field. Specify NULL for setting the provider's default value.
 * @param   fNotifyUI           Whether to notify the LogonUI about the reset.
 */
HRESULT VBoxCredProvCredential::setField(DWORD dwFieldID, const PRTUTF16 pcwszString, bool fNotifyUI)
{
    if (dwFieldID >= VBOXCREDPROV_NUM_FIELDS)
        return E_INVALIDARG;

    HRESULT hr = S_OK;

    PRTUTF16 pwszField = m_apwszFields[dwFieldID];
    if (pwszField)
    {
        /* First, wipe the existing value thoroughly. */
        RTMemWipeThoroughly(pwszField, (RTUtf16Len(pwszField) + 1) * sizeof(RTUTF16), 3 /* Passes */);

        /* Second, free the string. */
        RTUtf16Free(pwszField);
    }

    /* Either fill in the default value or the one specified in pcwszString. */
    pwszField = RTUtf16Dup(pcwszString ? pcwszString : s_VBoxCredProvDefaultFields[dwFieldID].desc.pszLabel);
    if (pwszField)
    {
        m_apwszFields[dwFieldID] = pwszField; /* Update the pointer. */

        if (   m_pEvents
            && fNotifyUI) /* Let the logon UI know if wanted. */
        {
            hr = m_pEvents->SetFieldString(this, dwFieldID, pwszField);
        }
    }
    else
        hr = E_OUTOFMEMORY;

    VBoxCredProvVerbose(0, "VBoxCredProvCredential::setField: Setting field dwFieldID=%ld to '%ls', fNotifyUI=%RTbool, hr=0x%08x\n",
                        dwFieldID,
#ifdef DEBUG
                        pwszField,
#else
                        /* Don't show any passwords in release mode. */
                        dwFieldID == VBOXCREDPROV_FIELDID_PASSWORD ? L"XXX" : pwszField,
#endif
                        fNotifyUI, hr);
    return hr;
}
static void supR3HardenedFindOrLoadModule(PSUPHNTIMPDLL pDll)
{
#ifdef VBOX_HARDENED_STUB_WITHOUT_IMPORTS
    uint32_t const  cbName     = (uint32_t)RTUtf16Len(pDll->pwszName) * sizeof(WCHAR);
    PPEB_LDR_DATA   pLdrData   = NtCurrentPeb()->Ldr;
    LIST_ENTRY     *pList      = &pLdrData->InMemoryOrderModuleList;
    LIST_ENTRY     *pListEntry = pList->Flink;
    uint32_t        cLoops     = 0;
    while (pListEntry != pList && cLoops < 1024)
    {
        PLDR_DATA_TABLE_ENTRY pLdrEntry = RT_FROM_MEMBER(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

        if (   pLdrEntry->FullDllName.Length > cbName + sizeof(WCHAR)
            && (   pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '\\'
                || pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '/')
            && RTUtf16ICmpAscii(&pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR)],
                                pDll->pszName) == 0)
        {
            pDll->pbImageBase = (uint8_t *)pLdrEntry->DllBase;
            return;
        }

        pListEntry = pListEntry->Flink;
        cLoops++;
    }

    if (!pDll->cImports)
        pDll->pbImageBase = NULL; /* optional */
    else
        SUPHNTIMP_ERROR(false, 1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
                        "Failed to locate %ls", pDll->pwszName);
#else
    HMODULE hmod = GetModuleHandleW(pDll->pwszName);
    if (RT_UNLIKELY(!hmod && pDll->cImports))
        SUPHNTIMP_ERROR(true, 1, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
                        "Failed to locate %ls", pDll->pwszName);
    pDll->pbImageBase = (uint8_t *)hmod;
#endif
}
Example #14
0
/**
  * Returns the string length in bytes without the terminator
  * @returns unsigned int length in bytes
  * @param bstr source string
  */
unsigned int SysStringByteLen(BSTR bstr)
{
    return RTUtf16Len(bstr) * sizeof(OLECHAR);
}
Example #15
0
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    HRESULT hr = DV_E_FORMATETC;

    LPFORMATETC pThisFormat = NULL;
    LPSTGMEDIUM pThisMedium = NULL;

    LogFlowThisFunc(("\n"));

    /* Format supported? */
    ULONG lIndex;
    if (   LookupFormatEtc(pFormatEtc, &lIndex)
        && lIndex < m_cFormats) /* Paranoia. */
    {
        pThisMedium = &m_pStgMedium[lIndex];
        AssertPtr(pThisMedium);
        pThisFormat = &m_pFormatEtc[lIndex];
        AssertPtr(pThisFormat);

        LogFlowThisFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat));
        LogFlowThisFunc(("mStatus=%RU32\n", m_enmStatus));
        switch (m_enmStatus)
        {
            case DnDDataObjectStatus_Dropping:
            {
#if 0
                LogRel3(("DnD: Dropping\n"));
                LogFlowFunc(("Waiting for event ...\n"));
                int rc2 = RTSemEventWait(m_SemEvent, RT_INDEFINITE_WAIT);
                LogFlowFunc(("rc=%Rrc, mStatus=%RU32\n", rc2, m_enmStatus));
#endif
                break;
            }

            case DnDDataObjectStatus_Dropped:
            {
                LogRel3(("DnD: Dropped\n"));
                LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                         pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                         pThisFormat->tymed, pThisFormat->dwAspect));
                LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                         m_strFormat.toUtf8().constData(), m_pvData, m_cbData));

                QVariant::Type vaType;
                QString strMIMEType;
                if (    (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (   pFormatEtc->cfFormat == CF_TEXT
                         || pFormatEtc->cfFormat == CF_UNICODETEXT)
                   )
                {
                    strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */
                    vaType = QVariant::String;
                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                         && (pFormatEtc->cfFormat == CF_HDROP))
                {
                    strMIMEType = "text/uri-list";
                    vaType = QVariant::StringList;
                }
#if 0 /* More formats; not needed right now. */
                else if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                        && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                        && (pFormatEtc->cfFormat == CF_FILECONTENTS))
                {

                }
                else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                          && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                          && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
                {

                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
                {
                    HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
                    DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
                    AssertPtr(pdwEffect);
                    *pdwEffect = DROPEFFECT_COPY;
                    GlobalUnlock(hData);

                    pMedium->hGlobal = hData;
                    pMedium->tymed = TYMED_HGLOBAL;
                }
#endif
                LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toUtf8().constData(), vaType));

                int rc;

                if (!m_fDataRetrieved)
                {
                    if (m_pDnDHandler)
                    {
                        rc = m_pDnDHandler->retrieveData(Qt::CopyAction,
                                                         strMIMEType, vaType, m_vaData);
                    }
                    else
                        rc = VERR_NOT_FOUND;

                    m_fDataRetrieved = true;
                    LogFlowFunc(("Retrieving data ended with %Rrc\n", rc));
                }
                else /* Data already been retrieved. */
                    rc = VINF_SUCCESS;

                if (   RT_SUCCESS(rc)
                    && m_vaData.isValid())
                {
                    if (   strMIMEType.startsWith("text/uri-list")
                               /* One item. */
                        && (   m_vaData.canConvert(QVariant::String)
                               /* Multiple items. */
                            || m_vaData.canConvert(QVariant::StringList))
                       )
                    {
                        QStringList lstFilesURI = m_vaData.toStringList();
                        QStringList lstFiles;
                        for (size_t i = 0; i < lstFilesURI.size(); i++)
                        {
                            char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).toUtf8().constData());
                            if (pszFilePath)
                            {
                                lstFiles.append(pszFilePath);
                                RTStrFree(pszFilePath);
                            }
                            else /* Unable to parse -- refuse entire request. */
                            {
                                lstFiles.clear();
                                rc = VERR_INVALID_PARAMETER;
                                break;
                            }
                        }

                        size_t cFiles = lstFiles.size();
                        LogFlowThisFunc(("Files (%zu)\n", cFiles));
                        if (   RT_SUCCESS(rc)
                            && cFiles)
                        {
                            size_t cchFiles = 0; /* Number of characters. */
                            for (size_t i = 0; i < cFiles; i++)
                            {
                                const char *pszFile = lstFiles.at(i).toUtf8().constData();
                                cchFiles += strlen(pszFile);
                                cchFiles += 1; /* Terminating '\0'. */
                                LogFlowThisFunc(("\tFile: %s (cchFiles=%zu)\n", pszFile, cchFiles));
                            }

                            /* List termination with '\0'. */
                            cchFiles++;

                            size_t cbBuf = sizeof(DROPFILES) + (cchFiles * sizeof(RTUTF16));
                            DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf);
                            if (pDropFiles)
                            {
                                /* Put the files list right after our DROPFILES structure. */
                                pDropFiles->pFiles = sizeof(DROPFILES); /* Offset to file list. */
                                pDropFiles->fWide  = 1;                 /* We use Unicode. Always. */

                                uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles;
                                AssertPtr(pCurFile);

                                LogFlowThisFunc(("Encoded:\n"));
                                for (size_t i = 0; i < cFiles; i++)
                                {
                                    const char *pszFile = lstFiles.at(i).toUtf8().constData();
                                    Assert(strlen(pszFile));

                                    size_t cchCurFile;
                                    PRTUTF16 pwszFile;
                                    rc = RTStrToUtf16(pszFile, &pwszFile);
                                    if (RT_SUCCESS(rc))
                                    {
                                        cchCurFile = RTUtf16Len(pwszFile);
                                        Assert(cchCurFile);
                                        memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
                                        RTUtf16Free(pwszFile);
                                    }
                                    else
                                        break;

                                    pCurFile += cchCurFile * sizeof(RTUTF16);

                                    /* Terminate current file name. */
                                    *pCurFile = L'\0';
                                    pCurFile += sizeof(RTUTF16);

                                    LogFlowThisFunc(("\t#%zu: cchCurFile=%zu\n", i, cchCurFile));
                                }

                                if (RT_SUCCESS(rc))
                                {
                                    *pCurFile = L'\0'; /* Final list terminator. */

                                    /*
                                     * Fill out the medium structure we're going to report back.
                                     */
                                    pMedium->tymed          = TYMED_HGLOBAL;
                                    pMedium->pUnkForRelease = NULL;
                                    pMedium->hGlobal        = GlobalAlloc(  GMEM_ZEROINIT
                                                                          | GMEM_MOVEABLE
                                                                          | GMEM_DDESHARE, cbBuf);
                                    if (pMedium->hGlobal)
                                    {
                                        LPVOID pvMem = GlobalLock(pMedium->hGlobal);
                                        if (pvMem)
                                        {
                                            memcpy(pvMem, pDropFiles, cbBuf);
                                            GlobalUnlock(pMedium->hGlobal);

                                            hr = S_OK;
                                        }
                                        else
                                            rc = VERR_ACCESS_DENIED;
                                    }
                                    else
                                        rc = VERR_NO_MEMORY;

                                    LogFlowThisFunc(("Copying to TYMED_HGLOBAL (%zu bytes): %Rrc\n", cbBuf, rc));
                                }

                                RTMemFree(pDropFiles);
                            }
                            else
                                rc = VERR_NO_MEMORY;

                            if (RT_FAILURE(rc))
                                LogFlowThisFunc(("Failed with %Rrc\n", rc));
                        }
                    }
                    else if (   strMIMEType.startsWith("text/plain")
                             && m_vaData.canConvert(QVariant::String))
                    {
                        const bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT;
                        const size_t cbCh   = fUnicode
                                            ? sizeof(WCHAR) : sizeof(char);

                        QString strText = m_vaData.toString();
                        size_t cbSrc = strText.length() * cbCh;
                        Assert(cbSrc);
                        LPCVOID pvSrc = fUnicode
                                      ? (void *)strText.unicode()
                                      : (void *)strText.toUtf8().constData();
                        AssertPtr(pvSrc);

                        LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbCh=%zu, fUnicode=%RTbool\n",
                                     pvSrc, cbSrc, cbCh, fUnicode));

                        pMedium->tymed          = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal        = GlobalAlloc(GHND | GMEM_SHARE, cbSrc);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pvDst = GlobalLock(pMedium->hGlobal);
                            if (pvDst)
                            {
                                memcpy(pvDst, pvSrc, cbSrc);
                                GlobalUnlock(pMedium->hGlobal);
                            }
                            else
                                rc = VERR_ACCESS_DENIED;

                            hr = S_OK;
                        }
                        else
                            hr  = VERR_NO_MEMORY;
                    }
                    else
                        LogRel2(("DnD: MIME type '%s' not supported\n", strMIMEType.toUtf8().constData()));

                    LogFlowThisFunc(("Handling formats ended with rc=%Rrc\n", rc));
                }

                break;
            }

            default:
                break;
        }
    }

    /*
     * Fallback in error case.
     */
    if (FAILED(hr))
    {
        if (pThisMedium)
        {
            switch (pThisMedium->tymed)
            {

            case TYMED_HGLOBAL:
                pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                             pThisFormat->cfFormat,
                                                             0 /* Flags */);
                break;

            default:
                break;
            }
        }

        if (pFormatEtc)
            pMedium->tymed = pFormatEtc->tymed;

        pMedium->pUnkForRelease = NULL;
    }

    LogFlowThisFunc(("Returning hr=%Rhrc\n", hr));
    return hr;
}
void VBoxClipboardService::MessageReceived(BMessage *message)
{
    uint32_t formats = 0;
    message->PrintToStream();
    switch (message->what)
    {
        case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS:
        {
            int rc;
            uint32_t cb;
            void *pv;
            bool commit = false;

            if (message->FindInt32("Formats", (int32 *)&formats) != B_OK)
                break;

            if (!formats)
                break;

            if (!be_clipboard->Lock())
                break;

            be_clipboard->Clear();
            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
            {
                pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb);
                if (pv)
                {
                    char *text;
                    rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text);
                    if (RT_SUCCESS(rc))
                    {
                        BString str(text);
                        /** @todo user vboxClipboardUtf16WinToLin() */
                        // convert Windows CRLF to LF
                        str.ReplaceAll("\r\n", "\n");
                        // don't include the \0
                        clip->AddData("text/plain", B_MIME_TYPE, str.String(), str.Length());
                        RTStrFree(text);
                        commit = true;
                    }
                    free(pv);
                }
            }

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
            {
                pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb);
                if (pv)
                {
                    void  *pBmp  = NULL;
                    size_t cbBmp = 0;
                    rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp);
                    if (RT_SUCCESS(rc))
                    {
                        BMemoryIO mio(pBmp, cbBmp);
                        BBitmap *bitmap = BTranslationUtils::GetBitmap(&mio);
                        if (bitmap)
                        {
                            BMessage bitmapArchive;

                            /** @todo r=ramshankar: split this into functions with error checking as
                             *        neccessary. */
                            if (   bitmap->IsValid()
                                && bitmap->Archive(&bitmapArchive) == B_OK
                                && clip->AddMessage("image/bitmap", &bitmapArchive) == B_OK)
                            {
                                commit = true;
                            }
                            delete bitmap;
                        }
                        RTMemFree(pBmp);
                    }
                    free(pv);
                }
            }

            /*
             * Make sure we don't bounce this data back to the host, it's impolite. It can also
             * be used as a hint to applications probably.
             */
            clip->AddBool("FromVirtualBoxHost", true);
            if (commit)
                be_clipboard->Commit();
            be_clipboard->Unlock();
            break;
        }

        case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA:
        {
            int rc;

            if (message->FindInt32("Formats", (int32 *)&formats) != B_OK)
                break;

            if (!formats)
                break;
            if (!be_clipboard->Lock())
                break;

            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }
            clip->PrintToStream();

            if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
            {
                const char *text;
                int32 textLen;
                if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK)
                {
                    // usually doesn't include the \0 so be safe
                    BString str(text, textLen);
                    // convert from LF to Windows CRLF
                    str.ReplaceAll("\n", "\r\n");
                    PRTUTF16 pwsz;
                    rc = RTStrToUtf16(str.String(), &pwsz);
                    if (RT_SUCCESS(rc))
                    {
                        uint32_t cb = (RTUtf16Len(pwsz) + 1) * sizeof(RTUTF16);

                        rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, pwsz, cb);
                        //printf("VbglR3ClipboardWriteData: %d\n", rc);
                        RTUtf16Free(pwsz);
                    }
                }
            }
            else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
            {
                BMessage archivedBitmap;
                if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK ||
                    clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK)
                {
                    BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap);
                    if (bitmap)
                    {
                        // Don't delete bitmap, BBitmapStream will.
                        BBitmapStream stream(bitmap);
                        BTranslatorRoster *roster = BTranslatorRoster::Default();
                        if (roster && bitmap->IsValid())
                        {
                            BMallocIO bmpStream;
                            if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK)
                            {
                                const void *pDib;
                                size_t cbDibSize;
                                /* Strip out the BM header */
                                rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize);
                                if (RT_SUCCESS(rc))
                                {
                                    rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib,
                                                                  cbDibSize);
                                }
                            }
                        }
                    }
                }
            }

            be_clipboard->Unlock();
            break;
        }

        case B_CLIPBOARD_CHANGED:
        {
            printf("B_CLIPBOARD_CHANGED\n");
            const void *data;
            int32 dataLen;
            if (!be_clipboard->Lock())
                break;

            BMessage *clip = be_clipboard->Data();
            if (!clip)
            {
                be_clipboard->Unlock();
                break;
            }

            bool fromVBox;
            if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox)
            {
                // It already comes from the host, discard.
                be_clipboard->Unlock();
                break;
            }

            if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK)
                formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;

            if (   clip->HasMessage("image/bitmap")
                || clip->HasMessage("image/x-be-bitmap"))
            {
                formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
            }

            be_clipboard->Unlock();

            VbglR3ClipboardReportFormats(fClientId, formats);
            break;
        }

        case B_QUIT_REQUESTED:
            fExiting = true;
            break;

        default:
            BHandler::MessageReceived(message);
    }
}
/**
 * Read content from the host clipboard and write it to the internal clipboard
 * structure for further processing.
 *
 * @param   pPasteboardRef Reference to the global pasteboard.
 * @param   fFormats       The format type which should be read.
 * @param   pv             The destination buffer.
 * @param   cb             The size of the destination buffer.
 * @param   pcbActual      The size which is needed to transfer the content.
 *
 * @returns IPRT status code.
 */
int readFromPasteboard(PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
{
    Log(("readFromPasteboard: fFormat = %02X\n", fFormat));

    OSStatus err = noErr;

    /* Make sure all is in sync */
    PasteboardSynchronize(pPasteboard);

    /* Are some items in the pasteboard? */
    ItemCount itemCount;
    err = PasteboardGetItemCount(pPasteboard, &itemCount);
    if (itemCount < 1)
        return VINF_SUCCESS;

    /* The id of the first element in the pasteboard */
    int rc = VERR_NOT_SUPPORTED;
    PasteboardItemID itemID;
    if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID)))
    {
        /* The guest request unicode */
        if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
        {
            CFDataRef outData;
            PRTUTF16 pwszTmp = NULL;
            /* Try utf-16 first */
            if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData)))
            {
                Log(("Clipboard content is utf-16\n"));

                PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData);
                if (pwszString)
                    rc = RTUtf16DupEx(&pwszTmp, pwszString, 0);
                else
                    rc = VERR_INVALID_PARAMETER;
            }
            /* Second try is utf-8 */
            else
                if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData)))
                {
                    Log(("readFromPasteboard: clipboard content is utf-8\n"));
                    const char *pszString = (const char *)CFDataGetBytePtr(outData);
                    if (pszString)
                        rc = RTStrToUtf16(pszString, &pwszTmp);
                    else
                        rc = VERR_INVALID_PARAMETER;
                }
            if (pwszTmp)
            {
                /* Check how much longer will the converted text will be. */
                size_t cwSrc = RTUtf16Len(pwszTmp);
                size_t cwDest;
                rc = vboxClipboardUtf16GetWinSize(pwszTmp, cwSrc, &cwDest);
                if (RT_FAILURE(rc))
                {
                    RTUtf16Free(pwszTmp);
                    Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16GetWinSize returned %Rrc.  Abandoning.\n", rc));
                    AssertRCReturn(rc, rc);
                }
                /* Set the actually needed data size */
                *pcbActual = cwDest * 2;
                /* Return success state */
                rc = VINF_SUCCESS;
                /* Do not copy data if the dst buffer is not big enough. */
                if (*pcbActual <= cb)
                {
                    rc = vboxClipboardUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2);
                    if (RT_FAILURE(rc))
                    {
                        RTUtf16Free(pwszTmp);
                        Log(("readFromPasteboard: clipboard conversion failed.  vboxClipboardUtf16LinToWin() returned %Rrc.  Abandoning.\n", rc));
                        AssertRCReturn(rc, rc);
                    }
#ifdef SHOW_CLIPBOARD_CONTENT
                    Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv)));
#endif
                }
                /* Free the temp string */
                RTUtf16Free(pwszTmp);
            }
        }
        /* The guest request BITMAP */
        else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
        {
            CFDataRef outData;
            const void *pTmp = NULL;
            size_t cbTmpSize;
            /* Get the data from the pasteboard */
            if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData)))
            {
                Log(("Clipboard content is BMP\n"));
                pTmp = CFDataGetBytePtr(outData);
                cbTmpSize = CFDataGetLength(outData);
            }
            if (pTmp)
            {
                const void *pDib;
                size_t cbDibSize;
                rc = vboxClipboardBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize);
                if (RT_FAILURE(rc))
                {
                    rc = VERR_NOT_SUPPORTED;
                    Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc.  Abandoning.\n", rc));
                    AssertRCReturn(rc, rc);
                }

                *pcbActual = cbDibSize;
                /* Return success state */
                rc = VINF_SUCCESS;
                /* Do not copy data if the dst buffer is not big enough. */
                if (*pcbActual <= cb)
                {
                    memcpy(pv, pDib, cbDibSize);
#ifdef SHOW_CLIPBOARD_CONTENT
                    Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize));
#endif
                }
            }
        }
    }

    Log(("readFromPasteboard: rc = %02X\n", rc));
    return rc;
}
/**
 * Checks and retrieves credentials provided by the host + does account lookup on eventually
 * renamed user accounts.
 *
 * @return  IPRT status code.
 */
int VBoxCredProvCredential::RetrieveCredentials(void)
{
    int rc = VbglR3CredentialsQueryAvailability();
    if (RT_SUCCESS(rc))
    {
        /*
         * Set status to "terminating" to let the host know this module now
         * tries to receive and use passed credentials so that credentials from
         * the host won't be sent twice.
         */
        VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating);

        rc = VbglR3CredentialsRetrieveUtf16(&m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
                                            &m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD],
                                            &m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);

        VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc);
    }

    if (RT_SUCCESS(rc))
    {
        VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: User=%ls, Password=%ls, Domain=%ls\n",
                            m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
#ifdef DEBUG
                            m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD],
#else
                            L"XXX" /* Don't show any passwords in release mode. */,
#endif
                            m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);

        /*
         * In case we got a "display name" (e.g. "John Doe")
         * instead of the real user name (e.g. "jdoe") we have
         * to translate the data first ...
         */
        PWSTR pwszAcount;
        if (TranslateAccountName(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount))
        {
            VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name %ls -> %ls\n",
                                m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], pwszAcount);

            if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME])
            {
                RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
                                    RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16),
                                    3 /* Passes */);
                RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]);
            }
            m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount;
        }
        else
        {
            /*
             * Okay, no display name, but maybe it's a
             * principal name from which we have to extract the domain from?
             * ([email protected] -> jdoe in domain my-domain.sub.net.com.)
             */
            PWSTR pwszDomain;
            if (ExtractAccoutData(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
                                  &pwszAcount, &pwszDomain))
            {
                /* Update user name. */
                if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME])
                {
                    RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
                                        RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16),
                                        3 /* Passes */);
                    RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]);
                }
                m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount;

                /* Update domain. */
                if (m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME])
                {
                    RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME],
                                        RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) + sizeof(RTUTF16),
                                        3 /* Passes */);
                    RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
                }
                m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME] = pwszDomain;

                VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account data pwszAccount=%ls, pwszDomain=%ls\n",
                                    m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME],
                                    m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]);
            }
        }

        m_fHaveCreds = true;
    }
    else
    {
        /* If credentials already were retrieved by a former call, don't try to retrieve new ones
         * and just report back the already retrieved ones. */
        if (m_fHaveCreds)
        {
            VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Credentials already retrieved\n");
            rc = VINF_SUCCESS;
        }
    }

    VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc);
    return rc;
}
HRESULT VBoxCredProvCredential::kerberosLogonInit(KERB_INTERACTIVE_LOGON *pLogonIn,
                                                  CREDENTIAL_PROVIDER_USAGE_SCENARIO enmUsage,
                                                  PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain)
{
    AssertPtrReturn(pLogonIn,     E_INVALIDARG);
    AssertPtrReturn(pwszUser,     E_INVALIDARG);
    AssertPtrReturn(pwszPassword, E_INVALIDARG);
    /* pwszDomain is optional. */

    HRESULT hr;

    /* Do we have a domain name set? */
    if (   pwszDomain
        && RTUtf16Len(pwszDomain))
    {
        hr = RTUTF16ToUnicode(&pLogonIn->LogonDomainName, pwszDomain, true /* fCopy */);
    }
    else /* No domain (FQDN) given, try local computer name. */
    {
        WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
        DWORD cch = ARRAYSIZE(wszComputerName);
        if (GetComputerNameW(wszComputerName, &cch))
        {
            /* Is a domain name missing? Then use the name of the local computer. */
            hr = RTUTF16ToUnicode(&pLogonIn->LogonDomainName, wszComputerName, true /* fCopy */);

            VBoxCredProvVerbose(0, "VBoxCredProvCredential::kerberosLogonInit: Local computer name=%ls\n",
                                wszComputerName);
        }
        else
            hr = HRESULT_FROM_WIN32(GetLastError());
    }

    /* Fill in the username and password. */
    if (SUCCEEDED(hr))
    {
        hr = RTUTF16ToUnicode(&pLogonIn->UserName, pwszUser, true /* fCopy */);
        if (SUCCEEDED(hr))
        {
            hr = RTUTF16ToUnicode(&pLogonIn->Password, pwszPassword, true /* fCopy */);
            if (SUCCEEDED(hr))
            {
                /* Set credential type according to current usage scenario. */
                switch (enmUsage)
                {
                    case CPUS_UNLOCK_WORKSTATION:
                        pLogonIn->MessageType = KerbWorkstationUnlockLogon;
                        break;

                    case CPUS_LOGON:
                        pLogonIn->MessageType = KerbInteractiveLogon;
                        break;

                    case CPUS_CREDUI:
                        pLogonIn->MessageType = (KERB_LOGON_SUBMIT_TYPE)0; /* No message type required here. */
                        break;

                    default:
                        VBoxCredProvVerbose(0, "VBoxCredProvCredential::kerberosLogonInit: Unknown usage scenario=%ld\n",
                                            enmUsage);
                        hr = E_FAIL;
                        break;
                }
            }
        }
    }

    return hr;
}
/**
 * Checks and retrieves credentials provided by the host + does account lookup on eventually
 * renamed user accounts.
 *
 * @return  IPRT status code.
 */
int VBoxCredProvCredential::RetrieveCredentials(void)
{
    PRTUTF16 pwszUser     = NULL;
    PRTUTF16 pwszPassword = NULL;
    PRTUTF16 pwszDomain   = NULL;

    int rc = VbglR3CredentialsQueryAvailability();
    if (RT_SUCCESS(rc))
    {
        /*
         * Set status to "terminating" to let the host know this module now
         * tries to receive and use passed credentials so that credentials from
         * the host won't be sent twice.
         */
        VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating);

        rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain);

        VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc);
    }

    if (RT_SUCCESS(rc))
    {
        VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Received credentials for user '%ls'\n", pwszUser);

        /*
         * In case we got a "display name" (e.g. "John Doe")
         * instead of the real user name (e.g. "jdoe") we have
         * to translate the data first ...
         */
        PWSTR pwszExtractedName = NULL;
        if (   TranslateAccountName(pwszUser, &pwszExtractedName)
            && pwszExtractedName)
        {
            VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name '%ls' -> '%ls'\n",
                                pwszUser, pwszExtractedName);

            RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */);
            RTUtf16Free(pwszUser);

            pwszUser = RTUtf16Dup(pwszExtractedName);

            CoTaskMemFree(pwszExtractedName);
            pwszExtractedName = NULL;
        }
        else
        {
            /*
             * Okay, no display name, but maybe it's a
             * principal name from which we have to extract the domain from?
             * ([email protected] -> jdoe in domain my-domain.sub.net.com.)
             */
            PWSTR pwszExtractedDomain = NULL;
            if (ExtractAccoutData(pwszUser, &pwszExtractedName, &pwszExtractedDomain))
            {
                /* Update user name. */
                if (pwszExtractedName)
                {
                    if (pwszUser)
                    {
                        RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */);
                        RTUtf16Free(pwszUser);
                    }

                    pwszUser = RTUtf16Dup(pwszExtractedName);

                    CoTaskMemFree(pwszExtractedName);
                    pwszExtractedName = NULL;
                }

                /* Update domain. */
                if (pwszExtractedDomain)
                {
                    if (pwszDomain)
                    {
                        RTMemWipeThoroughly(pwszDomain, (RTUtf16Len(pwszDomain) + 1) * sizeof(RTUTF16), 3 /* Passes */);
                        RTUtf16Free(pwszDomain);
                    }

                    pwszDomain = RTUtf16Dup(pwszExtractedDomain);

                    CoTaskMemFree(pwszExtractedDomain);
                    pwszExtractedDomain = NULL;
                }

                VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account name '%ls' + domain '%ls'\n",
                                    pwszUser ? pwszUser : L"<NULL>", pwszDomain ? pwszDomain : L"<NULL>");
            }
        }

        m_fHaveCreds = true;
    }

    if (m_fHaveCreds)
    {
        VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Setting fields\n");

        setField(VBOXCREDPROV_FIELDID_USERNAME,   pwszUser,     true /* fNotifyUI */);
        setField(VBOXCREDPROV_FIELDID_PASSWORD,   pwszPassword, true /* fNotifyUI */);
        setField(VBOXCREDPROV_FIELDID_DOMAINNAME, pwszDomain,   true /* fNotifyUI */);
    }

    VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Wiping ...\n");

    VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* cPasses */);

    VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc);
    return rc;
}
int rtDirNativeOpen(PRTDIRINTERNAL pDir, uintptr_t hRelativeDir, void *pvNativeRelative)
{
    /*
     * Convert the filter to UTF-16.
     */
    int rc;
    pDir->pNtFilterStr = NULL;
    if (   pDir->cchFilter > 0
        && pDir->enmFilter == RTDIRFILTER_WINNT)
    {
        PRTUTF16 pwszTmp;
        rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp);
        if (RT_FAILURE(rc))
            return rc;
        pDir->NtFilterStr.Buffer = pwszTmp;
        pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16));
        pDir->pNtFilterStr = &pDir->NtFilterStr;
    }

    /*
     * Try open the directory
     */
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
    bool fObjDir = false;
#endif
    if (hRelativeDir != ~(uintptr_t)0 && pvNativeRelative == NULL)
    {
        /* Caller already opened it, easy! */
        pDir->hDir = (HANDLE)hRelativeDir;
        rc = VINF_SUCCESS;
    }
    else
    {
        /*
         * If we have to check for reparse points, this gets complicated!
         */
        static int volatile g_fReparsePoints = -1;
        uint32_t            fOptions         = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT;
        int fReparsePoints = g_fReparsePoints;
        if (   fReparsePoints != 0
            && (pDir->fFlags & RTDIR_F_NO_FOLLOW)
            && !pDir->fDirSlash)
            fOptions |= FILE_OPEN_REPARSE_POINT;

        for (;;)
        {
            if (pvNativeRelative == NULL)
                rc = RTNtPathOpenDir(pDir->pszPath,
                                     FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                                     fOptions,
                                     OBJ_CASE_INSENSITIVE,
                                     &pDir->hDir,
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
                                     &fObjDir
#else
                                     NULL
#endif
                                     );
            else
                rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir,
                                       (struct _UNICODE_STRING *)pvNativeRelative,
                                       FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
                                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                                       fOptions,
                                       OBJ_CASE_INSENSITIVE,
                                       &pDir->hDir,
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
                                       &fObjDir
#else
                                       NULL
#endif
                                       );
            if (   !(fOptions & FILE_OPEN_REPARSE_POINT)
                || (rc != VINF_SUCCESS && rc != VERR_INVALID_PARAMETER) )
                break;
            if (rc == VINF_SUCCESS)
            {
                if (fReparsePoints == -1)
                    g_fReparsePoints = 1;

                /*
                 * We now need to check if we opened a symbolic directory link.
                 * (These can be enumerated, but contains only '.' and '..'.)
                 */
                FILE_ATTRIBUTE_TAG_INFORMATION  TagInfo = { 0, 0 };
                IO_STATUS_BLOCK                 Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
                NTSTATUS rcNt = NtQueryInformationFile(pDir->hDir, &Ios, &TagInfo, sizeof(TagInfo), FileAttributeTagInformation);
                AssertMsg(NT_SUCCESS(rcNt), ("%#x\n", rcNt));
                if (!NT_SUCCESS(rcNt))
                    TagInfo.FileAttributes = TagInfo.ReparseTag = 0;
                if (!(TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
                    break;

                NtClose(pDir->hDir);
                pDir->hDir = RTNT_INVALID_HANDLE_VALUE;

                if (TagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK)
                {
                    rc = VERR_IS_A_SYMLINK;
                    break;
                }

                /* Reparse point that isn't a symbolic link, try follow the reparsing. */
            }
            else if (fReparsePoints == -1)
                g_fReparsePoints = fReparsePoints = 0;
            fOptions &= ~FILE_OPEN_REPARSE_POINT;
        }

    }
    if (RT_SUCCESS(rc))
    {
        /*
         * Init data.
         */
        pDir->fDataUnread = false; /* spelling it out */
        pDir->uDirDev     = 0;
#ifdef IPRT_WITH_NT_PATH_PASSTHRU
        if (fObjDir)
            pDir->enmInfoClass = FileMaximumInformation; /* object directory. */
#endif
    }
    return rc;
}
int main(int argc, char **argv)
{
    RTTEST hTest;
    int rc = RTTestInitAndCreate("tstRTUuid", &hTest);
    if (rc)
        return rc;
    RTTestBanner(hTest);


#define CHECK_RC() \
    do { if (RT_FAILURE(rc)) { RTTestFailed(hTest, "line %d: rc=%Rrc", __LINE__, rc); } } while (0)

    RTTestSub(hTest, "RTUuidClear & RTUuisIsNull");
    RTUUID UuidNull;
    rc = RTUuidClear(&UuidNull); CHECK_RC();

    RTTEST_CHECK(hTest, RTUuidIsNull(&UuidNull));
    RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &UuidNull) == 0);

    RTTestSub(hTest, "RTUuidCreate");
    RTUUID Uuid;
    rc = RTUuidCreate(&Uuid); CHECK_RC();
    RTTEST_CHECK(hTest, !RTUuidIsNull(&Uuid));
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid) == 0);
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &UuidNull) > 0);
    RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &Uuid) < 0);

    RTTestSub(hTest, "RTUuidToStr");
    char sz[RTUUID_STR_LENGTH];
    rc = RTUuidToStr(&Uuid, sz, sizeof(sz)); CHECK_RC();
    RTTEST_CHECK(hTest, strlen(sz) == RTUUID_STR_LENGTH - 1);
    RTTestPrintf(hTest, RTTESTLVL_INFO, "UUID=%s\n", sz);

    RTTestSub(hTest, "RTUuidFromStr");
    RTUUID Uuid2;
    rc = RTUuidFromStr(&Uuid2, sz); CHECK_RC();
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);

    char *psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH);
    if (psz)
    {
        RTStrPrintf(psz, RTUUID_STR_LENGTH, "%s", sz);
        RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS);
        RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);
        for (unsigned off = 1; off < RTUUID_STR_LENGTH; off++)
        {
            char *psz2 = psz + off;
            RTStrPrintf(psz2, RTUUID_STR_LENGTH - off, "%s", sz);
            RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT);
        }
        RTTestGuardedFree(hTest, psz);
    }

    RTUuidClear(&Uuid2);
    char sz2[RTUUID_STR_LENGTH + 2];
    RTStrPrintf(sz2, sizeof(sz2), "{%s}", sz);
    rc = RTUuidFromStr(&Uuid2, sz2); CHECK_RC();
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);

    psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH + 2);
    if (psz)
    {
        RTStrPrintf(psz, RTUUID_STR_LENGTH + 2, "{%s}", sz);
        RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS);
        RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);
        for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++)
        {
            char *psz2 = psz + off;
            RTStrPrintf(psz2, RTUUID_STR_LENGTH + 2 - off, "{%s}", sz);
            RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT);
        }
        RTTestGuardedFree(hTest, psz);
    }

    RTTestSub(hTest, "RTUuidToUtf16");
    RTUTF16 wsz[RTUUID_STR_LENGTH];
    rc = RTUuidToUtf16(&Uuid, wsz, sizeof(wsz)); CHECK_RC();
    RTTEST_CHECK(hTest, RTUtf16Len(wsz) == RTUUID_STR_LENGTH - 1);

    RTTestSub(hTest, "RTUuidFromUtf16");
    rc = RTUuidFromUtf16(&Uuid2, wsz); CHECK_RC();
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);

    RTUTF16 *pwsz;
    rc = RTStrToUtf16(sz2, &pwsz);
    RTTEST_CHECK(hTest, rc == VINF_SUCCESS);
    if (RT_SUCCESS(rc))
    {
        RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz), VINF_SUCCESS);
        RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);
        RTUTF16 *pwsz2 = (RTUTF16*)RTTestGuardedAllocTail(hTest, 2 * (RTUUID_STR_LENGTH + 2));
        if (pwsz2)
        {
            memcpy(pwsz2, pwsz, 2 * (RTUUID_STR_LENGTH + 2));
            RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz2), VINF_SUCCESS);
            RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0);
            for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++)
            {
                RTUTF16 *pwsz3 = pwsz2 + off;
                memcpy(pwsz3, pwsz, 2 * (RTUUID_STR_LENGTH + 1 - off));
                pwsz3[RTUUID_STR_LENGTH + 1 - off] = 0;
                RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz3), VERR_INVALID_UUID_FORMAT);
            }
            RTTestGuardedFree(hTest, pwsz2);
        }
        RTUtf16Free(pwsz);
    }

    RTTestSub(hTest, "RTUuidCompareStr");
    RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, sz) == 0);
    RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, "00000000-0000-0000-0000-000000000000") > 0);
    RTTEST_CHECK(hTest, RTUuidCompareStr(&UuidNull, "00000000-0000-0000-0000-000000000000") == 0);

    RTTestSub(hTest, "RTUuidCompare2Strs");
    RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, sz) == 0);
    RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, "00000000-0000-0000-0000-000000000000") > 0);
    RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", sz) < 0);
    RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000") == 0);
    RTTEST_CHECK(hTest, RTUuidCompare2Strs("d95d883b-f91d-4ce5-a5c5-d08bb6a85dec", "a56193c7-3e0b-4c03-9d66-56efb45082f7") > 0);
    RTTEST_CHECK(hTest, RTUuidCompare2Strs("a56193c7-3e0b-4c03-9d66-56efb45082f7", "d95d883b-f91d-4ce5-a5c5-d08bb6a85dec") < 0);

    /*
     * Check the binary representation.
     */
    RTTestSub(hTest, "Binary representation");
    RTUUID Uuid3;
    Uuid3.au8[0]  = 0x01;
    Uuid3.au8[1]  = 0x23;
    Uuid3.au8[2]  = 0x45;
    Uuid3.au8[3]  = 0x67;
    Uuid3.au8[4]  = 0x89;
    Uuid3.au8[5]  = 0xab;
    Uuid3.au8[6]  = 0xcd;
    Uuid3.au8[7]  = 0x4f;
    Uuid3.au8[8]  = 0x10;
    Uuid3.au8[9]  = 0xb2;
    Uuid3.au8[10] = 0x54;
    Uuid3.au8[11] = 0x76;
    Uuid3.au8[12] = 0x98;
    Uuid3.au8[13] = 0xba;
    Uuid3.au8[14] = 0xdc;
    Uuid3.au8[15] = 0xfe;
    Uuid3.Gen.u8ClockSeqHiAndReserved = (Uuid3.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
    Uuid3.Gen.u16TimeHiAndVersion = (Uuid3.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
    const char *pszUuid3 = "67452301-ab89-4fcd-90b2-547698badcfe";
    rc = RTUuidToStr(&Uuid3, sz, sizeof(sz)); CHECK_RC();
    RTTEST_CHECK(hTest, strcmp(sz, pszUuid3) == 0);
    rc = RTUuidFromStr(&Uuid, pszUuid3); CHECK_RC();
    RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid3) == 0);
    RTTEST_CHECK(hTest, memcmp(&Uuid3, &Uuid, sizeof(Uuid)) == 0);

    /*
     * checking the clock seq and time hi and version bits...
     */
    RTTestSub(hTest, "Clock seq, time hi, version bits");
    RTUUID Uuid4Changes;
    Uuid4Changes.au64[0] = 0;
    Uuid4Changes.au64[1] = 0;

    RTUUID Uuid4Prev;
    RTUuidCreate(&Uuid4Prev);

    for (unsigned i = 0; i < 1024; i++)
    {
        RTUUID Uuid4;
        RTUuidCreate(&Uuid4);

        Uuid4Changes.au64[0] |= Uuid4.au64[0] ^ Uuid4Prev.au64[0];
        Uuid4Changes.au64[1] |= Uuid4.au64[1] ^ Uuid4Prev.au64[1];

#if 0   /** @todo make a bit string/dumper similar to %Rhxs/d. */
        RTPrintf("tstUuid: %d %d %d %d-%d %d %d %d  %d %d %d %d-%d %d %d %d ; %d %d %d %d-%d %d %d %d  %d %d %d %d-%d %d %d %d\n",
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(0)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(1)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(2)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(3)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(4)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(5)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(6)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(7)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(8)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(9)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(10)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(11)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(12)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(13)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(14)),
                 !!(Uuid4.Gen.u16ClockSeq & RT_BIT(15)),

                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(0)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(1)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(2)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(3)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(4)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(5)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(6)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(7)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(8)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(9)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(10)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(11)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(12)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(13)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(14)),
                 !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(15))
                 );
#endif
        Uuid4Prev = Uuid4;
    }

    RTUUID Uuid4Fixed;
    Uuid4Fixed.au64[0] = ~Uuid4Changes.au64[0];
    Uuid4Fixed.au64[1] = ~Uuid4Changes.au64[1];
    RTTestPrintf(hTest, RTTESTLVL_INFO, "fixed bits: %RTuuid (mask)\n", &Uuid4Fixed);
    RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid:        raw: %.*Rhxs\n", sizeof(Uuid4Fixed), &Uuid4Fixed);

    Uuid4Prev.au64[0] &= Uuid4Fixed.au64[0];
    Uuid4Prev.au64[1] &= Uuid4Fixed.au64[1];
    RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: fixed bits: %RTuuid (value)\n", &Uuid4Prev);
    RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid:        raw: %.*Rhxs\n", sizeof(Uuid4Prev), &Uuid4Prev);

    /*
     * Summary.
     */
    return RTTestSummaryAndDestroy(hTest);
}
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    HRESULT hr = DV_E_FORMATETC;

    LPFORMATETC pThisFormat = NULL;
    LPSTGMEDIUM pThisMedium = NULL;

    /* Format supported? */
    ULONG lIndex;
    if (   LookupFormatEtc(pFormatEtc, &lIndex)
        && lIndex < mcFormats) /* Paranoia. */
    {
        pThisMedium = &mpStgMedium[lIndex];
        AssertPtr(pThisMedium);
        pThisFormat = &mpFormatEtc[lIndex];
        AssertPtr(pThisFormat);

        LogFlowFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat));
        LogFlowFunc(("mStatus=%ld\n", mStatus));
        switch (mStatus)
        {
            case Dropping:
            {
                    LogRel3(("DnD: Dropping\n"));
                    LogFlowFunc(("Waiting for event ...\n"));
                    int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT);
                    LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus));
            }

            case Dropped:
            {
                LogRel3(("DnD: Dropped\n"));
                LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                         pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                         pThisFormat->tymed, pThisFormat->dwAspect));
                LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                         mstrFormat.toAscii().constData(), mpvData, mcbData));

                QVariant::Type vaType;
                QString strMIMEType;
                if (    (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (   pFormatEtc->cfFormat == CF_TEXT
                         || pFormatEtc->cfFormat == CF_UNICODETEXT)
                   )
                {
                    strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */
                    vaType = QVariant::String;
                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                         && (pFormatEtc->cfFormat == CF_HDROP))
                {
                    strMIMEType = "text/uri-list";
                    vaType = QVariant::StringList;
                }
#if 0 /* More formats; not needed right now. */
                else if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                        && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                        && (pFormatEtc->cfFormat == CF_FILECONTENTS))
                {

                }
                else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                          && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                          && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
                {

                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
                {
                    HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
                    DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
                    AssertPtr(pdwEffect);
                    *pdwEffect = DROPEFFECT_COPY;
                    GlobalUnlock(hData);

                    pMedium->hGlobal = hData;
                    pMedium->tymed = TYMED_HGLOBAL;
                }
#endif
                LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toAscii().constData(), vaType));

                int rc;
                if (!mVaData.isValid())
                {
                    /* Note:  We're usig Qt::MoveAction because this speeds up the whole operation
                     *        significantly: Instead of copying the data from the temporary location to
                     *        the final destination we just move it.
                     *
                     * Note2: The Qt::MoveAction *only* affects the behavior on the host! The desired
                     *        action for the guest (e.g. moving a file from guest to host) is not affected
                     *        by this setting. */
                    rc = m_pDnDHandler->retrieveData(Qt::MoveAction,
                                                     strMIMEType, vaType, mVaData);
                }
                else
                    rc = VINF_SUCCESS; /* Data already retrieved. */

                if (RT_SUCCESS(rc))
                {
                    if (   strMIMEType.startsWith("text/uri-list")
                               /* One item. */
                        && (   mVaData.canConvert(QVariant::String)
                               /* Multiple items. */
                            || mVaData.canConvert(QVariant::StringList))
                       )
                    {
                        QStringList lstFilesURI = mVaData.toStringList();
                        QStringList lstFiles;
                        for (size_t i = 0; i < lstFilesURI.size(); i++)
                        {
                            /* Extract path from URI. */
                            char *pszPath = RTUriPath(lstFilesURI.at(i).toAscii().constData());
                            if (   pszPath
                                && strlen(pszPath) > 1)
                            {
                                pszPath++; /** @todo Skip first '/' (part of URI). Correct? */
                                pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */);
                                lstFiles.append(pszPath);
                            }
                        }

                        size_t cFiles = lstFiles.size();
                        Assert(cFiles);
#ifdef DEBUG
                        LogFlowFunc(("Files (%zu)\n", cFiles));
                        for (size_t i = 0; i < cFiles; i++)
                            LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).toAscii().constData()));
#endif
                        size_t cchFiles = 0; /* Number of ASCII characters. */
                        for (size_t i = 0; i < cFiles; i++)
                        {
                            cchFiles += strlen(lstFiles.at(i).toAscii().constData());
                            cchFiles += 1; /* Terminating '\0'. */
                        }

                        size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
                        DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf);
                        if (pDropFiles)
                        {
                            pDropFiles->pFiles = sizeof(DROPFILES);
                            pDropFiles->fWide = 1; /* We use unicode. Always. */

                            uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles;
                            AssertPtr(pCurFile);

                            for (size_t i = 0; i < cFiles; i++)
                            {
                                size_t cchCurFile;
                                PRTUTF16 pwszFile;
                                rc = RTStrToUtf16(lstFiles.at(i).toAscii().constData(), &pwszFile);
                                if (RT_SUCCESS(rc))
                                {
                                    cchCurFile = RTUtf16Len(pwszFile);
                                    Assert(cchCurFile);
                                    memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
                                    RTUtf16Free(pwszFile);
                                }
                                else
                                    break;

                                pCurFile += cchCurFile * sizeof(RTUTF16);

                                /* Terminate current file name. */
                                *pCurFile = L'\0';
                                pCurFile += sizeof(RTUTF16);
                            }

                            if (RT_SUCCESS(rc))
                            {
                                *pCurFile = L'\0'; /* Final list terminator. */

                                pMedium->tymed = TYMED_HGLOBAL;
                                pMedium->pUnkForRelease = NULL;
                                pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                               | GMEM_MOVEABLE
                                                               | GMEM_DDESHARE, cbBuf);
                                if (pMedium->hGlobal)
                                {
                                    LPVOID pvMem = GlobalLock(pMedium->hGlobal);
                                    if (pvMem)
                                    {
                                        memcpy(pvMem, pDropFiles, cbBuf);
                                        GlobalUnlock(pMedium->hGlobal);

                                        hr = S_OK;
                                    }
                                    else
                                        rc = VERR_ACCESS_DENIED;
                                }
                                else
                                    rc = VERR_NO_MEMORY;
                            }

                            RTMemFree(pDropFiles);
                        }
                    }
                    else if (   strMIMEType.startsWith("text/plain")
                             && mVaData.canConvert(QVariant::String))
                    {
                        bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT;
                        int cbCh = fUnicode
                                 ? sizeof(WCHAR) : sizeof(char);

                        QString strText = mVaData.toString();
                        size_t cbSrc = strText.length() * cbCh;
                        Assert(cbSrc);
                        LPCVOID pvSrc = fUnicode
                                      ? (void *)strText.unicode()
                                      : (void *)strText.toAscii().constData();
                        AssertPtr(pvSrc);

                        LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbch=%d, fUnicode=%RTbool\n",
                                     pvSrc, cbSrc, cbCh, fUnicode));

                        pMedium->tymed = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                       | GMEM_MOVEABLE
                                                       | GMEM_DDESHARE,
                                                       cbSrc);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pvDst = GlobalLock(pMedium->hGlobal);
                            if (pvDst)
                            {
                                memcpy(pvDst, pvSrc, cbSrc);
                                GlobalUnlock(pMedium->hGlobal);
                            }
                            else
                                rc = VERR_ACCESS_DENIED;

                            hr = S_OK;
                        }
                        else
                            hr  = VERR_NO_MEMORY;
                    }
                    else
                        LogFlowFunc(("MIME type=%s not supported\n",
                                     strMIMEType.toAscii().constData()));

                    LogFlowFunc(("Handling formats ended with rc=%Rrc\n", rc));
                }
            }

            default:
                break;
        }
    }

    /*
     * Fallback in error case.
     */
    if (FAILED(hr))
    {
        if (pThisMedium)
        {
            switch (pThisMedium->tymed)
            {

            case TYMED_HGLOBAL:
                pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                             pThisFormat->cfFormat,
                                                             0 /* Flags */);
                break;

            default:
                break;
            }
        }

        if (pFormatEtc)
            pMedium->tymed = pFormatEtc->tymed;

        pMedium->pUnkForRelease = NULL;
    }

    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
    return hr;
}
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP VBoxDnDDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    ULONG lIndex;
    if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
        return DV_E_FORMATETC;
    if (lIndex >= mcFormats) /* Paranoia. */
        return DV_E_FORMATETC;

    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));

    FORMATETC *pThisFormat = &mpFormatEtc[lIndex];
    AssertPtr(pThisFormat);

    STGMEDIUM *pThisMedium = &mpStgMedium[lIndex];
    AssertPtr(pThisMedium);

    HRESULT hr = DV_E_FORMATETC;

    LogFlowFunc(("mStatus=%ld\n", mStatus));
    if (mStatus == Dropping)
    {
        LogFlowFunc(("Waiting for event ...\n"));
        int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT);
        LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus));
    }

    if (mStatus == Dropped)
    {
        LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                     pThisFormat->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                     pThisFormat->tymed, pThisFormat->dwAspect));
        LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                     mstrFormat.c_str(), mpvData, mcbData));

        if (mstrFormat.equalsIgnoreCase("text/uri-list"))
        {
            RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
            RTCList<RTCString> lstFiles;
            for (size_t i = 0; i < lstFilesURI.size(); i++)
            {
                /* Extract path from URI. */
                char *pszPath = RTUriPath(lstFilesURI.at(i).c_str());
                if (   pszPath
                    && strlen(pszPath) > 1)
                {
                    pszPath++; /** @todo Skip first '/' (part of URI). Correct? */
                    pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */);
                    lstFiles.append(pszPath);
                }
            }
#ifdef DEBUG
            LogFlowFunc(("Files (%zu)\n", lstFiles.size()));
            for (size_t i = 0; i < lstFiles.size(); i++)
                LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
#endif

#if 0
            if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                && (pFormatEtc->cfFormat == CF_FILECONTENTS))
            {

            }
            else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                      && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                      && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
            {

            }
            else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
            {
                HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
                DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
                AssertPtr(pdwEffect);
                *pdwEffect = DROPEFFECT_COPY;
                GlobalUnlock(hData);

                pMedium->hGlobal = hData;
                pMedium->tymed = TYMED_HGLOBAL;
            }
            else
#endif
                 if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_TEXT))
            {
                pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
                if (pMedium->hGlobal)
                {
                    /** @todo Not working yet -- needs URI to plain ASCII conversion. */

                    char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
                    memcpy(pcDst, mpvData, mcbData);
                    pcDst[mcbData] = '\0';
                    GlobalUnlock(pMedium->hGlobal);

                    hr = S_OK;
                }
            }
            else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_HDROP))
            {
                int rc = VINF_SUCCESS;

                size_t cchFiles = 0; /* Number of ASCII characters. */
                for (size_t i = 0; i < lstFiles.size(); i++)
                {
                    cchFiles += strlen(lstFiles.at(i).c_str());
                    cchFiles += 1; /* Terminating '\0'. */
                }

                size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
                DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
                if (pBuf)
                {
                    pBuf->pFiles = sizeof(DROPFILES);
                    pBuf->fWide = 1; /* We use unicode. Always. */

                    uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
                    AssertPtr(pCurFile);

                    for (size_t i = 0; i < lstFiles.size() && RT_SUCCESS(rc); i++)
                    {
                        size_t cchCurFile;
                        PRTUTF16 pwszFile;
                        rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
                        if (RT_SUCCESS(rc))
                        {
                            cchCurFile = RTUtf16Len(pwszFile);
                            Assert(cchCurFile);
                            memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
                            RTUtf16Free(pwszFile);
                        }
                        else
                            break;

                        pCurFile += cchCurFile * sizeof(RTUTF16);

                        /* Terminate current file name. */
                        *pCurFile = L'\0';
                        pCurFile += sizeof(RTUTF16);
                    }

                    if (RT_SUCCESS(rc))
                    {
                        *pCurFile = L'\0'; /* Final list terminator. */

                        pMedium->tymed = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                       | GMEM_MOVEABLE
                                                       | GMEM_DDESHARE, cbBuf);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pMem = GlobalLock(pMedium->hGlobal);
                            if (pMem)
                            {
                                memcpy(pMem, pBuf, cbBuf);
                                GlobalUnlock(pMedium->hGlobal);

                                hr = S_OK;
                            }
                        }
                    }

                    RTMemFree(pBuf);
                }
                else
                    rc = VERR_NO_MEMORY;

                if (RT_FAILURE(rc))
                    hr = DV_E_FORMATETC;
            }
        }
    }

    if (FAILED(hr))
    {
        LogFlowFunc(("Copying medium ...\n"));
        switch (pThisMedium->tymed)
        {

        case TYMED_HGLOBAL:
            pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                         pThisFormat->cfFormat, NULL);
            break;

        default:
            break;
        }

        pMedium->tymed          = pThisFormat->tymed;
        pMedium->pUnkForRelease = NULL;
    }

    LogFlowFunc(("hr=%Rhrc\n", hr));
    return hr;
}
Example #25
0
RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags)
{
    AssertPtrReturn(pwszzBlock, VERR_INVALID_POINTER);
    AssertReturn(!fFlags, VERR_INVALID_FLAGS);

    /*
     * Count the number of variables in the block.
     */
    uint32_t  cVars = 0;
    PCRTUTF16 pwsz  = pwszzBlock;
    while (*pwsz != '\0')
    {
        cVars++;
        pwsz += RTUtf16Len(pwsz) + 1;
        AssertReturn(cVars < _256K, VERR_OUT_OF_RANGE);
    }

    /*
     * Create the duplicate.
     */
    PRTENVINTERNAL pIntEnv;
    int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/);
    if (RT_SUCCESS(rc))
    {
        pIntEnv->cVars = cVars;
        pIntEnv->papszEnv[pIntEnv->cVars] = NULL;

        size_t iDst = 0;
        for (pwsz = pwszzBlock; *pwsz != '\0'; pwsz += RTUtf16Len(pwsz) + 1)
        {
            int rc2 = RTUtf16ToUtf8(pwsz, &pIntEnv->papszEnv[iDst]);
            if (RT_SUCCESS(rc2))
            {
                /* Make sure it contains an '='. */
                const char *pszEqual = strchr(pIntEnv->papszEnv[iDst], '=');
                if (!pszEqual)
                {
                    rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "=");
                    if (RT_SUCCESS(rc2))
                        pszEqual = strchr(pIntEnv->papszEnv[iDst], '=');

                }
                if (pszEqual)
                {
                    /* Check for duplicates, keep the last version. */
                    const char *pchVar        = pIntEnv->papszEnv[iDst];
                    size_t      cchVarNmAndEq = pszEqual - pchVar;
                    for (size_t iDst2 = 0; iDst2 < iDst; iDst2++)
                        if (pIntEnv->pfnCompare(pIntEnv->papszEnv[iDst2], pchVar, cchVarNmAndEq) == 0)
                        {
                            RTStrFree(pIntEnv->papszEnv[iDst2]);
                            pIntEnv->papszEnv[iDst2] = pIntEnv->papszEnv[iDst];
                            pIntEnv->papszEnv[iDst]  = NULL;
                            iDst--;
                            break;
                        }
                    iDst++;
                    continue;
                }
                iDst++;
            }

            /* failed fatally. */
            pIntEnv->cVars = iDst;
            RTEnvDestroy(pIntEnv);
            return rc2;
        }
        Assert(iDst <= pIntEnv->cVars);
        pIntEnv->cVars = iDst;

        /* done */
        *phEnv = pIntEnv;
    }
    return rc;
}
Example #26
0
/**
  * Returns the string length in OLECHARs without the terminator
  * @returns unsigned int length in OLECHARs
  * @param bstr source string
  */
unsigned int SysStringLen(BSTR bstr)
{
    return RTUtf16Len(bstr);
}
/**
 * Handles the getregisters sub-command.
 *
 * @returns Suitable exit code.
 * @param   pArgs               The handler arguments.
 * @param   pDebugger           Pointer to the debugger interface.
 */
static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
{
    /*
     * We take a list of register names (case insensitive).  If 'all' is
     * encountered we'll dump all registers.
     */
    ULONG                       idCpu = 0;
    unsigned                    cRegisters = 0;

    RTGETOPTSTATE               GetState;
    RTGETOPTUNION               ValueUnion;
    static const RTGETOPTDEF    s_aOptions[] =
    {
        { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
    };
    int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    AssertRCReturn(rc, RTEXITCODE_FAILURE);

    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
    {
        switch (rc)
        {
            case 'c':
                idCpu = ValueUnion.u32;
                break;

            case VINF_GETOPT_NOT_OPTION:
                if (!RTStrICmp(ValueUnion.psz, "all"))
                {
                    com::SafeArray<BSTR> aBstrNames;
                    com::SafeArray<BSTR> aBstrValues;
                    CHECK_ERROR2I_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames),
                                                              ComSafeArrayAsOutParam(aBstrValues)),
                                      RTEXITCODE_FAILURE);
                    Assert(aBstrNames.size() == aBstrValues.size());

                    size_t cchMaxName  = 8;
                    for (size_t i = 0; i < aBstrNames.size(); i++)
                    {
                        size_t cchName = RTUtf16Len(aBstrNames[i]);
                        if (cchName > cchMaxName)
                            cchMaxName = cchName;
                    }

                    for (size_t i = 0; i < aBstrNames.size(); i++)
                        RTPrintf("%-*ls = %ls\n", cchMaxName, aBstrNames[i], aBstrValues[i]);
                }
                else
                {
                    com::Bstr bstrName = ValueUnion.psz;
                    com::Bstr bstrValue;
                    CHECK_ERROR2I_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE);
                    RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw());
                }
                cRegisters++;
                break;

            default:
                return errorGetOpt(rc, &ValueUnion);
        }
    }

    if (!cRegisters)
        return errorSyntax("The getregisters sub-command takes at least one register name");
    return RTEXITCODE_SUCCESS;
}
Example #28
0
RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate)
{
    /*
     * Validate the input.
     */
    AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER);
    AssertPtrReturn(pszTarget, VERR_INVALID_POINTER);

    /*
     * Resolve the API.
     */
    typedef BOOLEAN (WINAPI *PFNCREATESYMBOLICLINKW)(LPCWSTR, LPCWSTR, DWORD);
    static PFNCREATESYMBOLICLINKW   s_pfnCreateSymbolicLinkW = NULL;
    static bool                     s_fTried = FALSE;
    if (!s_fTried)
    {
        HMODULE hmod = LoadLibrary("KERNEL32.DLL");
        if (hmod)
        {
            PFNCREATESYMBOLICLINKW pfn = (PFNCREATESYMBOLICLINKW)GetProcAddress(hmod, "CreateSymbolicLinkW");
            if (pfn)
                s_pfnCreateSymbolicLinkW = pfn;
        }
        s_fTried = true;
    }
    if (!s_pfnCreateSymbolicLinkW)
    {
        LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns VERR_NOT_SUPPORTED - Windows API not found\n",
                 pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate));
        return VERR_NOT_SUPPORTED;
    }

    /*
     * Convert the paths.
     */
    PRTUTF16 pwszNativeSymlink;
    int rc = RTStrToUtf16(pszSymlink, &pwszNativeSymlink);
    if (RT_SUCCESS(rc))
    {
        PRTUTF16 pwszNativeTarget;
        rc = RTStrToUtf16(pszTarget, &pwszNativeTarget);
        if (RT_SUCCESS(rc))
        {
            /*
             * Massage the target path, determin the link type.
             */
            size_t cchTarget        = strlen(pszTarget);
            size_t cchVolSpecTarget = rtPathVolumeSpecLen(pszTarget);
#if 0 /* looks like this isn't needed after all. That makes everything much simper :-) */
            if (   cchTarget > RT_MIN(cchVolSpecTarget, 1)
                && RTPATH_IS_SLASH(pszTarget[cchTarget - 1]))
            {
                size_t cwcNativeTarget = RTUtf16Len(pwszNativeTarget);
                size_t offFromEnd = 1;
                while (   offFromEnd < cchTarget
                       && cchTarget - offFromEnd >= cchVolSpecTarget
                       && RTPATH_IS_SLASH(pszTarget[cchTarget - offFromEnd]))
                {
                    Assert(offFromEnd < cwcNativeTarget);
                    pwszNativeTarget[cwcNativeTarget - offFromEnd] = 0;
                    offFromEnd++;
                }
            }
#endif

            if (enmType == RTSYMLINKTYPE_UNKNOWN)
            {
                if (   cchTarget > cchVolSpecTarget
                    && RTPATH_IS_SLASH(pszTarget[cchTarget - 1]))
                    enmType = RTSYMLINKTYPE_DIR;
                else if (cchVolSpecTarget)
                {
                    /** @todo this is subject to sharing violations. */
                    DWORD dwAttr = GetFileAttributesW(pwszNativeTarget);
                    if (   dwAttr != INVALID_FILE_ATTRIBUTES
                        && (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                        enmType = RTSYMLINKTYPE_DIR;
                }
                else
                {
                    /** @todo Join the symlink directory with the target and
                     *        look up the attributes on that. -lazy bird. */
                }
            }

            /*
             * Create the link.
             */
            if (s_pfnCreateSymbolicLinkW(pwszNativeSymlink, pwszNativeTarget, enmType == RTSYMLINKTYPE_DIR))
                rc = VINF_SUCCESS;
            else
                rc = RTErrConvertFromWin32(GetLastError());

            RTUtf16Free(pwszNativeTarget);
        }
        RTUtf16Free(pwszNativeSymlink);
    }

    LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate, rc));
    return rc;
}