Пример #1
0
/**
 * Opens a certificate store.
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          CERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 */
static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
{
    HCERTSTORE hStore = NULL;
    PRTUTF16   pwszStoreNm;
    int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
    if (RT_SUCCESS(rc))
    {
        /*
         * Make sure CERT_STORE_OPEN_EXISTING_FLAG is not set. This causes Windows XP
         * to return ACCESS_DENIED when installing TrustedPublisher certificates via
         * CertAddCertificateContextToStore() if the TrustedPublisher store never has
         * been used (through certmgr.exe and friends) yet.
         *
         * According to MSDN, if neither CERT_STORE_OPEN_EXISTING_FLAG nor
         * CERT_STORE_CREATE_NEW_FLAG is set, the store will be either opened or
         * created accordingly.
         */
        dwDst &= ~CERT_STORE_OPEN_EXISTING_FLAG;

        hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                               PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                               NULL /* hCryptProv = default */,
                               dwDst,
                               pwszStoreNm);

        RTUtf16Free(pwszStoreNm);
    }
    return hStore;
}
Пример #2
0
RTDECL(int) RTDirClose(PRTDIR pDir)
{
    /*
     * Validate input.
     */
    if (!pDir)
        return VERR_INVALID_PARAMETER;
    if (pDir->u32Magic != RTDIR_MAGIC)
    {
        AssertMsgFailed(("Invalid pDir=%p\n", pDir));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Close the handle.
     */
    pDir->u32Magic = ~RTDIR_MAGIC;
    if (pDir->hDir != MY_INVALID_HANDLE_VALUE)
    {
        int rc = rtNtPathClose(pDir->hDir);
        AssertRC(rc);
        pDir->hDir = MY_INVALID_HANDLE_VALUE;
    }
    RTStrFree(pDir->pszName);
    pDir->pszName = NULL;
    RTUtf16Free(pDir->NtFilterStr.Buffer);
    pDir->NtFilterStr.Buffer = NULL;
    RTMemFree(pDir->pabBuffer);
    pDir->pabBuffer = NULL;
    RTMemFree(pDir);

    return VINF_SUCCESS;
}
Пример #3
0
/**
 * Get the real (no symlinks, no . or .. components) path, must exist.
 *
 * @returns iprt status code.
 * @param   pszPath         The path to resolve.
 * @param   pszRealPath     Where to store the real path.
 * @param   cchRealPath     Size of the buffer.
 */
RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath)
{
    /*
     * Convert to UTF-16, call Win32 APIs, convert back.
     */
    PRTUTF16 pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (!RT_SUCCESS(rc))
        return (rc);

    LPWSTR lpFile;
    WCHAR  wsz[RTPATH_MAX];
    rc = GetFullPathNameW((LPCWSTR)pwszPath, RT_ELEMENTS(wsz), &wsz[0], &lpFile);
    if (rc > 0 && rc < RT_ELEMENTS(wsz))
    {
        /* Check that it exists. (Use RTPathAbs() to just resolve the name.) */
        DWORD dwAttr = GetFileAttributesW(wsz);
        if (dwAttr != INVALID_FILE_ATTRIBUTES)
            rc = RTUtf16ToUtf8Ex((PRTUTF16)&wsz[0], RTSTR_MAX, &pszRealPath, cchRealPath, NULL);
        else
            rc = RTErrConvertFromWin32(GetLastError());
    }
    else if (rc <= 0)
        rc = RTErrConvertFromWin32(GetLastError());
    else
        rc = VERR_FILENAME_TOO_LONG;

    RTUtf16Free(pwszPath);

    return rc;
}
Пример #4
0
/**
 * 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);
}
Пример #5
0
RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
{
    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
    AssertReturn(pszValue || !cbValue, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
    AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);

    if (pcchActual)
        *pcchActual = 0;

    PRTUTF16 pwszVar;
    int rc = RTStrToUtf16(pszVar, &pwszVar);
    AssertRCReturn(rc, rc);

    /** @todo Consider _wgetenv_s or GetEnvironmentVariableW here to avoid the
     *        potential race with a concurrent _wputenv/_putenv. */
    PCRTUTF16 pwszValue = _wgetenv(pwszVar);
    RTUtf16Free(pwszVar);
    if (pwszValue)
    {
        if (cbValue)
            rc = RTUtf16ToUtf8Ex(pwszValue, RTSTR_MAX, &pszValue, cbValue, pcchActual);
        else
            rc = RTUtf16CalcUtf8LenEx(pwszValue, RTSTR_MAX, pcchActual);
    }
    else
        rc = VERR_ENV_VAR_NOT_FOUND;
    return rc;
}
Пример #6
0
/**
 * Query the serial number of a filesystem.
 *
 * @returns iprt status code.
 * @param   pszFsPath       Path within the mounted filesystem.
 * @param   pu32Serial      Where to store the serial number.
 */
RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
{
    /*
     * Validate & get valid root path.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
    AssertMsgReturn(VALID_PTR(pu32Serial), ("%p", pu32Serial), VERR_INVALID_PARAMETER);
    PRTUTF16 pwszFsRoot;
    int rc = rtFsGetRoot(pszFsPath, &pwszFsRoot);
    if (RT_FAILURE(rc))
        return rc;

    /*
     * Do work.
     */
    DWORD   dwMaxName;
    DWORD   dwFlags;
    DWORD   dwSerial;
    if (GetVolumeInformationW(pwszFsRoot, NULL, 0, &dwSerial, &dwMaxName, &dwFlags, NULL, 0))
        *pu32Serial = dwSerial;
    else
    {
        DWORD Err = GetLastError();
        rc = RTErrConvertFromWin32(Err);
        Log(("RTFsQuerySizes(%s,): GetDiskFreeSpaceEx failed with lasterr %d (%Rrc)\n",
             pszFsPath, Err, rc));
    }

    RTUtf16Free(pwszFsRoot);
    return rc;
}
Пример #7
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;
}
/**
 * Wrapper around RTNtPathExpand8dot3Path that allocates a buffer instead of
 * working on the input buffer.
 *
 * @returns IPRT status code, see RTNtPathExpand8dot3Path().
 * @param   pUniStrSrc  The path to fix up. MaximumLength is the max buffer
 *                      length.
 * @param   fPathOnly   Whether to only process the path and leave the filename
 *                      as passed in.
 * @param   pUniStrDst  Output string.  On success, the caller must use
 *                      RTUtf16Free to free what the Buffer member points to.
 *                      This is all zeros and NULL on failure.
 */
RTDECL(int) RTNtPathExpand8dot3PathA(PCUNICODE_STRING pUniStrSrc, bool fPathOnly, PUNICODE_STRING pUniStrDst)
{
    /* Guess a reasonable size for the final version. */
    size_t const cbShort = pUniStrSrc->Length;
    size_t       cbLong  = RT_MIN(_64K - 1, cbShort * 8);
    if (cbLong < RTPATH_MAX)
        cbLong = RTPATH_MAX * 2;
    AssertCompile(RTPATH_MAX * 2 < _64K);

    pUniStrDst->Buffer = (WCHAR *)RTUtf16Alloc(cbLong);
    if (pUniStrDst->Buffer != NULL)
    {
        /* Copy over the short name and fix it up. */
        pUniStrDst->MaximumLength = (uint16_t)cbLong;
        pUniStrDst->Length        = (uint16_t)cbShort;
        memcpy(pUniStrDst->Buffer, pUniStrSrc->Buffer, cbShort);
        pUniStrDst->Buffer[cbShort / sizeof(WCHAR)] = '\0';
        int rc = RTNtPathExpand8dot3Path(pUniStrDst, fPathOnly);
        if (RT_SUCCESS(rc))
            return rc;

        /* We failed, bail. */
        RTUtf16Free(pUniStrDst->Buffer);
        pUniStrDst->Buffer    = NULL;
    }
    pUniStrDst->Length        = 0;
    pUniStrDst->MaximumLength = 0;
    return VERR_NO_UTF16_MEMORY;
}
Пример #9
0
RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
{
    *penmType = RTFSTYPE_UNKNOWN;

    AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
    AssertReturn(*pszFsPath, VERR_INVALID_PARAMETER);

    /*
     * Convert the path and try open it.
     */
    PRTUTF16 pwszFsPath;
    int rc = RTStrToUtf16(pszFsPath, &pwszFsPath);
    if (RT_SUCCESS(rc))
    {
        HANDLE hFile = CreateFileW(pwszFsPath,
                                   GENERIC_READ,
                                   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                   NULL,
                                   OPEN_EXISTING,
                                   FILE_FLAG_BACKUP_SEMANTICS,
                                   NULL);
        if (hFile != INVALID_HANDLE_VALUE)
        {
            /*
             * Use the NT api directly to get the file system name.
             */
            char            abBuf[8192];
            IO_STATUS_BLOCK Ios;
            NTSTATUS        rcNt = NtQueryVolumeInformationFile(hFile, &Ios,
                                                                abBuf, sizeof(abBuf),
                                                                FileFsAttributeInformation);
            if (rcNt >= 0)
            {
                PFILE_FS_ATTRIBUTE_INFORMATION pFsAttrInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)abBuf;
                if (pFsAttrInfo->FIleSystemNameLength)
                {
                }
#define IS_FS(szName) \
    rtFsWinAreEqual(pFsAttrInfo->FileSystemName, pFsAttrInfo->FIleSystemNameLength, szName, sizeof(szName) - 1)
                if (IS_FS("NTFS"))
                    *penmType = RTFSTYPE_NTFS;
                else if (IS_FS("FAT"))
                    *penmType = RTFSTYPE_FAT;
                else if (IS_FS("FAT32"))
                    *penmType = RTFSTYPE_FAT;
                else if (IS_FS("VBoxSharedFolderFS"))
                    *penmType = RTFSTYPE_VBOXSHF;
#undef IS_FS
            }
            else
                rc = RTErrConvertFromNtStatus(rcNt);
            CloseHandle(hFile);
        }
        else
            rc = RTErrConvertFromWin32(GetLastError());
        RTUtf16Free(pwszFsPath);
    }
    return rc;
}
Пример #10
0
/**
 * Internal worker for RTFileRename and RTFileMove.
 *
 * @returns iprt status code.
 * @param   pszSrc      The source filename.
 * @param   pszDst      The destination filename.
 * @param   fFlags      The windows MoveFileEx flags.
 * @param   fFileType   The filetype. We use the RTFMODE filetypes here. If it's 0,
 *                      anything goes. If it's RTFS_TYPE_DIRECTORY we'll check that the
 *                      source is a directory. If Its RTFS_TYPE_FILE we'll check that it's
 *                      not a directory (we are NOT checking whether it's a file).
 */
