/** * 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; }
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; }
/** * 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; }
/** * 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); }
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; }
/** * 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; }
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; }
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; }
/** * 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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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(); }
/** * 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; }
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; }
/** * 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; }
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; }
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; }
/** * 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? */ }