/** * 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); }
/** * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns * E_OUTOFMEMORY instead. * * @param a_pbstr The source string. * @returns S_OK or E_OUTOFMEMORY. */ HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr) { if (a_pbstr && *a_pbstr) { int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr, RTSTR_MAX, // size_t cwcString: translate entire string &m_psz, // char **ppsz: output buffer 0, // size_t cch: if 0, func allocates buffer in *ppsz &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator. if (RT_SUCCESS(vrc)) m_cbAllocated = m_cch + 1; else { if ( vrc != VERR_NO_STR_MEMORY && vrc != VERR_NO_MEMORY) { /* ASSUME: input is valid Utf-16. Fake out of memory error. */ AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len((PCRTUTF16)a_pbstr) * sizeof(RTUTF16), a_pbstr)); } m_cch = 0; m_cbAllocated = 0; m_psz = NULL; return E_OUTOFMEMORY; } } else { m_cch = 0; m_cbAllocated = 0; m_psz = NULL; } return S_OK; }
/** * Gets the user home directory. * * @returns iprt status code. * @param pszPath Buffer where to store the path. * @param cchPath Buffer size in bytes. */ RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath) { RTUTF16 wszPath[RTPATH_MAX]; DWORD dwAttr; /* * There are multiple definitions for what WE think of as user home... */ if ( !GetEnvironmentVariableW(L"HOME", &wszPath[0], RTPATH_MAX) || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { if ( !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX) || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { /* %HOMEDRIVE%%HOMEPATH% */ if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX)) return VERR_PATH_NOT_FOUND; size_t const cwc = RTUtf16Len(&wszPath[0]); if ( !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc) || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) return VERR_PATH_NOT_FOUND; } } /* * Convert and return. */ return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL); }
RTDECL(int) RTPathSetCurrent(const char *pszPath) { /* * Validate input. */ AssertPtrReturn(pszPath, VERR_INVALID_POINTER); AssertReturn(*pszPath, VERR_INVALID_PARAMETER); /* * This interface is almost identical to the Windows API. */ PRTUTF16 pwszPath; int rc = RTStrToUtf16(pszPath, &pwszPath); if (RT_SUCCESS(rc)) { /** @todo improve the slash stripping a bit? */ size_t cwc = RTUtf16Len(pwszPath); if ( cwc >= 2 && ( pwszPath[cwc - 1] == L'/' || pwszPath[cwc - 1] == L'\\') && pwszPath[cwc - 2] != ':') pwszPath[cwc - 1] = L'\0'; if (!SetCurrentDirectoryW(pwszPath)) rc = RTErrConvertFromWin32(GetLastError()); RTUtf16Free(pwszPath); } return rc; }
/** * Assigns or copies a RTUTF16 string to a UNICODE_STRING. * * When fCopy is false, this does *not* copy its contents * and only assigns its code points to the destination! * When fCopy is true, the actual string buffer gets copied. * * Does not take terminating \0 into account. * * @return HRESULT * @param pUnicodeDest Unicode string assigning the UTF16 string to. * @param pwszSource UTF16 string to assign. * @param fCopy Whether to just assign or copy the actual buffer * contents from source -> dest. */ HRESULT VBoxCredProvCredential::RTUTF16ToUnicode(PUNICODE_STRING pUnicodeDest, PRTUTF16 pwszSource, bool fCopy) { AssertPtrReturn(pUnicodeDest, E_POINTER); AssertPtrReturn(pwszSource, E_POINTER); size_t cbLen = RTUtf16Len(pwszSource) * sizeof(RTUTF16); AssertReturn(cbLen <= USHORT_MAX, E_INVALIDARG); HRESULT hr; if (fCopy) { if (cbLen <= pUnicodeDest->MaximumLength) { memcpy(pUnicodeDest->Buffer, pwszSource, cbLen); pUnicodeDest->Length = (USHORT)cbLen; hr = S_OK; } else hr = E_INVALIDARG; } else /* Just assign the buffer. */ { pUnicodeDest->Buffer = pwszSource; pUnicodeDest->Length = (USHORT)cbLen; hr = S_OK; } return hr; }
RTDECL(PRTUTF16) RTUtf16DupTag(PCRTUTF16 pwszString, const char *pszTag) { Assert(pwszString); size_t cb = (RTUtf16Len(pwszString) + 1) * sizeof(RTUTF16); PRTUTF16 pwsz = (PRTUTF16)RTMemAllocTag(cb, pszTag); if (pwsz) memcpy(pwsz, pwszString, cb); return pwsz; }
/** * Gets the user home directory. * * @returns iprt status code. * @param pszPath Buffer where to store the path. * @param cchPath Buffer size in bytes. */ RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath) { /* * Validate input */ AssertPtrReturn(pszPath, VERR_INVALID_POINTER); AssertReturn(cchPath, VERR_INVALID_PARAMETER); RTUTF16 wszPath[RTPATH_MAX]; bool fValidFolderPath = false; /* * Try with Windows XP+ functionality first. */ RTLDRMOD hShell32; int rc = RTLdrLoadSystem("Shell32.dll", true /*fNoUnload*/, &hShell32); if (RT_SUCCESS(rc)) { PFNSHGETFOLDERPATHW pfnSHGetFolderPathW; rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW); if (RT_SUCCESS(rc)) { HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, wszPath); fValidFolderPath = (hrc == S_OK); } RTLdrClose(hShell32); } DWORD dwAttr; if ( !fValidFolderPath || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { /* * Fall back to Windows specific environment variables. HOME is not used. */ if ( !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX) || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { /* %HOMEDRIVE%%HOMEPATH% */ if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX)) return VERR_PATH_NOT_FOUND; size_t const cwc = RTUtf16Len(&wszPath[0]); if ( !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc) || (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) return VERR_PATH_NOT_FOUND; } } /* * Convert and return. */ return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL); }
RTDECL(int) RTUtf16DupExTag(PRTUTF16 *ppwszString, PCRTUTF16 pwszString, size_t cwcExtra, const char *pszTag) { Assert(pwszString); size_t cb = (RTUtf16Len(pwszString) + 1) * sizeof(RTUTF16); PRTUTF16 pwsz = (PRTUTF16)RTMemAllocTag(cb + cwcExtra * sizeof(RTUTF16), pszTag); if (pwsz) { memcpy(pwsz, pwszString, cb); *ppwszString = pwsz; return VINF_SUCCESS; } return VERR_NO_MEMORY; }
/** * Finds the root of the specified volume. * * @returns iprt status code. * @param pszFsPath Path within the filesystem. Verified as one byte or more. * @param ppwszFsRoot Where to store the returned string. Free with rtFsFreeRoot(), */ static int rtFsGetRoot(const char *pszFsPath, PRTUTF16 *ppwszFsRoot) { /* * Do straight forward stuff first, */ if (rtFsIsRoot(pszFsPath)) return RTStrToUtf16(pszFsPath, ppwszFsRoot); /* * Expand and add slash (if required). */ char szFullPath[RTPATH_MAX]; int rc = RTPathAbs(pszFsPath, szFullPath, sizeof(szFullPath)); if (RT_FAILURE(rc)) return rc; size_t cb = strlen(szFullPath); if (!RTPATH_IS_SLASH(szFullPath[cb - 1])) { AssertReturn(cb + 1 < RTPATH_MAX, VERR_FILENAME_TOO_LONG); szFullPath[cb] = '\\'; szFullPath[++cb] = '\0'; } /* * Convert the path. */ rc = RTStrToUtf16(szFullPath, ppwszFsRoot); if (RT_FAILURE(rc)) return rc == VERR_BUFFER_OVERFLOW ? VERR_FILENAME_TOO_LONG : rc; /* * Walk the path until our proper API is happy or there is no more path left. */ PRTUTF16 pwszStart = *ppwszFsRoot; if (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0)) { PRTUTF16 pwszEnd = pwszStart + RTUtf16Len(pwszStart); PRTUTF16 pwszMin = pwszStart + 2; do { /* Strip off the last path component. */ while (pwszEnd-- > pwszMin) if (RTPATH_IS_SLASH(*pwszEnd)) break; AssertReturn(pwszEnd >= pwszMin, VERR_INTERNAL_ERROR); /* leaks, but that's irrelevant for an internal error. */ pwszEnd[1] = '\0'; } while (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0)); } return VINF_SUCCESS; }
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf) { /* * Convert the filter to UTF-16. */ int rc; pDir->pNtFilterStr = NULL; if ( pDir->cchFilter > 0 && pDir->enmFilter == RTDIRFILTER_WINNT) { PRTUTF16 pwszTmp; rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp); if (RT_FAILURE(rc)) return rc; pDir->NtFilterStr.Buffer = pwszTmp; pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16)); pDir->pNtFilterStr = &pDir->NtFilterStr; } /* * Try open the directory */ #ifdef IPRT_WITH_NT_PATH_PASSTHRU bool fObjDir; #endif rc = rtNtPathOpenDir(pszPathBuf, FILE_READ_DATA | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, OBJ_CASE_INSENSITIVE, &pDir->hDir, #ifdef IPRT_WITH_NT_PATH_PASSTHRU &fObjDir #else NULL #endif ); if (RT_SUCCESS(rc)) { /* * Init data. */ pDir->fDataUnread = false; /* spelling it out */ #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (fObjDir) pDir->enmInfoClass = FileMaximumInformation; /* object directory. */ #endif } return rc; }
/** * Copies an UTF16 string into a PUNICODE_STRING by allocating space for it. * * @return HRESULT * @param pUnicodeDest Where to store the copied (allocated) unicode string. * @param pwszSource UTF16 string to copy. */ HRESULT VBoxCredProvCredential::RTUTF16ToUnicodeA(PUNICODE_STRING pUnicodeDest, PRTUTF16 pwszSource) { AssertPtrReturn(pUnicodeDest, E_POINTER); AssertPtrReturn(pwszSource, E_POINTER); size_t cbLen = RTUtf16Len(pwszSource) * sizeof(RTUTF16); pUnicodeDest->Buffer = (LPWSTR)CoTaskMemAlloc(cbLen); if (!pUnicodeDest->Buffer) return E_OUTOFMEMORY; pUnicodeDest->MaximumLength = (USHORT)cbLen; pUnicodeDest->Length = 0; return RTUTF16ToUnicode(pUnicodeDest, pwszSource, true /* fCopy */); }
/** * Sets a credential provider field by first zero'ing out its current content in a (hopefully) secure manner, * then applying either the field's default or a new value. * * @return HRESULT * @param dwFieldID Field ID of the credential provider field to reset. * @param pcwszString String to set for the given field. Specify NULL for setting the provider's default value. * @param fNotifyUI Whether to notify the LogonUI about the reset. */ HRESULT VBoxCredProvCredential::setField(DWORD dwFieldID, const PRTUTF16 pcwszString, bool fNotifyUI) { if (dwFieldID >= VBOXCREDPROV_NUM_FIELDS) return E_INVALIDARG; HRESULT hr = S_OK; PRTUTF16 pwszField = m_apwszFields[dwFieldID]; if (pwszField) { /* First, wipe the existing value thoroughly. */ RTMemWipeThoroughly(pwszField, (RTUtf16Len(pwszField) + 1) * sizeof(RTUTF16), 3 /* Passes */); /* Second, free the string. */ RTUtf16Free(pwszField); } /* Either fill in the default value or the one specified in pcwszString. */ pwszField = RTUtf16Dup(pcwszString ? pcwszString : s_VBoxCredProvDefaultFields[dwFieldID].desc.pszLabel); if (pwszField) { m_apwszFields[dwFieldID] = pwszField; /* Update the pointer. */ if ( m_pEvents && fNotifyUI) /* Let the logon UI know if wanted. */ { hr = m_pEvents->SetFieldString(this, dwFieldID, pwszField); } } else hr = E_OUTOFMEMORY; VBoxCredProvVerbose(0, "VBoxCredProvCredential::setField: Setting field dwFieldID=%ld to '%ls', fNotifyUI=%RTbool, hr=0x%08x\n", dwFieldID, #ifdef DEBUG pwszField, #else /* Don't show any passwords in release mode. */ dwFieldID == VBOXCREDPROV_FIELDID_PASSWORD ? L"XXX" : pwszField, #endif fNotifyUI, hr); return hr; }
static void supR3HardenedFindOrLoadModule(PSUPHNTIMPDLL pDll) { #ifdef VBOX_HARDENED_STUB_WITHOUT_IMPORTS uint32_t const cbName = (uint32_t)RTUtf16Len(pDll->pwszName) * sizeof(WCHAR); PPEB_LDR_DATA pLdrData = NtCurrentPeb()->Ldr; LIST_ENTRY *pList = &pLdrData->InMemoryOrderModuleList; LIST_ENTRY *pListEntry = pList->Flink; uint32_t cLoops = 0; while (pListEntry != pList && cLoops < 1024) { PLDR_DATA_TABLE_ENTRY pLdrEntry = RT_FROM_MEMBER(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if ( pLdrEntry->FullDllName.Length > cbName + sizeof(WCHAR) && ( pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '\\' || pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR) - 1] == '/') && RTUtf16ICmpAscii(&pLdrEntry->FullDllName.Buffer[(pLdrEntry->FullDllName.Length - cbName) / sizeof(WCHAR)], pDll->pszName) == 0) { pDll->pbImageBase = (uint8_t *)pLdrEntry->DllBase; return; } pListEntry = pListEntry->Flink; cLoops++; } if (!pDll->cImports) pDll->pbImageBase = NULL; /* optional */ else SUPHNTIMP_ERROR(false, 1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, "Failed to locate %ls", pDll->pwszName); #else HMODULE hmod = GetModuleHandleW(pDll->pwszName); if (RT_UNLIKELY(!hmod && pDll->cImports)) SUPHNTIMP_ERROR(true, 1, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, "Failed to locate %ls", pDll->pwszName); pDll->pbImageBase = (uint8_t *)hmod; #endif }
/** * Returns the string length in bytes without the terminator * @returns unsigned int length in bytes * @param bstr source string */ unsigned int SysStringByteLen(BSTR bstr) { return RTUtf16Len(bstr) * sizeof(OLECHAR); }
/** * Retrieves the data stored in this object and store the result in * pMedium. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc * @param pMedium */ STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium) { AssertPtrReturn(pFormatEtc, DV_E_FORMATETC); AssertPtrReturn(pMedium, DV_E_FORMATETC); HRESULT hr = DV_E_FORMATETC; LPFORMATETC pThisFormat = NULL; LPSTGMEDIUM pThisMedium = NULL; LogFlowThisFunc(("\n")); /* Format supported? */ ULONG lIndex; if ( LookupFormatEtc(pFormatEtc, &lIndex) && lIndex < m_cFormats) /* Paranoia. */ { pThisMedium = &m_pStgMedium[lIndex]; AssertPtr(pThisMedium); pThisFormat = &m_pFormatEtc[lIndex]; AssertPtr(pThisFormat); LogFlowThisFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat)); LogFlowThisFunc(("mStatus=%RU32\n", m_enmStatus)); switch (m_enmStatus) { case DnDDataObjectStatus_Dropping: { #if 0 LogRel3(("DnD: Dropping\n")); LogFlowFunc(("Waiting for event ...\n")); int rc2 = RTSemEventWait(m_SemEvent, RT_INDEFINITE_WAIT); LogFlowFunc(("rc=%Rrc, mStatus=%RU32\n", rc2, m_enmStatus)); #endif break; } case DnDDataObjectStatus_Dropped: { LogRel3(("DnD: Dropped\n")); LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), pThisFormat->tymed, pThisFormat->dwAspect)); LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n", m_strFormat.toUtf8().constData(), m_pvData, m_cbData)); QVariant::Type vaType; QString strMIMEType; if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && ( pFormatEtc->cfFormat == CF_TEXT || pFormatEtc->cfFormat == CF_UNICODETEXT) ) { strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */ vaType = QVariant::String; } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_HDROP)) { strMIMEType = "text/uri-list"; vaType = QVariant::StringList; } #if 0 /* More formats; not needed right now. */ else if ( (pFormatEtc->tymed & TYMED_ISTREAM) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILECONTENTS)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT)) { HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD)); DWORD *pdwEffect = (DWORD *)GlobalLock(hData); AssertPtr(pdwEffect); *pdwEffect = DROPEFFECT_COPY; GlobalUnlock(hData); pMedium->hGlobal = hData; pMedium->tymed = TYMED_HGLOBAL; } #endif LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toUtf8().constData(), vaType)); int rc; if (!m_fDataRetrieved) { if (m_pDnDHandler) { rc = m_pDnDHandler->retrieveData(Qt::CopyAction, strMIMEType, vaType, m_vaData); } else rc = VERR_NOT_FOUND; m_fDataRetrieved = true; LogFlowFunc(("Retrieving data ended with %Rrc\n", rc)); } else /* Data already been retrieved. */ rc = VINF_SUCCESS; if ( RT_SUCCESS(rc) && m_vaData.isValid()) { if ( strMIMEType.startsWith("text/uri-list") /* One item. */ && ( m_vaData.canConvert(QVariant::String) /* Multiple items. */ || m_vaData.canConvert(QVariant::StringList)) ) { QStringList lstFilesURI = m_vaData.toStringList(); QStringList lstFiles; for (size_t i = 0; i < lstFilesURI.size(); i++) { char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).toUtf8().constData()); if (pszFilePath) { lstFiles.append(pszFilePath); RTStrFree(pszFilePath); } else /* Unable to parse -- refuse entire request. */ { lstFiles.clear(); rc = VERR_INVALID_PARAMETER; break; } } size_t cFiles = lstFiles.size(); LogFlowThisFunc(("Files (%zu)\n", cFiles)); if ( RT_SUCCESS(rc) && cFiles) { size_t cchFiles = 0; /* Number of characters. */ for (size_t i = 0; i < cFiles; i++) { const char *pszFile = lstFiles.at(i).toUtf8().constData(); cchFiles += strlen(pszFile); cchFiles += 1; /* Terminating '\0'. */ LogFlowThisFunc(("\tFile: %s (cchFiles=%zu)\n", pszFile, cchFiles)); } /* List termination with '\0'. */ cchFiles++; size_t cbBuf = sizeof(DROPFILES) + (cchFiles * sizeof(RTUTF16)); DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf); if (pDropFiles) { /* Put the files list right after our DROPFILES structure. */ pDropFiles->pFiles = sizeof(DROPFILES); /* Offset to file list. */ pDropFiles->fWide = 1; /* We use Unicode. Always. */ uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles; AssertPtr(pCurFile); LogFlowThisFunc(("Encoded:\n")); for (size_t i = 0; i < cFiles; i++) { const char *pszFile = lstFiles.at(i).toUtf8().constData(); Assert(strlen(pszFile)); size_t cchCurFile; PRTUTF16 pwszFile; rc = RTStrToUtf16(pszFile, &pwszFile); if (RT_SUCCESS(rc)) { cchCurFile = RTUtf16Len(pwszFile); Assert(cchCurFile); memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16)); RTUtf16Free(pwszFile); } else break; pCurFile += cchCurFile * sizeof(RTUTF16); /* Terminate current file name. */ *pCurFile = L'\0'; pCurFile += sizeof(RTUTF16); LogFlowThisFunc(("\t#%zu: cchCurFile=%zu\n", i, cchCurFile)); } if (RT_SUCCESS(rc)) { *pCurFile = L'\0'; /* Final list terminator. */ /* * Fill out the medium structure we're going to report back. */ pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbBuf); if (pMedium->hGlobal) { LPVOID pvMem = GlobalLock(pMedium->hGlobal); if (pvMem) { memcpy(pvMem, pDropFiles, cbBuf); GlobalUnlock(pMedium->hGlobal); hr = S_OK; } else rc = VERR_ACCESS_DENIED; } else rc = VERR_NO_MEMORY; LogFlowThisFunc(("Copying to TYMED_HGLOBAL (%zu bytes): %Rrc\n", cbBuf, rc)); } RTMemFree(pDropFiles); } else rc = VERR_NO_MEMORY; if (RT_FAILURE(rc)) LogFlowThisFunc(("Failed with %Rrc\n", rc)); } } else if ( strMIMEType.startsWith("text/plain") && m_vaData.canConvert(QVariant::String)) { const bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT; const size_t cbCh = fUnicode ? sizeof(WCHAR) : sizeof(char); QString strText = m_vaData.toString(); size_t cbSrc = strText.length() * cbCh; Assert(cbSrc); LPCVOID pvSrc = fUnicode ? (void *)strText.unicode() : (void *)strText.toUtf8().constData(); AssertPtr(pvSrc); LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbCh=%zu, fUnicode=%RTbool\n", pvSrc, cbSrc, cbCh, fUnicode)); pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cbSrc); if (pMedium->hGlobal) { LPVOID pvDst = GlobalLock(pMedium->hGlobal); if (pvDst) { memcpy(pvDst, pvSrc, cbSrc); GlobalUnlock(pMedium->hGlobal); } else rc = VERR_ACCESS_DENIED; hr = S_OK; } else hr = VERR_NO_MEMORY; } else LogRel2(("DnD: MIME type '%s' not supported\n", strMIMEType.toUtf8().constData())); LogFlowThisFunc(("Handling formats ended with rc=%Rrc\n", rc)); } break; } default: break; } } /* * Fallback in error case. */ if (FAILED(hr)) { if (pThisMedium) { switch (pThisMedium->tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, 0 /* Flags */); break; default: break; } } if (pFormatEtc) pMedium->tymed = pFormatEtc->tymed; pMedium->pUnkForRelease = NULL; } LogFlowThisFunc(("Returning hr=%Rhrc\n", hr)); return hr; }
void VBoxClipboardService::MessageReceived(BMessage *message) { uint32_t formats = 0; message->PrintToStream(); switch (message->what) { case VBOX_GUEST_CLIPBOARD_HOST_MSG_FORMATS: { int rc; uint32_t cb; void *pv; bool commit = false; if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) break; if (!formats) break; if (!be_clipboard->Lock()) break; be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, &cb); if (pv) { char *text; rc = RTUtf16ToUtf8((PCRTUTF16)pv, &text); if (RT_SUCCESS(rc)) { BString str(text); /** @todo user vboxClipboardUtf16WinToLin() */ // convert Windows CRLF to LF str.ReplaceAll("\r\n", "\n"); // don't include the \0 clip->AddData("text/plain", B_MIME_TYPE, str.String(), str.Length()); RTStrFree(text); commit = true; } free(pv); } } if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { pv = _VBoxReadHostClipboard(VBOX_SHARED_CLIPBOARD_FMT_BITMAP, &cb); if (pv) { void *pBmp = NULL; size_t cbBmp = 0; rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmp); if (RT_SUCCESS(rc)) { BMemoryIO mio(pBmp, cbBmp); BBitmap *bitmap = BTranslationUtils::GetBitmap(&mio); if (bitmap) { BMessage bitmapArchive; /** @todo r=ramshankar: split this into functions with error checking as * neccessary. */ if ( bitmap->IsValid() && bitmap->Archive(&bitmapArchive) == B_OK && clip->AddMessage("image/bitmap", &bitmapArchive) == B_OK) { commit = true; } delete bitmap; } RTMemFree(pBmp); } free(pv); } } /* * Make sure we don't bounce this data back to the host, it's impolite. It can also * be used as a hint to applications probably. */ clip->AddBool("FromVirtualBoxHost", true); if (commit) be_clipboard->Commit(); be_clipboard->Unlock(); break; } case VBOX_GUEST_CLIPBOARD_HOST_MSG_READ_DATA: { int rc; if (message->FindInt32("Formats", (int32 *)&formats) != B_OK) break; if (!formats) break; if (!be_clipboard->Lock()) break; BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } clip->PrintToStream(); if (formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { const char *text; int32 textLen; if (clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &textLen) == B_OK) { // usually doesn't include the \0 so be safe BString str(text, textLen); // convert from LF to Windows CRLF str.ReplaceAll("\n", "\r\n"); PRTUTF16 pwsz; rc = RTStrToUtf16(str.String(), &pwsz); if (RT_SUCCESS(rc)) { uint32_t cb = (RTUtf16Len(pwsz) + 1) * sizeof(RTUTF16); rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, pwsz, cb); //printf("VbglR3ClipboardWriteData: %d\n", rc); RTUtf16Free(pwsz); } } } else if (formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { BMessage archivedBitmap; if (clip->FindMessage("image/bitmap", &archivedBitmap) == B_OK || clip->FindMessage("image/x-be-bitmap", &archivedBitmap) == B_OK) { BBitmap *bitmap = new(std::nothrow) BBitmap(&archivedBitmap); if (bitmap) { // Don't delete bitmap, BBitmapStream will. BBitmapStream stream(bitmap); BTranslatorRoster *roster = BTranslatorRoster::Default(); if (roster && bitmap->IsValid()) { BMallocIO bmpStream; if (roster->Translate(&stream, NULL, NULL, &bmpStream, B_BMP_FORMAT) == B_OK) { const void *pDib; size_t cbDibSize; /* Strip out the BM header */ rc = vboxClipboardBmpGetDib(bmpStream.Buffer(), bmpStream.BufferLength(), &pDib, &cbDibSize); if (RT_SUCCESS(rc)) { rc = VbglR3ClipboardWriteData(fClientId, VBOX_SHARED_CLIPBOARD_FMT_BITMAP, (void *)pDib, cbDibSize); } } } } } } be_clipboard->Unlock(); break; } case B_CLIPBOARD_CHANGED: { printf("B_CLIPBOARD_CHANGED\n"); const void *data; int32 dataLen; if (!be_clipboard->Lock()) break; BMessage *clip = be_clipboard->Data(); if (!clip) { be_clipboard->Unlock(); break; } bool fromVBox; if (clip->FindBool("FromVirtualBoxHost", &fromVBox) == B_OK && fromVBox) { // It already comes from the host, discard. be_clipboard->Unlock(); break; } if (clip->FindData("text/plain", B_MIME_TYPE, &data, &dataLen) == B_OK) formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; if ( clip->HasMessage("image/bitmap") || clip->HasMessage("image/x-be-bitmap")) { formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; } be_clipboard->Unlock(); VbglR3ClipboardReportFormats(fClientId, formats); break; } case B_QUIT_REQUESTED: fExiting = true; break; default: BHandler::MessageReceived(message); } }
/** * Read content from the host clipboard and write it to the internal clipboard * structure for further processing. * * @param pPasteboardRef Reference to the global pasteboard. * @param fFormats The format type which should be read. * @param pv The destination buffer. * @param cb The size of the destination buffer. * @param pcbActual The size which is needed to transfer the content. * * @returns IPRT status code. */ int readFromPasteboard(PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual) { Log(("readFromPasteboard: fFormat = %02X\n", fFormat)); OSStatus err = noErr; /* Make sure all is in sync */ PasteboardSynchronize(pPasteboard); /* Are some items in the pasteboard? */ ItemCount itemCount; err = PasteboardGetItemCount(pPasteboard, &itemCount); if (itemCount < 1) return VINF_SUCCESS; /* The id of the first element in the pasteboard */ int rc = VERR_NOT_SUPPORTED; PasteboardItemID itemID; if (!(err = PasteboardGetItemIdentifier(pPasteboard, 1, &itemID))) { /* The guest request unicode */ if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { CFDataRef outData; PRTUTF16 pwszTmp = NULL; /* Try utf-16 first */ if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF16PlainText, &outData))) { Log(("Clipboard content is utf-16\n")); PRTUTF16 pwszString = (PRTUTF16)CFDataGetBytePtr(outData); if (pwszString) rc = RTUtf16DupEx(&pwszTmp, pwszString, 0); else rc = VERR_INVALID_PARAMETER; } /* Second try is utf-8 */ else if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeUTF8PlainText, &outData))) { Log(("readFromPasteboard: clipboard content is utf-8\n")); const char *pszString = (const char *)CFDataGetBytePtr(outData); if (pszString) rc = RTStrToUtf16(pszString, &pwszTmp); else rc = VERR_INVALID_PARAMETER; } if (pwszTmp) { /* Check how much longer will the converted text will be. */ size_t cwSrc = RTUtf16Len(pwszTmp); size_t cwDest; rc = vboxClipboardUtf16GetWinSize(pwszTmp, cwSrc, &cwDest); if (RT_FAILURE(rc)) { RTUtf16Free(pwszTmp); Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } /* Set the actually needed data size */ *pcbActual = cwDest * 2; /* Return success state */ rc = VINF_SUCCESS; /* Do not copy data if the dst buffer is not big enough. */ if (*pcbActual <= cb) { rc = vboxClipboardUtf16LinToWin(pwszTmp, RTUtf16Len(pwszTmp), static_cast <PRTUTF16>(pv), cb / 2); if (RT_FAILURE(rc)) { RTUtf16Free(pwszTmp); Log(("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } #ifdef SHOW_CLIPBOARD_CONTENT Log(("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16>(pv))); #endif } /* Free the temp string */ RTUtf16Free(pwszTmp); } } /* The guest request BITMAP */ else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { CFDataRef outData; const void *pTmp = NULL; size_t cbTmpSize; /* Get the data from the pasteboard */ if (!(err = PasteboardCopyItemFlavorData(pPasteboard, itemID, kUTTypeBMP, &outData))) { Log(("Clipboard content is BMP\n")); pTmp = CFDataGetBytePtr(outData); cbTmpSize = CFDataGetLength(outData); } if (pTmp) { const void *pDib; size_t cbDibSize; rc = vboxClipboardBmpGetDib(pTmp, cbTmpSize, &pDib, &cbDibSize); if (RT_FAILURE(rc)) { rc = VERR_NOT_SUPPORTED; Log(("readFromPasteboard: unknown bitmap format. vboxClipboardBmpGetDib returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } *pcbActual = cbDibSize; /* Return success state */ rc = VINF_SUCCESS; /* Do not copy data if the dst buffer is not big enough. */ if (*pcbActual <= cb) { memcpy(pv, pDib, cbDibSize); #ifdef SHOW_CLIPBOARD_CONTENT Log(("readFromPasteboard: clipboard content bitmap %d bytes\n", cbDibSize)); #endif } } } } Log(("readFromPasteboard: rc = %02X\n", rc)); return rc; }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], &m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: User=%ls, Password=%ls, Domain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], #ifdef DEBUG m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], #else L"XXX" /* Don't show any passwords in release mode. */, #endif m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszAcount; if (TranslateAccountName(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name %ls -> %ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], pwszAcount); if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszDomain; if (ExtractAccoutData(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount, &pwszDomain)) { /* Update user name. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; /* Update domain. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME] = pwszDomain; VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account data pwszAccount=%ls, pwszDomain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } } m_fHaveCreds = true; } else { /* If credentials already were retrieved by a former call, don't try to retrieve new ones * and just report back the already retrieved ones. */ if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Credentials already retrieved\n"); rc = VINF_SUCCESS; } } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }
HRESULT VBoxCredProvCredential::kerberosLogonInit(KERB_INTERACTIVE_LOGON *pLogonIn, CREDENTIAL_PROVIDER_USAGE_SCENARIO enmUsage, PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain) { AssertPtrReturn(pLogonIn, E_INVALIDARG); AssertPtrReturn(pwszUser, E_INVALIDARG); AssertPtrReturn(pwszPassword, E_INVALIDARG); /* pwszDomain is optional. */ HRESULT hr; /* Do we have a domain name set? */ if ( pwszDomain && RTUtf16Len(pwszDomain)) { hr = RTUTF16ToUnicode(&pLogonIn->LogonDomainName, pwszDomain, true /* fCopy */); } else /* No domain (FQDN) given, try local computer name. */ { WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD cch = ARRAYSIZE(wszComputerName); if (GetComputerNameW(wszComputerName, &cch)) { /* Is a domain name missing? Then use the name of the local computer. */ hr = RTUTF16ToUnicode(&pLogonIn->LogonDomainName, wszComputerName, true /* fCopy */); VBoxCredProvVerbose(0, "VBoxCredProvCredential::kerberosLogonInit: Local computer name=%ls\n", wszComputerName); } else hr = HRESULT_FROM_WIN32(GetLastError()); } /* Fill in the username and password. */ if (SUCCEEDED(hr)) { hr = RTUTF16ToUnicode(&pLogonIn->UserName, pwszUser, true /* fCopy */); if (SUCCEEDED(hr)) { hr = RTUTF16ToUnicode(&pLogonIn->Password, pwszPassword, true /* fCopy */); if (SUCCEEDED(hr)) { /* Set credential type according to current usage scenario. */ switch (enmUsage) { case CPUS_UNLOCK_WORKSTATION: pLogonIn->MessageType = KerbWorkstationUnlockLogon; break; case CPUS_LOGON: pLogonIn->MessageType = KerbInteractiveLogon; break; case CPUS_CREDUI: pLogonIn->MessageType = (KERB_LOGON_SUBMIT_TYPE)0; /* No message type required here. */ break; default: VBoxCredProvVerbose(0, "VBoxCredProvCredential::kerberosLogonInit: Unknown usage scenario=%ld\n", enmUsage); hr = E_FAIL; break; } } } } return hr; }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { PRTUTF16 pwszUser = NULL; PRTUTF16 pwszPassword = NULL; PRTUTF16 pwszDomain = NULL; int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Received credentials for user '%ls'\n", pwszUser); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszExtractedName = NULL; if ( TranslateAccountName(pwszUser, &pwszExtractedName) && pwszExtractedName) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name '%ls' -> '%ls'\n", pwszUser, pwszExtractedName); RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszExtractedDomain = NULL; if (ExtractAccoutData(pwszUser, &pwszExtractedName, &pwszExtractedDomain)) { /* Update user name. */ if (pwszExtractedName) { if (pwszUser) { RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); } pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } /* Update domain. */ if (pwszExtractedDomain) { if (pwszDomain) { RTMemWipeThoroughly(pwszDomain, (RTUtf16Len(pwszDomain) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszDomain); } pwszDomain = RTUtf16Dup(pwszExtractedDomain); CoTaskMemFree(pwszExtractedDomain); pwszExtractedDomain = NULL; } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account name '%ls' + domain '%ls'\n", pwszUser ? pwszUser : L"<NULL>", pwszDomain ? pwszDomain : L"<NULL>"); } } m_fHaveCreds = true; } if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Setting fields\n"); setField(VBOXCREDPROV_FIELDID_USERNAME, pwszUser, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_PASSWORD, pwszPassword, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_DOMAINNAME, pwszDomain, true /* fNotifyUI */); } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Wiping ...\n"); VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* cPasses */); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }
int rtDirNativeOpen(PRTDIRINTERNAL pDir, uintptr_t hRelativeDir, void *pvNativeRelative) { /* * Convert the filter to UTF-16. */ int rc; pDir->pNtFilterStr = NULL; if ( pDir->cchFilter > 0 && pDir->enmFilter == RTDIRFILTER_WINNT) { PRTUTF16 pwszTmp; rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp); if (RT_FAILURE(rc)) return rc; pDir->NtFilterStr.Buffer = pwszTmp; pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16)); pDir->pNtFilterStr = &pDir->NtFilterStr; } /* * Try open the directory */ #ifdef IPRT_WITH_NT_PATH_PASSTHRU bool fObjDir = false; #endif if (hRelativeDir != ~(uintptr_t)0 && pvNativeRelative == NULL) { /* Caller already opened it, easy! */ pDir->hDir = (HANDLE)hRelativeDir; rc = VINF_SUCCESS; } else { /* * If we have to check for reparse points, this gets complicated! */ static int volatile g_fReparsePoints = -1; uint32_t fOptions = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT; int fReparsePoints = g_fReparsePoints; if ( fReparsePoints != 0 && (pDir->fFlags & RTDIR_F_NO_FOLLOW) && !pDir->fDirSlash) fOptions |= FILE_OPEN_REPARSE_POINT; for (;;) { if (pvNativeRelative == NULL) rc = RTNtPathOpenDir(pDir->pszPath, FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, fOptions, OBJ_CASE_INSENSITIVE, &pDir->hDir, #ifdef IPRT_WITH_NT_PATH_PASSTHRU &fObjDir #else NULL #endif ); else rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir, (struct _UNICODE_STRING *)pvNativeRelative, FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, fOptions, OBJ_CASE_INSENSITIVE, &pDir->hDir, #ifdef IPRT_WITH_NT_PATH_PASSTHRU &fObjDir #else NULL #endif ); if ( !(fOptions & FILE_OPEN_REPARSE_POINT) || (rc != VINF_SUCCESS && rc != VERR_INVALID_PARAMETER) ) break; if (rc == VINF_SUCCESS) { if (fReparsePoints == -1) g_fReparsePoints = 1; /* * We now need to check if we opened a symbolic directory link. * (These can be enumerated, but contains only '.' and '..'.) */ FILE_ATTRIBUTE_TAG_INFORMATION TagInfo = { 0, 0 }; IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; NTSTATUS rcNt = NtQueryInformationFile(pDir->hDir, &Ios, &TagInfo, sizeof(TagInfo), FileAttributeTagInformation); AssertMsg(NT_SUCCESS(rcNt), ("%#x\n", rcNt)); if (!NT_SUCCESS(rcNt)) TagInfo.FileAttributes = TagInfo.ReparseTag = 0; if (!(TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) break; NtClose(pDir->hDir); pDir->hDir = RTNT_INVALID_HANDLE_VALUE; if (TagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK) { rc = VERR_IS_A_SYMLINK; break; } /* Reparse point that isn't a symbolic link, try follow the reparsing. */ } else if (fReparsePoints == -1) g_fReparsePoints = fReparsePoints = 0; fOptions &= ~FILE_OPEN_REPARSE_POINT; } } if (RT_SUCCESS(rc)) { /* * Init data. */ pDir->fDataUnread = false; /* spelling it out */ pDir->uDirDev = 0; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (fObjDir) pDir->enmInfoClass = FileMaximumInformation; /* object directory. */ #endif } return rc; }
int main(int argc, char **argv) { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTUuid", &hTest); if (rc) return rc; RTTestBanner(hTest); #define CHECK_RC() \ do { if (RT_FAILURE(rc)) { RTTestFailed(hTest, "line %d: rc=%Rrc", __LINE__, rc); } } while (0) RTTestSub(hTest, "RTUuidClear & RTUuisIsNull"); RTUUID UuidNull; rc = RTUuidClear(&UuidNull); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidIsNull(&UuidNull)); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &UuidNull) == 0); RTTestSub(hTest, "RTUuidCreate"); RTUUID Uuid; rc = RTUuidCreate(&Uuid); CHECK_RC(); RTTEST_CHECK(hTest, !RTUuidIsNull(&Uuid)); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid) == 0); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &UuidNull) > 0); RTTEST_CHECK(hTest, RTUuidCompare(&UuidNull, &Uuid) < 0); RTTestSub(hTest, "RTUuidToStr"); char sz[RTUUID_STR_LENGTH]; rc = RTUuidToStr(&Uuid, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strlen(sz) == RTUUID_STR_LENGTH - 1); RTTestPrintf(hTest, RTTESTLVL_INFO, "UUID=%s\n", sz); RTTestSub(hTest, "RTUuidFromStr"); RTUUID Uuid2; rc = RTUuidFromStr(&Uuid2, sz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); char *psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH - off, "%s", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTUuidClear(&Uuid2); char sz2[RTUUID_STR_LENGTH + 2]; RTStrPrintf(sz2, sizeof(sz2), "{%s}", sz); rc = RTUuidFromStr(&Uuid2, sz2); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); psz = (char *)RTTestGuardedAllocTail(hTest, RTUUID_STR_LENGTH + 2); if (psz) { RTStrPrintf(psz, RTUUID_STR_LENGTH + 2, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { char *psz2 = psz + off; RTStrPrintf(psz2, RTUUID_STR_LENGTH + 2 - off, "{%s}", sz); RTTESTI_CHECK_RC(RTUuidFromStr(&Uuid2, psz2), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, psz); } RTTestSub(hTest, "RTUuidToUtf16"); RTUTF16 wsz[RTUUID_STR_LENGTH]; rc = RTUuidToUtf16(&Uuid, wsz, sizeof(wsz)); CHECK_RC(); RTTEST_CHECK(hTest, RTUtf16Len(wsz) == RTUUID_STR_LENGTH - 1); RTTestSub(hTest, "RTUuidFromUtf16"); rc = RTUuidFromUtf16(&Uuid2, wsz); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz; rc = RTStrToUtf16(sz2, &pwsz); RTTEST_CHECK(hTest, rc == VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); RTUTF16 *pwsz2 = (RTUTF16*)RTTestGuardedAllocTail(hTest, 2 * (RTUUID_STR_LENGTH + 2)); if (pwsz2) { memcpy(pwsz2, pwsz, 2 * (RTUUID_STR_LENGTH + 2)); RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz2), VINF_SUCCESS); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid2) == 0); for (unsigned off = 1; off < RTUUID_STR_LENGTH + 2; off++) { RTUTF16 *pwsz3 = pwsz2 + off; memcpy(pwsz3, pwsz, 2 * (RTUUID_STR_LENGTH + 1 - off)); pwsz3[RTUUID_STR_LENGTH + 1 - off] = 0; RTTESTI_CHECK_RC(RTUuidFromUtf16(&Uuid2, pwsz3), VERR_INVALID_UUID_FORMAT); } RTTestGuardedFree(hTest, pwsz2); } RTUtf16Free(pwsz); } RTTestSub(hTest, "RTUuidCompareStr"); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&Uuid, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompareStr(&UuidNull, "00000000-0000-0000-0000-000000000000") == 0); RTTestSub(hTest, "RTUuidCompare2Strs"); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, sz) == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs(sz, "00000000-0000-0000-0000-000000000000") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", sz) < 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("00000000-0000-0000-0000-000000000000", "00000000-0000-0000-0000-000000000000") == 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("d95d883b-f91d-4ce5-a5c5-d08bb6a85dec", "a56193c7-3e0b-4c03-9d66-56efb45082f7") > 0); RTTEST_CHECK(hTest, RTUuidCompare2Strs("a56193c7-3e0b-4c03-9d66-56efb45082f7", "d95d883b-f91d-4ce5-a5c5-d08bb6a85dec") < 0); /* * Check the binary representation. */ RTTestSub(hTest, "Binary representation"); RTUUID Uuid3; Uuid3.au8[0] = 0x01; Uuid3.au8[1] = 0x23; Uuid3.au8[2] = 0x45; Uuid3.au8[3] = 0x67; Uuid3.au8[4] = 0x89; Uuid3.au8[5] = 0xab; Uuid3.au8[6] = 0xcd; Uuid3.au8[7] = 0x4f; Uuid3.au8[8] = 0x10; Uuid3.au8[9] = 0xb2; Uuid3.au8[10] = 0x54; Uuid3.au8[11] = 0x76; Uuid3.au8[12] = 0x98; Uuid3.au8[13] = 0xba; Uuid3.au8[14] = 0xdc; Uuid3.au8[15] = 0xfe; Uuid3.Gen.u8ClockSeqHiAndReserved = (Uuid3.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; Uuid3.Gen.u16TimeHiAndVersion = (Uuid3.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; const char *pszUuid3 = "67452301-ab89-4fcd-90b2-547698badcfe"; rc = RTUuidToStr(&Uuid3, sz, sizeof(sz)); CHECK_RC(); RTTEST_CHECK(hTest, strcmp(sz, pszUuid3) == 0); rc = RTUuidFromStr(&Uuid, pszUuid3); CHECK_RC(); RTTEST_CHECK(hTest, RTUuidCompare(&Uuid, &Uuid3) == 0); RTTEST_CHECK(hTest, memcmp(&Uuid3, &Uuid, sizeof(Uuid)) == 0); /* * checking the clock seq and time hi and version bits... */ RTTestSub(hTest, "Clock seq, time hi, version bits"); RTUUID Uuid4Changes; Uuid4Changes.au64[0] = 0; Uuid4Changes.au64[1] = 0; RTUUID Uuid4Prev; RTUuidCreate(&Uuid4Prev); for (unsigned i = 0; i < 1024; i++) { RTUUID Uuid4; RTUuidCreate(&Uuid4); Uuid4Changes.au64[0] |= Uuid4.au64[0] ^ Uuid4Prev.au64[0]; Uuid4Changes.au64[1] |= Uuid4.au64[1] ^ Uuid4Prev.au64[1]; #if 0 /** @todo make a bit string/dumper similar to %Rhxs/d. */ RTPrintf("tstUuid: %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d ; %d %d %d %d-%d %d %d %d %d %d %d %d-%d %d %d %d\n", !!(Uuid4.Gen.u16ClockSeq & RT_BIT(0)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(1)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(2)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(3)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(4)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(5)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(6)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(7)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(8)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(9)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(10)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(11)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(12)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(13)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(14)), !!(Uuid4.Gen.u16ClockSeq & RT_BIT(15)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(0)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(1)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(2)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(3)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(4)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(5)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(6)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(7)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(8)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(9)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(10)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(11)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(12)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(13)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(14)), !!(Uuid4.Gen.u16TimeHiAndVersion & RT_BIT(15)) ); #endif Uuid4Prev = Uuid4; } RTUUID Uuid4Fixed; Uuid4Fixed.au64[0] = ~Uuid4Changes.au64[0]; Uuid4Fixed.au64[1] = ~Uuid4Changes.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "fixed bits: %RTuuid (mask)\n", &Uuid4Fixed); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Fixed), &Uuid4Fixed); Uuid4Prev.au64[0] &= Uuid4Fixed.au64[0]; Uuid4Prev.au64[1] &= Uuid4Fixed.au64[1]; RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: fixed bits: %RTuuid (value)\n", &Uuid4Prev); RTTestPrintf(hTest, RTTESTLVL_INFO, "tstUuid: raw: %.*Rhxs\n", sizeof(Uuid4Prev), &Uuid4Prev); /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
/** * Retrieves the data stored in this object and store the result in * pMedium. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc * @param pMedium */ STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium) { AssertPtrReturn(pFormatEtc, DV_E_FORMATETC); AssertPtrReturn(pMedium, DV_E_FORMATETC); HRESULT hr = DV_E_FORMATETC; LPFORMATETC pThisFormat = NULL; LPSTGMEDIUM pThisMedium = NULL; /* Format supported? */ ULONG lIndex; if ( LookupFormatEtc(pFormatEtc, &lIndex) && lIndex < mcFormats) /* Paranoia. */ { pThisMedium = &mpStgMedium[lIndex]; AssertPtr(pThisMedium); pThisFormat = &mpFormatEtc[lIndex]; AssertPtr(pThisFormat); LogFlowFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat)); LogFlowFunc(("mStatus=%ld\n", mStatus)); switch (mStatus) { case Dropping: { LogRel3(("DnD: Dropping\n")); LogFlowFunc(("Waiting for event ...\n")); int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT); LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus)); } case Dropped: { LogRel3(("DnD: Dropped\n")); LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), pThisFormat->tymed, pThisFormat->dwAspect)); LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n", mstrFormat.toAscii().constData(), mpvData, mcbData)); QVariant::Type vaType; QString strMIMEType; if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && ( pFormatEtc->cfFormat == CF_TEXT || pFormatEtc->cfFormat == CF_UNICODETEXT) ) { strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */ vaType = QVariant::String; } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_HDROP)) { strMIMEType = "text/uri-list"; vaType = QVariant::StringList; } #if 0 /* More formats; not needed right now. */ else if ( (pFormatEtc->tymed & TYMED_ISTREAM) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILECONTENTS)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT)) { HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD)); DWORD *pdwEffect = (DWORD *)GlobalLock(hData); AssertPtr(pdwEffect); *pdwEffect = DROPEFFECT_COPY; GlobalUnlock(hData); pMedium->hGlobal = hData; pMedium->tymed = TYMED_HGLOBAL; } #endif LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toAscii().constData(), vaType)); int rc; if (!mVaData.isValid()) { /* Note: We're usig Qt::MoveAction because this speeds up the whole operation * significantly: Instead of copying the data from the temporary location to * the final destination we just move it. * * Note2: The Qt::MoveAction *only* affects the behavior on the host! The desired * action for the guest (e.g. moving a file from guest to host) is not affected * by this setting. */ rc = m_pDnDHandler->retrieveData(Qt::MoveAction, strMIMEType, vaType, mVaData); } else rc = VINF_SUCCESS; /* Data already retrieved. */ if (RT_SUCCESS(rc)) { if ( strMIMEType.startsWith("text/uri-list") /* One item. */ && ( mVaData.canConvert(QVariant::String) /* Multiple items. */ || mVaData.canConvert(QVariant::StringList)) ) { QStringList lstFilesURI = mVaData.toStringList(); QStringList lstFiles; for (size_t i = 0; i < lstFilesURI.size(); i++) { /* Extract path from URI. */ char *pszPath = RTUriPath(lstFilesURI.at(i).toAscii().constData()); if ( pszPath && strlen(pszPath) > 1) { pszPath++; /** @todo Skip first '/' (part of URI). Correct? */ pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */); lstFiles.append(pszPath); } } size_t cFiles = lstFiles.size(); Assert(cFiles); #ifdef DEBUG LogFlowFunc(("Files (%zu)\n", cFiles)); for (size_t i = 0; i < cFiles; i++) LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).toAscii().constData())); #endif size_t cchFiles = 0; /* Number of ASCII characters. */ for (size_t i = 0; i < cFiles; i++) { cchFiles += strlen(lstFiles.at(i).toAscii().constData()); cchFiles += 1; /* Terminating '\0'. */ } size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16)); DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf); if (pDropFiles) { pDropFiles->pFiles = sizeof(DROPFILES); pDropFiles->fWide = 1; /* We use unicode. Always. */ uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles; AssertPtr(pCurFile); for (size_t i = 0; i < cFiles; i++) { size_t cchCurFile; PRTUTF16 pwszFile; rc = RTStrToUtf16(lstFiles.at(i).toAscii().constData(), &pwszFile); if (RT_SUCCESS(rc)) { cchCurFile = RTUtf16Len(pwszFile); Assert(cchCurFile); memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16)); RTUtf16Free(pwszFile); } else break; pCurFile += cchCurFile * sizeof(RTUTF16); /* Terminate current file name. */ *pCurFile = L'\0'; pCurFile += sizeof(RTUTF16); } if (RT_SUCCESS(rc)) { *pCurFile = L'\0'; /* Final list terminator. */ pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbBuf); if (pMedium->hGlobal) { LPVOID pvMem = GlobalLock(pMedium->hGlobal); if (pvMem) { memcpy(pvMem, pDropFiles, cbBuf); GlobalUnlock(pMedium->hGlobal); hr = S_OK; } else rc = VERR_ACCESS_DENIED; } else rc = VERR_NO_MEMORY; } RTMemFree(pDropFiles); } } else if ( strMIMEType.startsWith("text/plain") && mVaData.canConvert(QVariant::String)) { bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT; int cbCh = fUnicode ? sizeof(WCHAR) : sizeof(char); QString strText = mVaData.toString(); size_t cbSrc = strText.length() * cbCh; Assert(cbSrc); LPCVOID pvSrc = fUnicode ? (void *)strText.unicode() : (void *)strText.toAscii().constData(); AssertPtr(pvSrc); LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbch=%d, fUnicode=%RTbool\n", pvSrc, cbSrc, cbCh, fUnicode)); pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbSrc); if (pMedium->hGlobal) { LPVOID pvDst = GlobalLock(pMedium->hGlobal); if (pvDst) { memcpy(pvDst, pvSrc, cbSrc); GlobalUnlock(pMedium->hGlobal); } else rc = VERR_ACCESS_DENIED; hr = S_OK; } else hr = VERR_NO_MEMORY; } else LogFlowFunc(("MIME type=%s not supported\n", strMIMEType.toAscii().constData())); LogFlowFunc(("Handling formats ended with rc=%Rrc\n", rc)); } } default: break; } } /* * Fallback in error case. */ if (FAILED(hr)) { if (pThisMedium) { switch (pThisMedium->tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, 0 /* Flags */); break; default: break; } } if (pFormatEtc) pMedium->tymed = pFormatEtc->tymed; pMedium->pUnkForRelease = NULL; } LogFlowFunc(("Returning hr=%Rhrc\n", hr)); return hr; }
/** * Retrieves the data stored in this object and store the result in * pMedium. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc * @param pMedium */ STDMETHODIMP VBoxDnDDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { AssertPtrReturn(pFormatEtc, DV_E_FORMATETC); AssertPtrReturn(pMedium, DV_E_FORMATETC); ULONG lIndex; if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */ return DV_E_FORMATETC; if (lIndex >= mcFormats) /* Paranoia. */ return DV_E_FORMATETC; LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium)); FORMATETC *pThisFormat = &mpFormatEtc[lIndex]; AssertPtr(pThisFormat); STGMEDIUM *pThisMedium = &mpStgMedium[lIndex]; AssertPtr(pThisMedium); HRESULT hr = DV_E_FORMATETC; LogFlowFunc(("mStatus=%ld\n", mStatus)); if (mStatus == Dropping) { LogFlowFunc(("Waiting for event ...\n")); int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT); LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus)); } if (mStatus == Dropped) { LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", pThisFormat->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), pThisFormat->tymed, pThisFormat->dwAspect)); LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n", mstrFormat.c_str(), mpvData, mcbData)); if (mstrFormat.equalsIgnoreCase("text/uri-list")) { RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n"); RTCList<RTCString> lstFiles; for (size_t i = 0; i < lstFilesURI.size(); i++) { /* Extract path from URI. */ char *pszPath = RTUriPath(lstFilesURI.at(i).c_str()); if ( pszPath && strlen(pszPath) > 1) { pszPath++; /** @todo Skip first '/' (part of URI). Correct? */ pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */); lstFiles.append(pszPath); } } #ifdef DEBUG LogFlowFunc(("Files (%zu)\n", lstFiles.size())); for (size_t i = 0; i < lstFiles.size(); i++) LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str())); #endif #if 0 if ( (pFormatEtc->tymed & TYMED_ISTREAM) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILECONTENTS)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR)) { } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT)) { HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD)); DWORD *pdwEffect = (DWORD *)GlobalLock(hData); AssertPtr(pdwEffect); *pdwEffect = DROPEFFECT_COPY; GlobalUnlock(hData); pMedium->hGlobal = hData; pMedium->tymed = TYMED_HGLOBAL; } else #endif if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_TEXT)) { pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1); if (pMedium->hGlobal) { /** @todo Not working yet -- needs URI to plain ASCII conversion. */ char *pcDst = (char *)GlobalLock(pMedium->hGlobal); memcpy(pcDst, mpvData, mcbData); pcDst[mcbData] = '\0'; GlobalUnlock(pMedium->hGlobal); hr = S_OK; } } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_HDROP)) { int rc = VINF_SUCCESS; size_t cchFiles = 0; /* Number of ASCII characters. */ for (size_t i = 0; i < lstFiles.size(); i++) { cchFiles += strlen(lstFiles.at(i).c_str()); cchFiles += 1; /* Terminating '\0'. */ } size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16)); DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf); if (pBuf) { pBuf->pFiles = sizeof(DROPFILES); pBuf->fWide = 1; /* We use unicode. Always. */ uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles; AssertPtr(pCurFile); for (size_t i = 0; i < lstFiles.size() && RT_SUCCESS(rc); i++) { size_t cchCurFile; PRTUTF16 pwszFile; rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile); if (RT_SUCCESS(rc)) { cchCurFile = RTUtf16Len(pwszFile); Assert(cchCurFile); memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16)); RTUtf16Free(pwszFile); } else break; pCurFile += cchCurFile * sizeof(RTUTF16); /* Terminate current file name. */ *pCurFile = L'\0'; pCurFile += sizeof(RTUTF16); } if (RT_SUCCESS(rc)) { *pCurFile = L'\0'; /* Final list terminator. */ pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbBuf); if (pMedium->hGlobal) { LPVOID pMem = GlobalLock(pMedium->hGlobal); if (pMem) { memcpy(pMem, pBuf, cbBuf); GlobalUnlock(pMedium->hGlobal); hr = S_OK; } } } RTMemFree(pBuf); } else rc = VERR_NO_MEMORY; if (RT_FAILURE(rc)) hr = DV_E_FORMATETC; } } } if (FAILED(hr)) { LogFlowFunc(("Copying medium ...\n")); switch (pThisMedium->tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, NULL); break; default: break; } pMedium->tymed = pThisFormat->tymed; pMedium->pUnkForRelease = NULL; } LogFlowFunc(("hr=%Rhrc\n", hr)); return hr; }
RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags) { AssertPtrReturn(pwszzBlock, VERR_INVALID_POINTER); AssertReturn(!fFlags, VERR_INVALID_FLAGS); /* * Count the number of variables in the block. */ uint32_t cVars = 0; PCRTUTF16 pwsz = pwszzBlock; while (*pwsz != '\0') { cVars++; pwsz += RTUtf16Len(pwsz) + 1; AssertReturn(cVars < _256K, VERR_OUT_OF_RANGE); } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; size_t iDst = 0; for (pwsz = pwszzBlock; *pwsz != '\0'; pwsz += RTUtf16Len(pwsz) + 1) { int rc2 = RTUtf16ToUtf8(pwsz, &pIntEnv->papszEnv[iDst]); if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ const char *pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); if (!pszEqual) { rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "="); if (RT_SUCCESS(rc2)) pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); } if (pszEqual) { /* Check for duplicates, keep the last version. */ const char *pchVar = pIntEnv->papszEnv[iDst]; size_t cchVarNmAndEq = pszEqual - pchVar; for (size_t iDst2 = 0; iDst2 < iDst; iDst2++) if (pIntEnv->pfnCompare(pIntEnv->papszEnv[iDst2], pchVar, cchVarNmAndEq) == 0) { RTStrFree(pIntEnv->papszEnv[iDst2]); pIntEnv->papszEnv[iDst2] = pIntEnv->papszEnv[iDst]; pIntEnv->papszEnv[iDst] = NULL; iDst--; break; } iDst++; continue; } iDst++; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } Assert(iDst <= pIntEnv->cVars); pIntEnv->cVars = iDst; /* done */ *phEnv = pIntEnv; } return rc; }
/** * Returns the string length in OLECHARs without the terminator * @returns unsigned int length in OLECHARs * @param bstr source string */ unsigned int SysStringLen(BSTR bstr) { return RTUtf16Len(bstr); }
/** * Handles the getregisters sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * We take a list of register names (case insensitive). If 'all' is * encountered we'll dump all registers. */ ULONG idCpu = 0; unsigned cRegisters = 0; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'c': idCpu = ValueUnion.u32; break; case VINF_GETOPT_NOT_OPTION: if (!RTStrICmp(ValueUnion.psz, "all")) { com::SafeArray<BSTR> aBstrNames; com::SafeArray<BSTR> aBstrValues; CHECK_ERROR2I_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), ComSafeArrayAsOutParam(aBstrValues)), RTEXITCODE_FAILURE); Assert(aBstrNames.size() == aBstrValues.size()); size_t cchMaxName = 8; for (size_t i = 0; i < aBstrNames.size(); i++) { size_t cchName = RTUtf16Len(aBstrNames[i]); if (cchName > cchMaxName) cchMaxName = cchName; } for (size_t i = 0; i < aBstrNames.size(); i++) RTPrintf("%-*ls = %ls\n", cchMaxName, aBstrNames[i], aBstrValues[i]); } else { com::Bstr bstrName = ValueUnion.psz; com::Bstr bstrValue; CHECK_ERROR2I_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE); RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw()); } cRegisters++; break; default: return errorGetOpt(rc, &ValueUnion); } } if (!cRegisters) return errorSyntax("The getregisters sub-command takes at least one register name"); return RTEXITCODE_SUCCESS; }
RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate) { /* * Validate the input. */ AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER); AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER); AssertPtrReturn(pszTarget, VERR_INVALID_POINTER); /* * Resolve the API. */ typedef BOOLEAN (WINAPI *PFNCREATESYMBOLICLINKW)(LPCWSTR, LPCWSTR, DWORD); static PFNCREATESYMBOLICLINKW s_pfnCreateSymbolicLinkW = NULL; static bool s_fTried = FALSE; if (!s_fTried) { HMODULE hmod = LoadLibrary("KERNEL32.DLL"); if (hmod) { PFNCREATESYMBOLICLINKW pfn = (PFNCREATESYMBOLICLINKW)GetProcAddress(hmod, "CreateSymbolicLinkW"); if (pfn) s_pfnCreateSymbolicLinkW = pfn; } s_fTried = true; } if (!s_pfnCreateSymbolicLinkW) { LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns VERR_NOT_SUPPORTED - Windows API not found\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate)); return VERR_NOT_SUPPORTED; } /* * Convert the paths. */ PRTUTF16 pwszNativeSymlink; int rc = RTStrToUtf16(pszSymlink, &pwszNativeSymlink); if (RT_SUCCESS(rc)) { PRTUTF16 pwszNativeTarget; rc = RTStrToUtf16(pszTarget, &pwszNativeTarget); if (RT_SUCCESS(rc)) { /* * Massage the target path, determin the link type. */ size_t cchTarget = strlen(pszTarget); size_t cchVolSpecTarget = rtPathVolumeSpecLen(pszTarget); #if 0 /* looks like this isn't needed after all. That makes everything much simper :-) */ if ( cchTarget > RT_MIN(cchVolSpecTarget, 1) && RTPATH_IS_SLASH(pszTarget[cchTarget - 1])) { size_t cwcNativeTarget = RTUtf16Len(pwszNativeTarget); size_t offFromEnd = 1; while ( offFromEnd < cchTarget && cchTarget - offFromEnd >= cchVolSpecTarget && RTPATH_IS_SLASH(pszTarget[cchTarget - offFromEnd])) { Assert(offFromEnd < cwcNativeTarget); pwszNativeTarget[cwcNativeTarget - offFromEnd] = 0; offFromEnd++; } } #endif if (enmType == RTSYMLINKTYPE_UNKNOWN) { if ( cchTarget > cchVolSpecTarget && RTPATH_IS_SLASH(pszTarget[cchTarget - 1])) enmType = RTSYMLINKTYPE_DIR; else if (cchVolSpecTarget) { /** @todo this is subject to sharing violations. */ DWORD dwAttr = GetFileAttributesW(pwszNativeTarget); if ( dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) enmType = RTSYMLINKTYPE_DIR; } else { /** @todo Join the symlink directory with the target and * look up the attributes on that. -lazy bird. */ } } /* * Create the link. */ if (s_pfnCreateSymbolicLinkW(pwszNativeSymlink, pwszNativeTarget, enmType == RTSYMLINKTYPE_DIR)) rc = VINF_SUCCESS; else rc = RTErrConvertFromWin32(GetLastError()); RTUtf16Free(pwszNativeTarget); } RTUtf16Free(pwszNativeSymlink); } LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate, rc)); return rc; }