DECLHIDDEN(int) rtPathWin32MoveRename(const char *pszSrc, const char *pszDst, uint32_t fFlags, RTFMODE fFileType)
{
    /*
     * Convert the strings.
     */
    PRTUTF16 pwszSrc;
    int rc = RTStrToUtf16(pszSrc, &pwszSrc);
    if (RT_SUCCESS(rc))
    {
        PRTUTF16 pwszDst;
        rc = RTStrToUtf16(pszDst, &pwszDst);
        if (RT_SUCCESS(rc))
        {
            /*
             * Check object type if requested.
             * This is open to race conditions.
             */
            if (fFileType)
            {
                DWORD dwAttr = GetFileAttributesW(pwszSrc);
                if (dwAttr == INVALID_FILE_ATTRIBUTES)
                    rc = RTErrConvertFromWin32(GetLastError());
                else if (RTFS_IS_DIRECTORY(fFileType))
                    rc = dwAttr & FILE_ATTRIBUTE_DIRECTORY ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
                else
                    rc = dwAttr & FILE_ATTRIBUTE_DIRECTORY ? VERR_IS_A_DIRECTORY : VINF_SUCCESS;
            }
            if (RT_SUCCESS(rc))
            {
                if (MoveFileExW(pwszSrc, pwszDst, fFlags))
                    rc = VINF_SUCCESS;
                else
                {
                    DWORD Err = GetLastError();
                    rc = RTErrConvertFromWin32(Err);
                    Log(("MoveFileExW('%s', '%s', %#x, %RTfmode): fails with rc=%Rrc & lasterr=%d\n",
                         pszSrc, pszDst, fFlags, fFileType, rc, Err));
                }
            }
            RTUtf16Free(pwszDst);
        }
        RTUtf16Free(pwszSrc);
    }
    return rc;
}
Пример #11
0
/**
 * Builds and allocates the security descriptor required for securing the local pipe.
 *
 * @return  IPRT status code.
 * @param   ppDesc              Where to store the allocated security descriptor on success.
 *                              Must be free'd using LocalFree().
 */
