/** * Retrieves and clears the user credentials for logging into the guest OS. * UTF-16 version. * * @returns IPRT status value * @param ppwszUser Receives pointer of allocated user name string. * The returned pointer must be freed using VbglR3CredentialsDestroyUtf16(). * @param ppswzPassword Receives pointer of allocated user password string. * The returned pointer must be freed using VbglR3CredentialsDestroyUtf16(). * @param ppwszDomain Receives pointer of allocated domain name string. * The returned pointer must be freed using VbglR3CredentialsDestroyUtf16(). */ VBGLR3DECL(int) VbglR3CredentialsRetrieveUtf16(PRTUTF16 *ppwszUser, PRTUTF16 *ppwszPassword, PRTUTF16 *ppwszDomain) { AssertPtrReturn(ppwszUser, VERR_INVALID_POINTER); AssertPtrReturn(ppwszPassword, VERR_INVALID_POINTER); AssertPtrReturn(ppwszDomain, VERR_INVALID_POINTER); char *pszUser, *pszPassword, *pszDomain; int rc = VbglR3CredentialsRetrieve(&pszUser, &pszPassword, &pszDomain); if (RT_SUCCESS(rc)) { PRTUTF16 pwszUser = NULL; PRTUTF16 pwszPassword = NULL; PRTUTF16 pwszDomain = NULL; rc = RTStrToUtf16(pszUser, &pwszUser); if (RT_SUCCESS(rc)) { rc = RTStrToUtf16(pszPassword, &pwszPassword); if (RT_SUCCESS(rc)) rc = RTStrToUtf16(pszDomain, &pwszDomain); } if (RT_SUCCESS(rc)) { *ppwszUser = pwszUser; *ppwszPassword = pwszPassword; *ppwszDomain = pwszDomain; } else VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* Passes */); VbglR3CredentialsDestroy(pszUser, pszPassword, pszDomain, 3 /* Passes */); } return rc; }
/** * 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; }
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; }
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; }
/** * 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; }
/** * 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; }
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(int) RTGetOptArgvToUtf16String(PRTUTF16 *ppwszCmdLine, const char * const *papszArgv, uint32_t fFlags) { char *pszCmdLine; int rc = RTGetOptArgvToString(&pszCmdLine, papszArgv, fFlags); if (RT_SUCCESS(rc)) { rc = RTStrToUtf16(pszCmdLine, ppwszCmdLine); RTStrFree(pszCmdLine); } return rc; }
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 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; }
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; }
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; }
RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen) { /* * Validate input. */ if (!pFile) { AssertMsgFailed(("Invalid pFile\n")); return VERR_INVALID_PARAMETER; } *pFile = NIL_RTFILE; if (!pszFilename) { AssertMsgFailed(("Invalid pszFilename\n")); return VERR_INVALID_PARAMETER; } /* * Merge forced open flags and validate them. */ int rc = rtFileRecalcAndValidateFlags(&fOpen); if (RT_FAILURE(rc)) return rc; /* * Determine disposition, access, share mode, creation flags, and security attributes * for the CreateFile API call. */ DWORD dwCreationDisposition; switch (fOpen & RTFILE_O_ACTION_MASK) { case RTFILE_O_OPEN: dwCreationDisposition = fOpen & RTFILE_O_TRUNCATE ? TRUNCATE_EXISTING : OPEN_EXISTING; break; case RTFILE_O_OPEN_CREATE: dwCreationDisposition = OPEN_ALWAYS; break; case RTFILE_O_CREATE: dwCreationDisposition = CREATE_NEW; break; case RTFILE_O_CREATE_REPLACE: dwCreationDisposition = CREATE_ALWAYS; break; default: AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen)); return VERR_INVALID_PARAMETER; } DWORD dwDesiredAccess; switch (fOpen & RTFILE_O_ACCESS_MASK) { case RTFILE_O_READ: dwDesiredAccess = FILE_GENERIC_READ; /* RTFILE_O_APPEND is ignored. */ break; case RTFILE_O_WRITE: dwDesiredAccess = fOpen & RTFILE_O_APPEND ? FILE_GENERIC_WRITE & ~FILE_WRITE_DATA : FILE_GENERIC_WRITE; break; case RTFILE_O_READWRITE: dwDesiredAccess = fOpen & RTFILE_O_APPEND ? FILE_GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA) : FILE_GENERIC_READ | FILE_GENERIC_WRITE; break; default: AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen)); return VERR_INVALID_PARAMETER; } if (dwCreationDisposition == TRUNCATE_EXISTING) /* Required for truncating the file (see MSDN), it is *NOT* part of FILE_GENERIC_WRITE. */ dwDesiredAccess |= GENERIC_WRITE; /* RTFileSetMode needs following rights as well. */ switch (fOpen & RTFILE_O_ACCESS_ATTR_MASK) { case RTFILE_O_ACCESS_ATTR_READ: dwDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break; case RTFILE_O_ACCESS_ATTR_WRITE: dwDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break; case RTFILE_O_ACCESS_ATTR_READWRITE: dwDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break; default: /* Attributes access is the same as the file access. */ switch (fOpen & RTFILE_O_ACCESS_MASK) { case RTFILE_O_READ: dwDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break; case RTFILE_O_WRITE: dwDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break; case RTFILE_O_READWRITE: dwDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break; default: AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen)); return VERR_INVALID_PARAMETER; } } DWORD dwShareMode; switch (fOpen & RTFILE_O_DENY_MASK) { case RTFILE_O_DENY_NONE: dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; break; case RTFILE_O_DENY_READ: dwShareMode = FILE_SHARE_WRITE; break; case RTFILE_O_DENY_WRITE: dwShareMode = FILE_SHARE_READ; break; case RTFILE_O_DENY_READWRITE: dwShareMode = 0; break; case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_NONE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; break; case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_WRITE; break; case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ; break; case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READWRITE:dwShareMode = FILE_SHARE_DELETE; break; default: AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen)); return VERR_INVALID_PARAMETER; } SECURITY_ATTRIBUTES SecurityAttributes; PSECURITY_ATTRIBUTES pSecurityAttributes = NULL; if (fOpen & RTFILE_O_INHERIT) { SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = TRUE; pSecurityAttributes = &SecurityAttributes; } DWORD dwFlagsAndAttributes; dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; if (fOpen & RTFILE_O_WRITE_THROUGH) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH; if (fOpen & RTFILE_O_ASYNC_IO) dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED; if (fOpen & RTFILE_O_NO_CACHE) { dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING; dwDesiredAccess &= ~FILE_APPEND_DATA; } /* * Open/Create the file. */ PRTUTF16 pwszFilename; rc = RTStrToUtf16(pszFilename, &pwszFilename); if (RT_FAILURE(rc)) return rc; HANDLE hFile = CreateFileW(pwszFilename, dwDesiredAccess, dwShareMode, pSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL); if (hFile != INVALID_HANDLE_VALUE) { bool fCreated = dwCreationDisposition == CREATE_ALWAYS || dwCreationDisposition == CREATE_NEW || (dwCreationDisposition == OPEN_ALWAYS && GetLastError() == 0); /* * Turn off indexing of directory through Windows Indexing Service. */ if ( fCreated && (fOpen & RTFILE_O_NOT_CONTENT_INDEXED)) { if (!SetFileAttributesW(pwszFilename, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) rc = RTErrConvertFromWin32(GetLastError()); } /* * Do we need to truncate the file? */ else if ( !fCreated && (fOpen & (RTFILE_O_TRUNCATE | RTFILE_O_ACTION_MASK)) == (RTFILE_O_TRUNCATE | RTFILE_O_OPEN_CREATE)) { if (!SetEndOfFile(hFile)) rc = RTErrConvertFromWin32(GetLastError()); } if (RT_SUCCESS(rc)) { *pFile = (RTFILE)hFile; Assert((HANDLE)*pFile == hFile); RTUtf16Free(pwszFilename); return VINF_SUCCESS; } CloseHandle(hFile); } else rc = RTErrConvertFromWin32(GetLastError()); RTUtf16Free(pwszFilename); 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); }
/** * 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? */ }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/) { LPCTSTR lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */ /* * Need to parse the command line before initializing the VBox runtime. */ TCHAR szTokens[] = _T("-/"); LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); while (lpszToken != NULL) { if (WordCmpI(lpszToken, _T("Embedding")) == 0) { /* %HOMEDRIVE%%HOMEPATH% */ wchar_t wszHome[RTPATH_MAX]; DWORD cEnv = GetEnvironmentVariable(L"HOMEDRIVE", &wszHome[0], RTPATH_MAX); if (cEnv && cEnv < RTPATH_MAX) { DWORD cwc = cEnv; /* doesn't include NUL */ cEnv = GetEnvironmentVariable(L"HOMEPATH", &wszHome[cEnv], RTPATH_MAX - cwc); if (cEnv && cEnv < RTPATH_MAX - cwc) { /* If this fails there is nothing we can do. Ignore. */ SetCurrentDirectory(wszHome); } } } lpszToken = FindOneOf(lpszToken, szTokens); } /* * Initialize the VBox runtime without loading * the support driver. */ int argc = __argc; char **argv = __argv; RTR3InitExe(argc, &argv, 0); /* Note that all options are given lowercase/camel case/uppercase to * approximate case insensitive matching, which RTGetOpt doesn't offer. */ static const RTGETOPTDEF s_aOptions[] = { { "--embedding", 'e', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "-embedding", 'e', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "/embedding", 'e', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "--unregserver", 'u', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "-unregserver", 'u', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "/unregserver", 'u', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "--regserver", 'r', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "-regserver", 'r', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "/regserver", 'r', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "--reregserver", 'f', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "-reregserver", 'f', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "/reregserver", 'f', RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE }, { "--helper", 'H', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "-helper", 'H', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "/helper", 'H', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "--logfile", 'F', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "-logfile", 'F', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "/logfile", 'F', RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE }, { "--logrotate", 'R', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, { "-logrotate", 'R', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, { "/logrotate", 'R', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, { "--logsize", 'S', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE }, { "-logsize", 'S', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE }, { "/logsize", 'S', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE }, { "--loginterval", 'I', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, { "-loginterval", 'I', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, { "/loginterval", 'I', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE }, }; bool fRun = true; bool fRegister = false; bool fUnregister = false; const char *pszPipeName = NULL; const char *pszLogFile = NULL; uint32_t cHistory = 10; // enable log rotation, 10 files uint32_t uHistoryFileTime = RT_SEC_1DAY; // max 1 day per file uint64_t uHistoryFileSize = 100 * _1M; // max 100MB per file RTGETOPTSTATE GetOptState; int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/); AssertRC(vrc); RTGETOPTUNION ValueUnion; while ((vrc = RTGetOpt(&GetOptState, &ValueUnion))) { switch (vrc) { case 'e': /* already handled above */ break; case 'u': fUnregister = true; fRun = false; break; case 'r': fRegister = true; fRun = false; break; case 'f': fUnregister = true; fRegister = true; fRun = false; break; case 'H': pszPipeName = ValueUnion.psz; if (!pszPipeName) pszPipeName = ""; fRun = false; break; case 'F': pszLogFile = ValueUnion.psz; break; case 'R': cHistory = ValueUnion.u32; break; case 'S': uHistoryFileSize = ValueUnion.u64; break; case 'I': uHistoryFileTime = ValueUnion.u32; break; case 'h': { TCHAR txt[]= L"Options:\n\n" L"/RegServer:\tregister COM out-of-proc server\n" L"/UnregServer:\tunregister COM out-of-proc server\n" L"/ReregServer:\tunregister and register COM server\n" L"no options:\trun the server"; TCHAR title[]=_T("Usage"); fRun = false; MessageBox(NULL, txt, title, MB_OK); return 0; } case 'V': { char *psz = NULL; RTStrAPrintf(&psz, "%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr()); PRTUTF16 txt = NULL; RTStrToUtf16(psz, &txt); TCHAR title[]=_T("Version"); fRun = false; MessageBox(NULL, txt, title, MB_OK); RTStrFree(psz); RTUtf16Free(txt); return 0; } default: /** @todo this assumes that stderr is visible, which is not * true for standard Windows applications. */ /* continue on command line errors... */ RTGetOptPrintError(vrc, &ValueUnion); } } /* Only create the log file when running VBoxSVC normally, but not when * registering/unregistering or calling the helper functionality. */ if (fRun) { if (!pszLogFile) { char szLogFile[RTPATH_MAX]; vrc = com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile)); if (RT_SUCCESS(vrc)) vrc = RTPathAppend(szLogFile, sizeof(szLogFile), "VBoxSVC.log"); if (RT_SUCCESS(vrc)) pszLogFile = RTStrDup(szLogFile); } char szError[RTPATH_MAX + 128]; vrc = com::VBoxLogRelCreate("COM Server", pszLogFile, RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG, "all", "VBOXSVC_RELEASE_LOG", RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */, cHistory, uHistoryFileTime, uHistoryFileSize, szError, sizeof(szError)); if (RT_FAILURE(vrc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, vrc); } int nRet = 0; HRESULT hRes = com::Initialize(); _ASSERTE(SUCCEEDED(hRes)); _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox); _Module.dwThreadID = GetCurrentThreadId(); if (!fRun) { if (fUnregister) { _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE); nRet = _Module.UnregisterServer(TRUE); } if (fRegister) { _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE); nRet = _Module.RegisterServer(TRUE); } if (pszPipeName) { Log(("SVCMAIN: Processing Helper request (cmdline=\"%s\")...\n", pszPipeName)); if (!*pszPipeName) vrc = VERR_INVALID_PARAMETER; if (RT_SUCCESS(vrc)) { /* do the helper job */ SVCHlpServer server; vrc = server.open(pszPipeName); if (RT_SUCCESS(vrc)) vrc = server.run(); } if (RT_FAILURE(vrc)) { Log(("SVCMAIN: Failed to process Helper request (%Rrc).", vrc)); nRet = 1; } } } else { _Module.StartMonitor(); #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); _ASSERTE(SUCCEEDED(hRes)); hRes = CoResumeClassObjects(); #else hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); #endif _ASSERTE(SUCCEEDED(hRes)); MSG msg; while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg); _Module.RevokeClassObjects(); Sleep(dwPause); //wait for any threads to finish } _Module.Term(); com::Shutdown(); Log(("SVCMAIN: Returning, COM server process ends.\n")); return nRet; }
/** * 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); } }