static int rtLocalIpcServerWinAllocSecurityDescriptior(PSECURITY_DESCRIPTOR *ppDesc, bool fServer)
{
    /** @todo Stuff this into RTInitOnce? Later. */
    PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR
        pfnConvertStringSecurityDescriptorToSecurityDescriptor = NULL;

    RTLDRMOD hAdvApi32 = NIL_RTLDRMOD;
    int rc = RTLdrLoadSystem("Advapi32.dll", true /*fNoUnload*/, &hAdvApi32);
    if (RT_SUCCESS(rc))
        rc = RTLdrGetSymbol(hAdvApi32, "ConvertStringSecurityDescriptorToSecurityDescriptorW",
                            (void**)&pfnConvertStringSecurityDescriptorToSecurityDescriptor);

    PSECURITY_DESCRIPTOR pSecDesc = NULL;
    if (RT_SUCCESS(rc))
    {
        AssertPtr(pfnConvertStringSecurityDescriptorToSecurityDescriptor);

        /*
         * We'll create a security descriptor from a SDDL that denies
         * access to network clients (this is local IPC after all), it
         * makes some further restrictions to prevent non-authenticated
         * users from screwing around.
         */
        PRTUTF16 pwszSDDL;
        rc = RTStrToUtf16(fServer
                          ? RTLOCALIPC_WIN_SDDL_SERVER : RTLOCALIPC_WIN_SDDL_CLIENT, &pwszSDDL);
        if (RT_SUCCESS(rc))
        {
            if (!pfnConvertStringSecurityDescriptorToSecurityDescriptor((LPCTSTR)pwszSDDL,
                                                                        SDDL_REVISION_1,
                                                                        &pSecDesc,
                                                                        NULL))
            {
                rc = RTErrConvertFromWin32(GetLastError());
            }

            RTUtf16Free(pwszSDDL);
        }
    }
    else
    {
        /* Windows OSes < W2K SP2 not supported for now, bail out. */
        /** @todo Implement me! */
        rc = VERR_NOT_SUPPORTED;
    }

    if (hAdvApi32 != NIL_RTLDRMOD)
         RTLdrClose(hAdvApi32);

    if (RT_SUCCESS(rc))
    {
        AssertPtr(pSecDesc);
        *ppDesc = pSecDesc;
    }

    return rc;
}
Пример #12
0
RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate)
{
    /*
     * Validate the file mode.
     */
    int rc;
    fMode = rtFsModeNormalize(fMode, pszPath, 0);
    if (rtFsModeIsValidPermissions(fMode))
    {
        /*
         * Convert to UTF-16.
         */
        PRTUTF16 pwszString;
        rc = RTStrToUtf16(pszPath, &pwszString);
        AssertRC(rc);
        if (RT_SUCCESS(rc))
        {
            /*
             * Create the directory.
             */
            if (CreateDirectoryW((LPCWSTR)pwszString, NULL))
                rc = VINF_SUCCESS;
            else
                rc = RTErrConvertFromWin32(GetLastError());

            /*
             * Turn off indexing of directory through Windows Indexing Service
             */
            /** @todo This FILE_ATTRIBUTE_NOT_CONTENT_INDEXED hack (for .VDI files,
             *        really) may cause failures on samba shares.  That really sweet and
             *        need to be addressed differently.  We shouldn't be doing this
             *        unless the caller actually asks for it, must less returning failure,
             *        for crying out loud!  This is only important a couple of places in
             *        main, if important is the right way to put it... */
            if (   RT_SUCCESS(rc)
                && !(fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET))
            {
                if (   SetFileAttributesW((LPCWSTR)pwszString, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
                    || (fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL) )
                    rc = VINF_SUCCESS;
                else
                    rc = RTErrConvertFromWin32(GetLastError());
            }

            RTUtf16Free(pwszString);
        }
    }
    else
    {
        AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
        rc = VERR_INVALID_FMODE;
    }

    LogFlow(("RTDirCreate(%p:{%s}, %RTfmode): returns %Rrc\n", pszPath, pszPath, fMode, rc));
    return rc;
}
/**
 * Convert a UTF-8 string to a BSTR.
 *
 * @returns BSTR pointer.
 * @param   psz                 The UTF-8 string.
 */
static BSTR rtSystemWinBstrFromUtf8(const char *psz)
{
    PRTUTF16 pwsz = NULL;
    int rc = RTStrToUtf16(psz, &pwsz);
    if (RT_FAILURE(rc))
        return NULL;
    BSTR pBStr = SysAllocString((const OLECHAR *)pwsz);
    RTUtf16Free(pwsz);
    return pBStr;
}
Пример #14
0
RTDECL(bool) RTEnvExistsUtf8(const char *pszVar)
{
    AssertReturn(strchr(pszVar, '=') == NULL, false);

    PRTUTF16 pwszVar;
    int rc = RTStrToUtf16(pszVar, &pwszVar);
    AssertRCReturn(rc, false);
    bool fRet = _wgetenv(pwszVar) != NULL;
    RTUtf16Free(pwszVar);
    return fRet;
}
Пример #15
0
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
{
    /*
     * Setup the search expression.
     *
     * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
     * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
     * it when adding the wildcard expression.
     */
    size_t cbExpr;
    const char *pszExpr;
    if (pDir->enmFilter == RTDIRFILTER_WINNT)
    {
        pszExpr = pDir->pszFilter;
        cbExpr  = pDir->cchFilter + 1;
    }
    else
    {
        pszExpr = "*";
        cbExpr  = sizeof("*");
    }
    if (pDir->cchPath + cbExpr > RTPATH_MAX)
        return VERR_FILENAME_TOO_LONG;
    memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr);


    /*
     * Attempt opening the search.
     */
    int rc = VINF_SUCCESS;
    PRTUTF16 pwszName;
    rc = RTStrToUtf16(pszPathBuf, &pwszName);
    if (RT_SUCCESS(rc))
    {
        pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
        if (pDir->hDir != INVALID_HANDLE_VALUE)
            pDir->fDataUnread = true;
        else
        {
            DWORD dwErr = GetLastError();
            /* Theoretical case of an empty directory or more normal case of no matches. */
            if (   dwErr == ERROR_FILE_NOT_FOUND
                || dwErr == ERROR_NO_MORE_FILES /* ???*/)
                pDir->fDataUnread = false;
            else
                rc = RTErrConvertFromWin32(GetLastError());
        }
        RTUtf16Free(pwszName);
    }

    return rc;
}
Пример #16
0
RTR3DECL(int)  RTFileDelete(const char *pszFilename)
{
    PRTUTF16 pwszFilename;
    int rc = RTStrToUtf16(pszFilename, &pwszFilename);
    if (RT_SUCCESS(rc))
    {
        if (!DeleteFileW(pwszFilename))
            rc = RTErrConvertFromWin32(GetLastError());
        RTUtf16Free(pwszFilename);
    }

    return rc;
}
Пример #17
0
int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName,
                  RTUTF16 pwszDelimiter, bool fCaseSensitive, SHFLROOT *pRoot)
{
    MAPPING *pFolderMapping = NULL;

    if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
    {
        Log(("vbsfMapFolder %s\n", pszMapName->String.utf8));
    }
    else
    {
        Log(("vbsfMapFolder %ls\n", pszMapName->String.ucs2));
    }

    if (pClient->PathDelimiter == 0)
    {
        pClient->PathDelimiter = pwszDelimiter;
    }
    else
    {
        Assert(pwszDelimiter == pClient->PathDelimiter);
    }

    if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
    {
        int rc;
        PRTUTF16 utf16Name;

        rc = RTStrToUtf16 ((const char *) pszMapName->String.utf8, &utf16Name);
        if (RT_FAILURE (rc))
            return rc;

        pFolderMapping = vbsfMappingGetByName(utf16Name, pRoot);
        RTUtf16Free (utf16Name);
    }
    else
    {
        pFolderMapping = vbsfMappingGetByName(pszMapName->String.ucs2, pRoot);
    }

    if (!pFolderMapping)
    {
        return VERR_FILE_NOT_FOUND;
    }

    pFolderMapping->cMappings++;
    Assert(pFolderMapping->cMappings == 1 || pFolderMapping->fGuestCaseSensitive == fCaseSensitive);
    pFolderMapping->fGuestCaseSensitive = fCaseSensitive;
    return VINF_SUCCESS;
}
Пример #18
0
RTDECL(int) RTEnvPutUtf8(const char *pszVarEqualValue)
{
    PRTUTF16 pwszVarEqualValue;
    int rc = RTStrToUtf16(pszVarEqualValue, &pwszVarEqualValue);
    if (RT_SUCCESS(rc))
    {
        if (!_wputenv(pwszVarEqualValue))
            rc = VINF_SUCCESS;
        else
            rc = RTErrConvertFromErrno(errno);
        RTUtf16Free(pwszVarEqualValue);
    }
    return rc;
}
/**
 * Get the absolute path (no symlinks, no . or .. components), doesn't have to exit.
 *
 * @returns iprt status code.
 * @param   pszPath         The path to resolve.
 * @param   pszAbsPath      Where to store the absolute path.
 * @param   cchAbsPath      Size of the buffer.
 */
RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath)
{
    /*
     * Validation.
     */
    AssertPtr(pszAbsPath);
    AssertPtr(pszPath);
    if (RT_UNLIKELY(!*pszPath))
        return VERR_INVALID_PARAMETER;

    /*
     * Convert to UTF-16, call Win32 API, convert back.
     */
    LPWSTR pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (!RT_SUCCESS(rc))
        return (rc);

    LPWSTR pwszFile; /* Ignored */
    RTUTF16 wsz[RTPATH_MAX];
    rc = GetFullPathNameW(pwszPath, RT_ELEMENTS(wsz), &wsz[0], &pwszFile);
    if (rc > 0 && rc < RT_ELEMENTS(wsz))
    {
        size_t cch;
        rc = RTUtf16ToUtf8Ex(&wsz[0], RTSTR_MAX, &pszAbsPath, cchAbsPath, &cch);
        if (RT_SUCCESS(rc))
        {
# if 1 /** @todo This code is completely bonkers. */
            /*
             * Remove trailing slash if the path may be pointing to a directory.
             * (See posix variant.)
             */
            if (    cch > 1
                &&  RTPATH_IS_SLASH(pszAbsPath[cch - 1])
                &&  !RTPATH_IS_VOLSEP(pszAbsPath[cch - 2])
                &&  !RTPATH_IS_SLASH(pszAbsPath[cch - 2]))
                pszAbsPath[cch - 1] = '\0';
# endif
        }
    }
    else if (rc <= 0)
        rc = RTErrConvertFromWin32(GetLastError());
    else
        rc = VERR_FILENAME_TOO_LONG;

    RTUtf16Free(pwszPath);
    return rc;
}
Пример #20
0
RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode)
{
    /*
     * Validate the file mode.
     */
    int rc;
    fMode = rtFsModeNormalize(fMode, pszPath, 0);
    if (rtFsModeIsValidPermissions(fMode))
    {
        /*
         * Convert to UTF-16.
         */
        PRTUTF16 pwszString;
        rc = RTStrToUtf16(pszPath, &pwszString);
        AssertRC(rc);
        if (RT_SUCCESS(rc))
        {
            /*
             * Create the directory.
             */
            if (CreateDirectoryW((LPCWSTR)pwszString, NULL))
                rc = VINF_SUCCESS;
            else
                rc = RTErrConvertFromWin32(GetLastError());

            /*
             * Turn off indexing of directory through Windows Indexing Service
             */
            if (RT_SUCCESS(rc))
            {
                if (SetFileAttributesW((LPCWSTR)pwszString, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED))
                    rc = VINF_SUCCESS;
                else
                    rc = RTErrConvertFromWin32(GetLastError());
            }

            RTUtf16Free(pwszString);
        }
    }
    else
    {
        AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
        rc = VERR_INVALID_FMODE;
    }

    LogFlow(("RTDirCreate(%p:{%s}, %RTfmode): returns %Rrc\n", pszPath, pszPath, fMode, rc));
    return rc;
}
Пример #21
0
VBoxCredProvCredential::~VBoxCredProvCredential(void)
{
    VBoxCredProvVerbose(0, "VBoxCredProvCredential: Destroying\n");

    Reset();

    for (unsigned i = 0; i < VBOXCREDPROV_NUM_FIELDS; i++)
    {
        if (m_apwszFields[i])
        {
            RTUtf16Free(m_apwszFields[i]);
            m_apwszFields[i] = NULL;
        }
    }

    VBoxCredentialProviderRelease();
}
Пример #22
0
/**
 * 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;
}
/**
 * Query the properties of a mounted filesystem.
 *
 * @returns iprt status code.
 * @param   pszFsPath       Path within the mounted filesystem.
 * @param   pProperties     Where to store the properties.
 */
RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
{
    /*
     * Validate & get valid root path.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
    AssertMsgReturn(VALID_PTR(pProperties), ("%p", pProperties), VERR_INVALID_PARAMETER);
    PRTUTF16 pwszFsRoot;
    int rc = rtFsGetRoot(pszFsPath, &pwszFsRoot);
    if (RT_FAILURE(rc))
        return rc;

    /*
     * Do work.
     */
    DWORD   dwMaxName;
    DWORD   dwFlags;
    DWORD   dwSerial;
    if (GetVolumeInformationW(pwszFsRoot, NULL, 0, &dwSerial, &dwMaxName, &dwFlags, NULL, 0))
    {
        memset(pProperties, 0, sizeof(*pProperties));
        pProperties->cbMaxComponent   = dwMaxName;
        pProperties->fFileCompression = !!(dwFlags & FILE_FILE_COMPRESSION);
        pProperties->fCompressed      = !!(dwFlags & FILE_VOLUME_IS_COMPRESSED);
        pProperties->fReadOnly        = !!(dwFlags & FILE_READ_ONLY_VOLUME);
        pProperties->fSupportsUnicode = !!(dwFlags & FILE_UNICODE_ON_DISK);
        pProperties->fCaseSensitive   = false;    /* win32 is case preserving only */
        /** @todo r=bird: What about FILE_CASE_SENSITIVE_SEARCH ?  Is this set for NTFS
         *        as well perchance?  If so, better mention it instead of just setting
         *        fCaseSensitive to false. */
        pProperties->fRemote          = false;    /* no idea yet */
    }
    else
    {
        DWORD Err = GetLastError();
        rc = RTErrConvertFromWin32(Err);
        Log(("RTFsQuerySizes(%s,): GetVolumeInformation failed with lasterr %d (%Rrc)\n",
             pszFsPath, Err, rc));
    }

    RTUtf16Free(pwszFsRoot);
    return rc;
}
Пример #24
0
RTDECL(int) RTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
{
    /*
     * Convert the path.
     */
    PRTUTF16 pwszNativeSymlink;
    int rc = RTStrToUtf16(pszSymlink, &pwszNativeSymlink);
    if (RT_SUCCESS(rc))
    {
        /*
         * We have to use different APIs depending on whether this is a
         * directory or file link.  This means we're subject to one more race
         * than on posix at the moment.  We could probably avoid this though,
         * if we wanted to go talk with the native API layer below Win32...
         */
        DWORD dwAttr = GetFileAttributesW(pwszNativeSymlink);
        if (dwAttr != INVALID_FILE_ATTRIBUTES)
        {
            if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)
            {
                BOOL fRc;
                if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
                    fRc = RemoveDirectoryW(pwszNativeSymlink);
                else
                    fRc = DeleteFileW(pwszNativeSymlink);
                if (fRc)
                    rc = VINF_SUCCESS;
                else
                    rc = RTErrConvertFromWin32(GetLastError());
            }
            else
                rc = VERR_NOT_SYMLINK;
        }
        else
            rc = RTErrConvertFromWin32(GetLastError());
        RTUtf16Free(pwszNativeSymlink);
    }

    LogFlow(("RTSymlinkDelete(%p={%s}, %#x): returns %Rrc\n", pszSymlink, pszSymlink, fDelete, rc));
    return rc;
}
Пример #25
0
/**
 * Opens a certificate store.
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          ERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 */
static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
{
    HCERTSTORE hStore = NULL;
    PRTUTF16   pwszStoreNm;
    int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
    if (RT_SUCCESS(rc))
    {
        if (g_cVerbosityLevel > 1)
            RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);

        hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                               PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                               NULL /* hCryptProv = default */,
                               dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
                               pwszStoreNm);
        if (hStore == NULL)
            RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
                       dwDst, pszStoreNm, errorToString(GetLastError()));

        RTUtf16Free(pwszStoreNm);
    }
    return hStore;
}
Пример #26
0
RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, false);
    AssertReturn(*pszPath, false);
    Assert(RTPATH_F_IS_VALID(fFlags, 0));

    /*
     * Try query file info.
     */
    DWORD dwAttr;
    PRTUTF16 pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (RT_SUCCESS(rc))
    {
        dwAttr = GetFileAttributesW(pwszPath);
        RTUtf16Free(pwszPath);
    }
    else
        dwAttr = INVALID_FILE_ATTRIBUTES;
    if (dwAttr == INVALID_FILE_ATTRIBUTES)
        return false;

#ifdef FILE_ATTRIBUTE_REPARSE_POINT
    if (   (fFlags & RTPATH_F_FOLLOW_LINK)
        && (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT))
    {
        AssertFailed();
        /** @todo Symlinks: RTPathExists+RTPathExistsEx is misbehaving on symbolic
         *        links on Windows. */
    }
#endif

    return true;
}
Пример #27
0
RTDECL(int) RTDirRemove(const char *pszPath)
{
    /*
     * Convert to UTF-16.
     */
    PRTUTF16 pwszString;
    int rc = RTStrToUtf16(pszPath, &pwszString);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        /*
         * Remove the directory.
         */
        if (RemoveDirectoryW((LPCWSTR)pwszString))
            rc = VINF_SUCCESS;
        else
            rc = RTErrConvertFromWin32(GetLastError());

        RTUtf16Free(pwszString);
    }

    LogFlow(("RTDirRemove(%p:{%s}): returns %Rrc\n", pszPath, pszPath, rc));
    return rc;
}
Пример #28
0
/**
 * Frees string returned by rtFsGetRoot().
 */
static void rtFsFreeRoot(PRTUTF16 pwszFsRoot)
{
    RTUtf16Free(pwszFsRoot);
}
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);
}
/**
 * Read guest's clipboard buffer and forward its content to host.
 *
 * @param   u32ClientId    Host clipboard connection.
 * @param   pPasteboard    Guest PasteBoard reference.
 * @param   fFormats       List of data formats (bit field) received from host.
 *
 * @returns IPRT status code.
 */
int vbclClipboardForwardToHost(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats)
{
    int       rc = VINF_SUCCESS;

    void     *pvData  = NULL;
    uint32_t  cbData  = 0;
    uint32_t  cbAlloc = 0;

    VBoxClientVerbose(3, "vbclClipboardForwardToHost: %d\n", fFormats);

    /* Walk across all item(s) formats */
    uint32_t  fFormatsLeft = fFormats;
    while (fFormatsLeft)
    {
        if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
        {
            VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT: %d\n", fFormats);

            RTUTF16 *pUtf16Str = NULL;

            /* First, try to get UTF16 encoded buffer */
            rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF16PlainText, &pvData, &cbData, &cbAlloc);
            if (RT_SUCCESS(rc))
            {
                rc = RTUtf16DupEx(&pUtf16Str, (PRTUTF16)pvData, 0);
                if (RT_FAILURE(rc))
                    pUtf16Str = NULL;
            }
            else /* Failed to get UTF16 buffer */
            {
                /* Then, try to get UTF8 encoded buffer */
                rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeUTF8PlainText, &pvData, &cbData, &cbAlloc);
                if (RT_SUCCESS(rc))
                {
                    rc = RTStrToUtf16((const char *)pvData, &pUtf16Str);
                    if (RT_FAILURE(rc))
                        pUtf16Str = NULL;
                }
            }

            /* Finally, we got UTF16 encoded buffer */
            if (RT_SUCCESS(rc))
            {
                rc = vbclClipboardHostPasteText(u32ClientId, (PRTUTF16)pvData, cbData);

                if (pUtf16Str)
                {
                    RTUtf16Free(pUtf16Str);
                    pUtf16Str = NULL;
                }

                vbclClipboardReleaseGuestData(&pvData, cbAlloc);
            }
            else
            {
                /* No data found or error occurred: send empty buffer */
                rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, NULL, 0);
            }

            fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
        }

        else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
        {
            VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_BITMAP: %d\n", fFormats);

            rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeBMP, &pvData, &cbData, &cbAlloc);
            if (RT_SUCCESS(rc))
            {
                rc = vbclClipboardHostPasteBitmap(u32ClientId, pvData, cbData);
                vbclClipboardReleaseGuestData(&pvData, cbAlloc);
            }
            else
            {
                /* No data found or error occurred: send empty buffer */
                rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, NULL, 0);
            }

            fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
        }

        else if (fFormatsLeft & VBOX_SHARED_CLIPBOARD_FMT_HTML)
        {
            VBoxClientVerbose(3, "requested VBOX_SHARED_CLIPBOARD_FMT_HTML: %d\n", fFormats);

            rc = vbclClipboardReadGuestData(pPasteboard, kUTTypeHTML, &pvData, &cbData, &cbAlloc);
            if (RT_SUCCESS(rc))
            {
                rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, pvData, cbData);
                vbclClipboardReleaseGuestData(&pvData, cbAlloc);
            }
            else
            {
                /* No data found or error occurred: send empty buffer */
                rc = vbclClipboardHostPasteData(u32ClientId, VBOX_SHARED_CLIPBOARD_FMT_HTML, NULL, 0);
            }

            fFormatsLeft &= ~(uint32_t)VBOX_SHARED_CLIPBOARD_FMT_HTML;
        }

        else
        {
            VBoxClientVerbose(3, "requested data in unsupported format: %#x\n", fFormatsLeft);
            break;
        }
    }

    return rc; /** @todo r=bird: If there are multiple formats available, which rc is returned here? Does it matter? */
}