/** * Connects to VBoxTray IPC under the behalf of the user running * in the current thread context. * * @return IPRT status code. * @param phSession Where to store the IPC session. */ static int vboxConnectToVBoxTray(RTLOCALIPCSESSION *phSession) { int rc = VINF_SUCCESS; RTUTF16 wszUserName[255]; DWORD cchUserName = sizeof(wszUserName) / sizeof(RTUTF16); BOOL fRc = GetUserNameW(wszUserName, &cchUserName); if (!fRc) rc = RTErrConvertFromWin32(GetLastError()); if (RT_SUCCESS(rc)) { char *pszUserName; rc = RTUtf16ToUtf8(wszUserName, &pszUserName); if (RT_SUCCESS(rc)) { char szPipeName[255]; if (RTStrPrintf(szPipeName, sizeof(szPipeName), "%s%s", VBOXTRAY_IPC_PIPE_PREFIX, pszUserName)) { rc = RTLocalIpcSessionConnect(phSession, szPipeName, 0 /* Flags */); } else rc = VERR_NO_MEMORY; RTStrFree(pszUserName); } } return rc; }
static void tstCheckNativeMsCrtToArgv(const char *pszCmdLine, int cExpectedArgs, const char * const *papszExpectedArgs) { #ifdef RT_OS_WINDOWS /* * Resolve APIs. */ static void *(__stdcall * s_pfnLocalFree)(void *pvFree); static PRTUTF16 *(__stdcall * s_pfnCommandLineToArgvW)(PCRTUTF16 pwszCmdLine, int *pcArgs); if (!s_pfnCommandLineToArgvW) { *(void **)&s_pfnLocalFree = RTLdrGetSystemSymbol("kernel32.dll", "LocalFree"); RTTESTI_CHECK_RETV(s_pfnLocalFree != NULL); *(void **)&s_pfnCommandLineToArgvW = RTLdrGetSystemSymbol("shell32.dll", "CommandLineToArgvW"); RTTESTI_CHECK_RETV(s_pfnCommandLineToArgvW != NULL); } /* * Calc expected arguments if needed. */ if (cExpectedArgs == -1) for (cExpectedArgs = 0; papszExpectedArgs[cExpectedArgs]; cExpectedArgs++) { /* nothing */ } /* * Convert input command line to UTF-16 and call native API. */ RTUTF16 wszCmdLine[1024]; PRTUTF16 pwszCmdLine = &wszCmdLine[1]; RTTESTI_CHECK_RC_RETV(RTStrToUtf16Ex(pszCmdLine, RTSTR_MAX, &pwszCmdLine, 1023, NULL), VINF_SUCCESS); wszCmdLine[0] = ' '; int cArgs = -2; PRTUTF16 *papwszArgs = s_pfnCommandLineToArgvW(wszCmdLine, &cArgs); /* * Check the result. */ if (cArgs - 1 != cExpectedArgs) RTTestIFailed("Native returns cArgs=%d, expected %d (cmdline=|%s|)", cArgs - 1, cExpectedArgs, pszCmdLine); int cArgsCheck = RT_MIN(cArgs - 1, cExpectedArgs); for (int i = 0; i < cArgsCheck; i++) { char *pszArg = NULL; RTTESTI_CHECK_RC_RETV(RTUtf16ToUtf8(papwszArgs[i + 1], &pszArg), VINF_SUCCESS); if (strcmp(pszArg, papszExpectedArgs[i])) RTTestIFailed("Native returns argv[%i]='%s', expected '%s' (cmdline=|%s|)", i, pszArg, papszExpectedArgs[i], pszCmdLine); RTStrFree(pszArg); } if (papwszArgs) s_pfnLocalFree(papwszArgs); #else NOREF(pszCmdLine); NOREF(cExpectedArgs); NOREF(papszExpectedArgs); #endif }
/** * Paste text data into guest clipboard. * * @param pPasteboard Guest PasteBoard reference. * @param pData Data to be pasted. * @param cbDataSize Size of *pData. */ static int vbclClipboardGuestPasteText(PasteboardRef pPasteboard, void *pData, uint32_t cbDataSize) { size_t cbActualLen; int rc; char *pszUtf8Buf; RTUTF16 *pDataInternal; AssertReturn(pData, VERR_INVALID_PARAMETER); /* Skip zero-sized buffer */ AssertReturn(cbDataSize > 0, VINF_SUCCESS); /* If buffer content is Unicode text, then deliver it in both formats UTF16 (original) and UTF8. */ /* Convert END-OF-LINE */ rc = vboxClipboardUtf16GetLinSize((RTUTF16 *)pData, cbDataSize / 2, &cbActualLen); AssertReturn(RT_SUCCESS(rc), rc); pDataInternal = (RTUTF16 *)RTMemAlloc(cbActualLen * 2); AssertReturn(pDataInternal, VERR_NO_MEMORY); rc = vboxClipboardUtf16WinToLin((RTUTF16 *)pData, cbDataSize / 2, pDataInternal, cbActualLen); /* Do actual paste */ if (RT_SUCCESS(rc)) { /* Paste UTF16 */ rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pDataInternal, cbActualLen * 2, kUTTypeUTF16PlainText, true); if (RT_SUCCESS(rc)) { /* Paste UTF8 */ rc = RTUtf16ToUtf8((RTUTF16 *)pDataInternal, &pszUtf8Buf); if (RT_SUCCESS(rc)) { rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pszUtf8Buf, strlen(pszUtf8Buf), kUTTypeUTF8PlainText, false); RTStrFree(pszUtf8Buf); } } } RTMemFree(pDataInternal); return rc; }
/** * Get the real name of a shared folder. * * @returns VBox status code. * @param u32ClientId The client id returned by VbglR3InvsSvcConnect(). * @param u32Root Root ID of shared folder to get the name for. * @param ppszName Where to return the name string. This shall be * freed by calling RTStrFree. */ VBGLR3DECL(int) VbglR3SharedFolderGetName(uint32_t u32ClientId, uint32_t u32Root, char **ppszName) { AssertPtr(ppszName); VBoxSFQueryMapName Msg; Msg.callInfo.result = VERR_WRONG_ORDER; Msg.callInfo.u32ClientID = u32ClientId; Msg.callInfo.u32Function = SHFL_FN_QUERY_MAP_NAME; Msg.callInfo.cParms = 2; int rc; uint32_t cbString = SHFLSTRING_HEADER_SIZE + SHFL_MAX_LEN; PSHFLSTRING pString = (PSHFLSTRING)RTMemAlloc(cbString); if (pString) { if (!ShflStringInitBuffer(pString, cbString)) { RTMemFree(pString); return VERR_INVALID_PARAMETER; } VbglHGCMParmUInt32Set(&Msg.root, u32Root); VbglHGCMParmPtrSet(&Msg.name, pString, cbString); rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); if (RT_SUCCESS(rc)) { rc = Msg.callInfo.result; if (RT_SUCCESS(rc)) { *ppszName = NULL; rc = RTUtf16ToUtf8(&pString->String.ucs2[0], ppszName); } } RTMemFree(pString); } else rc = VERR_INVALID_PARAMETER; return rc; }
STDMETHODIMP VBoxDnDDropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { RT_NOREF(pt); AssertPtrReturn(pDataObject, E_INVALIDARG); AssertPtrReturn(pdwEffect, E_INVALIDARG); LogFlowFunc(("mFormatEtc.cfFormat=%RI16 (%s), pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), pDataObject, grfKeyState, pt.x, pt.y)); HRESULT hr = S_OK; if (mFormatEtc.cfFormat) /* Did we get a supported format yet? */ { /* Make sure the data object's data format is still valid. */ hr = pDataObject->QueryGetData(&mFormatEtc); AssertMsg(SUCCEEDED(hr), ("Data format changed to invalid between DragEnter() and Drop(), cfFormat=%RI16 (%s), hr=%Rhrc\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), hr)); } int rc = VINF_SUCCESS; if (SUCCEEDED(hr)) { STGMEDIUM stgMed; hr = pDataObject->GetData(&mFormatEtc, &stgMed); if (SUCCEEDED(hr)) { /* * First stage: Prepare the access to the storage medium. * For now we only support HGLOBAL stuff. */ PVOID pvData = NULL; /** @todo Put this in an own union? */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: pvData = GlobalLock(stgMed.hGlobal); if (!pvData) { LogFlowFunc(("Locking HGLOBAL storage failed with %Rrc\n", RTErrConvertFromWin32(GetLastError()))); rc = VERR_INVALID_HANDLE; hr = E_INVALIDARG; /* Set special hr for OLE. */ } break; default: AssertMsgFailed(("Storage medium type %RI32 supported\n", mFormatEtc.tymed)); rc = VERR_NOT_SUPPORTED; hr = DV_E_TYMED; /* Set special hr for OLE. */ break; } if (RT_SUCCESS(rc)) { /* * Second stage: Do the actual copying of the data object's data, * based on the storage medium type. */ switch (mFormatEtc.cfFormat) { case CF_TEXT: /* Fall through is intentional. */ case CF_UNICODETEXT: { AssertPtr(pvData); size_t cbSize = GlobalSize(pvData); LogFlowFunc(("CF_TEXT/CF_UNICODETEXT 0x%p got %zu bytes\n", pvData, cbSize)); if (cbSize) { char *pszText = NULL; rc = mFormatEtc.cfFormat == CF_TEXT /* ANSI codepage -> UTF-8 */ ? RTStrCurrentCPToUtf8(&pszText, (char *)pvData) /* Unicode -> UTF-8 */ : RTUtf16ToUtf8((PCRTUTF16)pvData, &pszText); if (RT_SUCCESS(rc)) { AssertPtr(pszText); size_t cbText = strlen(pszText) + 1; /* Include termination. */ mpvData = RTMemDup((void *)pszText, cbText); mcbData = cbText; RTStrFree(pszText); pszText = NULL; } } break; } case CF_HDROP: { AssertPtr(pvData); /* Convert to a string list, separated by \r\n. */ DROPFILES *pDropFiles = (DROPFILES *)pvData; AssertPtr(pDropFiles); bool fUnicode = RT_BOOL(pDropFiles->fWide); /* Get the offset of the file list. */ Assert(pDropFiles->pFiles >= sizeof(DROPFILES)); /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only * will work with the plain storage medium pointer! */ HDROP hDrop = (HDROP)(pvData); /* First, get the file count. */ /** @todo Does this work on Windows 2000 / NT4? */ char *pszFiles = NULL; uint32_t cchFiles = 0; UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */); LogFlowFunc(("CF_HDROP got %RU16 file(s)\n", cFiles)); for (UINT i = 0; i < cFiles; i++) { UINT cch = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */); Assert(cch); if (RT_FAILURE(rc)) break; char *pszFile = NULL; /* UTF-8 version. */ UINT cchFile = 0; if (fUnicode) { /* Allocate enough space (including terminator). */ WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cch + 1) * sizeof(WCHAR)); if (pwszFile) { cchFile = DragQueryFileW(hDrop, i /* File index */, pwszFile, cch + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); rc = RTUtf16ToUtf8(pwszFile, &pszFile); AssertRC(rc); RTMemFree(pwszFile); } else rc = VERR_NO_MEMORY; } else /* ANSI */ { /* Allocate enough space (including terminator). */ pszFile = (char *)RTMemAlloc((cch + 1) * sizeof(char)); if (pszFile) { cchFile = DragQueryFileA(hDrop, i /* File index */, pszFile, cchFile + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); } else rc = VERR_NO_MEMORY; } if (RT_SUCCESS(rc)) { LogFlowFunc(("\tFile: %s (cchFile=%RU32)\n", pszFile, cchFile)); rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFile, cchFile); if (RT_SUCCESS(rc)) cchFiles += cchFile; } if (pszFile) RTStrFree(pszFile); if (RT_FAILURE(rc)) break; /* Add separation between filenames. * Note: Also do this for the last element of the list. */ rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */); if (RT_SUCCESS(rc)) cchFiles += 2; /* Include \r\n */ } if (RT_SUCCESS(rc)) { cchFiles += 1; /* Add string termination. */ uint32_t cbFiles = cchFiles * sizeof(char); LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n", cFiles, cchFiles, cbFiles, pszFiles)); /* Translate the list into URI elements. */ DnDURIList lstURI; rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles, DNDURILIST_FLAGS_ABSOLUTE_PATHS); if (RT_SUCCESS(rc)) { RTCString strRoot = lstURI.RootToString(); size_t cbRoot = strRoot.length() + 1; /* Include termination */ mpvData = RTMemAlloc(cbRoot); if (mpvData) { memcpy(mpvData, strRoot.c_str(), cbRoot); mcbData = cbRoot; } else rc = VERR_NO_MEMORY; } } LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n", rc, pszFiles, cFiles, cchFiles)); if (pszFiles) RTStrFree(pszFiles); break; } default: /* Note: Should not happen due to the checks done in DragEnter(). */ AssertMsgFailed(("Format of type %RI16 (%s) not supported\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat))); hr = DV_E_CLIPFORMAT; /* Set special hr for OLE. */ break; } /* * Third stage: Unlock + release access to the storage medium again. */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: GlobalUnlock(stgMed.hGlobal); break; default: AssertMsgFailed(("Really should not happen -- see init stage!\n")); break; } } /* Release storage medium again. */ ReleaseStgMedium(&stgMed); /* Signal waiters. */ mDroppedRc = rc; RTSemEventSignal(hEventDrop); } } if (RT_SUCCESS(rc)) { /* Note: pt is not used since we don't need to differentiate within our * proxy window. */ *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect); } else *pdwEffect = DROPEFFECT_NONE; if (mpWndParent) mpWndParent->hide(); LogFlowFunc(("Returning with hr=%Rhrc (%Rrc), mFormatEtc.cfFormat=%RI16 (%s), *pdwEffect=%RI32\n", hr, rc, mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), *pdwEffect)); return hr; }
RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags) { /** @todo Symlinks: Find[First|Next]FileW will return info about the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */ /* * Validate input. */ if (!pDir || pDir->u32Magic != RTDIR_MAGIC) { AssertMsgFailed(("Invalid pDir=%p\n", pDir)); return VERR_INVALID_PARAMETER; } if (!pDirEntry) { AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); return VERR_INVALID_PARAMETER; } if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING || enmAdditionalAttribs > RTFSOBJATTRADD_LAST) { AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs)); return VERR_INVALID_PARAMETER; } AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2])) { AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2]))); return VERR_INVALID_PARAMETER; } } /* * Fetch data? */ if (!pDir->fDataUnread) { RTStrFree(pDir->pszName); pDir->pszName = NULL; BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); if (!fRc) { int iErr = GetLastError(); if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) return VERR_NO_MORE_FILES; return RTErrConvertFromWin32(iErr); } } /* * Convert the filename to UTF-8. */ if (!pDir->pszName) { int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); if (RT_FAILURE(rc)) { pDir->pszName = NULL; return rc; } pDir->cchName = strlen(pDir->pszName); } /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ pDir->fDataUnread = false; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); if (pDir->Data.cAlternateFileName[0]) { /* copy and calc length */ PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName; PRTUTF16 pwszDst = pDirEntry->wszShortName; uint32_t off = 0; while (off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U && pwszSrc[off]) { pwszDst[off] = pwszSrc[off]; off++; } pDirEntry->cwcShortName = (uint16_t)off; /* zero the rest */ do pwszDst[off++] = '\0'; while (off < RT_ELEMENTS(pDirEntry->wszShortName)); } else { memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName)); pDirEntry->cwcShortName = 0; } pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32) | (uint64_t)pDir->Data.nFileSizeLow; pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject; Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime)); RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime); RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime); RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime); pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime; pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszName, cchName); /* * Requested attributes (we cannot provide anything actually). */ switch (enmAdditionalAttribs) { case RTFSOBJATTRADD_EASIZE: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; pDirEntry->Info.Attr.u.EASize.cb = 0; break; case RTFSOBJATTRADD_UNIX: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX; pDirEntry->Info.Attr.u.Unix.uid = ~0U; pDirEntry->Info.Attr.u.Unix.gid = ~0U; pDirEntry->Info.Attr.u.Unix.cHardlinks = 1; pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */ pDirEntry->Info.Attr.u.Unix.fFlags = 0; pDirEntry->Info.Attr.u.Unix.GenerationId = 0; pDirEntry->Info.Attr.u.Unix.Device = 0; break; case RTFSOBJATTRADD_NOTHING: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING; break; case RTFSOBJATTRADD_UNIX_OWNER: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U; pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */ break; case RTFSOBJATTRADD_UNIX_GROUP: pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U; pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0'; break; default: AssertMsgFailed(("Impossible!\n")); return VERR_INTERNAL_ERROR; } return VINF_SUCCESS; }
RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry) { /* * Validate input. */ if (!pDir || pDir->u32Magic != RTDIR_MAGIC) { AssertMsgFailed(("Invalid pDir=%p\n", pDir)); return VERR_INVALID_PARAMETER; } if (!pDirEntry) { AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry)); return VERR_INVALID_PARAMETER; } size_t cbDirEntry = sizeof(*pDirEntry); if (pcbDirEntry) { cbDirEntry = *pcbDirEntry; if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2])) { AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2]))); return VERR_INVALID_PARAMETER; } } /* * Fetch data? */ if (!pDir->fDataUnread) { RTStrFree(pDir->pszName); pDir->pszName = NULL; BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data); if (!fRc) { int iErr = GetLastError(); if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES) return VERR_NO_MORE_FILES; return RTErrConvertFromWin32(iErr); } } /* * Convert the filename to UTF-8. */ if (!pDir->pszName) { int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName); if (RT_FAILURE(rc)) { pDir->pszName = NULL; return rc; } pDir->cchName = strlen(pDir->pszName); } /* * Check if we've got enough space to return the data. */ const char *pszName = pDir->pszName; const size_t cchName = pDir->cchName; const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName; if (pcbDirEntry) *pcbDirEntry = cbRequired; if (cbRequired > cbDirEntry) return VERR_BUFFER_OVERFLOW; /* * Setup the returned data. */ pDir->fDataUnread = false; pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */ pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE; pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName); memcpy(pDirEntry->szName, pszName, cchName + 1); return VINF_SUCCESS; }
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); } }
RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone) { /* * Validate input and figure out how many variable to clone and where to get them. */ bool fCaseSensitive = true; bool fPutEnvBlock = false; size_t cVars; const char * const *papszEnv; #ifdef RTENV_HAVE_WENVIRON PCRTUTF16 const * papwszEnv; #endif PRTENVINTERNAL pIntEnvToClone; AssertPtrReturn(pEnv, VERR_INVALID_POINTER); if (EnvToClone == RTENV_DEFAULT) { cVars = 0; pIntEnvToClone = NULL; #ifdef RTENV_HAVE_WENVIRON papszEnv = NULL; papwszEnv = (PCRTUTF16 * const)_wenviron; if (!papwszEnv) { _wgetenv(L"Path"); /* Force the CRT to initalize it. */ papwszEnv = (PCRTUTF16 * const)_wenviron; } if (papwszEnv) while (papwszEnv[cVars]) cVars++; #else papszEnv = rtEnvDefault(); if (papszEnv) while (papszEnv[cVars]) cVars++; #endif #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) /* DOS systems was case insensitive. A prime example is the 'Path' variable on windows which turns into the 'PATH' variable. */ fCaseSensitive = false; #endif } else { pIntEnvToClone = EnvToClone; AssertPtrReturn(pIntEnvToClone, VERR_INVALID_HANDLE); AssertReturn(pIntEnvToClone->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnvToClone); fPutEnvBlock = pIntEnvToClone->fPutEnvBlock; papszEnv = pIntEnvToClone->papszEnv; cVars = pIntEnvToClone->cVars; } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, fPutEnvBlock); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; if (EnvToClone == RTENV_DEFAULT) { /* ASSUMES the default environment is in the current codepage. */ size_t iDst = 0; for (size_t iSrc = 0; iSrc < cVars; iSrc++) { #ifdef RTENV_HAVE_WENVIRON int rc2 = RTUtf16ToUtf8(papwszEnv[iSrc], &pIntEnv->papszEnv[iDst]); #else int rc2 = RTStrCurrentCPToUtf8(&pIntEnv->papszEnv[iDst], papszEnv[iSrc]); #endif if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ iDst++; if (strchr(pIntEnv->papszEnv[iDst - 1], '=')) continue; rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "="); if (RT_SUCCESS(rc2)) continue; } else if (rc2 == VERR_NO_TRANSLATION) { rc = VWRN_ENV_NOT_FULLY_TRANSLATED; continue; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } pIntEnv->cVars = iDst; } else { for (size_t iVar = 0; iVar < cVars; iVar++) { char *pszVar = RTStrDup(papszEnv[iVar]); if (RT_UNLIKELY(!pszVar)) { RTENV_UNLOCK(pIntEnvToClone); pIntEnv->cVars = iVar; RTEnvDestroy(pIntEnv); return VERR_NO_STR_MEMORY; } pIntEnv->papszEnv[iVar] = pszVar; } } /* done */ *pEnv = pIntEnv; } if (pIntEnvToClone) RTENV_UNLOCK(pIntEnvToClone); return rc; }
/** * Retrieves the currently logged in users and stores their names along with the * user count. * * @returns VBox status code. * @param ppszUserList Where to store the user list (separated by commas). * Must be freed with RTStrFree(). * @param pcUsersInList Where to store the number of users in the list. */ int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList) { PLUID paSessions = NULL; ULONG cSessions = 0; /* This function can report stale or orphaned interactive logon sessions of already logged off users (especially in Windows 2000). */ NTSTATUS rcNt = LsaEnumerateLogonSessions(&cSessions, &paSessions); if (rcNt != STATUS_SUCCESS) { ULONG ulError = LsaNtStatusToWinError(rcNt); switch (ulError) { case ERROR_NOT_ENOUGH_MEMORY: VBoxServiceError("Not enough memory to enumerate logon sessions!\n"); break; case ERROR_SHUTDOWN_IN_PROGRESS: /* If we're about to shutdown when we were in the middle of enumerating the logon * sessions, skip the error to not confuse the user with an unnecessary log message. */ VBoxServiceVerbose(3, "Shutdown in progress ...\n"); ulError = ERROR_SUCCESS; break; default: VBoxServiceError("LsaEnumerate failed with error %u\n", ulError); break; } return RTErrConvertFromWin32(ulError); } VBoxServiceVerbose(3, "Found %ld sessions\n", cSessions); PVBOXSERVICEVMINFOPROC paProcs; DWORD cProcs; int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MEMORY) VBoxServiceError("Not enough memory to enumerate processes\n"); else VBoxServiceError("Failed to enumerate processes, rc=%Rrc\n", rc); } else { PVBOXSERVICEVMINFOUSER pUserInfo; pUserInfo = (PVBOXSERVICEVMINFOUSER)RTMemAllocZ(cSessions * sizeof(VBOXSERVICEVMINFOUSER) + 1); if (!pUserInfo) VBoxServiceError("Not enough memory to store enumerated users!\n"); else { ULONG cUniqueUsers = 0; for (ULONG i = 0; i < cSessions; i++) { VBoxServiceVerbose(3, "Handling session %u\n", i); VBOXSERVICEVMINFOUSER UserInfo; if (VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])) { VBoxServiceVerbose(4, "Handling user=%ls, domain=%ls, package=%ls\n", UserInfo.wszUser, UserInfo.wszLogonDomain, UserInfo.wszAuthenticationPackage); /* Retrieve assigned processes of current session. */ ULONG ulSession; uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs, &ulSession); /* Don't return here when current session does not have assigned processes * anymore -- in that case we have to search through the unique users list below * and see if got a stale user/session entry. */ bool fFoundUser = false; for (ULONG i = 0; i < cUniqueUsers; i++) { if ( !wcscmp(UserInfo.wszUser, pUserInfo[i].wszUser) && !wcscmp(UserInfo.wszLogonDomain, pUserInfo[i].wszLogonDomain) && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage) && cSessionProcs) { /* * Only respect the highest session for the current user. */ if (ulSession > pUserInfo[i].ulSession) { VBoxServiceVerbose(4, "Updating user=%ls to %u processes (last session: %u)\n", UserInfo.wszUser, cSessionProcs, ulSession); pUserInfo[i].ulNumProcs = cSessionProcs; pUserInfo[i].ulSession = ulSession; if (!cSessionProcs) VBoxServiceVerbose(3, "Stale session for user=%ls detected! Old processes: %u, new: %u\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs); } /* There can be multiple session objects using the same session ID for the * current user -- so when we got the same session again just add the found * processes to it. */ else if (pUserInfo[i].ulSession == ulSession) { VBoxServiceVerbose(4, "Adding %u processes to user=%ls (session %u)\n", cSessionProcs, UserInfo.wszUser, ulSession); pUserInfo[i].ulNumProcs += cSessionProcs; pUserInfo[i].ulSession = ulSession; } fFoundUser = true; break; } } if (!fFoundUser) { VBoxServiceVerbose(4, "Adding new user=%ls (session %u) with %u processes\n", UserInfo.wszUser, ulSession, cSessionProcs); memcpy(&pUserInfo[cUniqueUsers], &UserInfo, sizeof(VBOXSERVICEVMINFOUSER)); pUserInfo[cUniqueUsers].ulNumProcs = cSessionProcs; pUserInfo[cUniqueUsers].ulSession = ulSession; cUniqueUsers++; Assert(cUniqueUsers <= cSessions); } } } VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n", cUniqueUsers); *pcUsersInList = 0; for (ULONG i = 0; i < cUniqueUsers; i++) { if (pUserInfo[i].ulNumProcs) { VBoxServiceVerbose(3, "User %ls has %ld processes (session %u)\n", pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulSession); if (*pcUsersInList > 0) { rc = RTStrAAppend(ppszUserList, ","); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } *pcUsersInList += 1; char *pszTemp; int rc2 = RTUtf16ToUtf8(pUserInfo[i].wszUser, &pszTemp); if (RT_SUCCESS(rc2)) { rc = RTStrAAppend(ppszUserList, pszTemp); RTMemFree(pszTemp); } else rc = RTStrAAppend(ppszUserList, "<string-conversion-error>"); AssertRCBreakStmt(rc, RTStrFree(*ppszUserList)); } } RTMemFree(pUserInfo); } VBoxServiceVMInfoWinProcessesFree(paProcs); } LsaFreeReturnBuffer(paSessions); return rc; }
/** * Write clipboard content to the host clipboard from the internal clipboard * structure. * * @param pPasteboardRef Reference to the global pasteboard. * @param pv The source buffer. * @param cb The size of the source buffer. * @param fFormats The format type which should be written. * * @returns IPRT status code. */ int writeToPasteboard(PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat) { Log(("writeToPasteboard: fFormat = %02X\n", fFormat)); /* Clear the pasteboard */ if (PasteboardClear(pPasteboard)) return VERR_NOT_SUPPORTED; /* Make sure all is in sync */ PasteboardSynchronize(pPasteboard); int rc = VERR_NOT_SUPPORTED; /* Handle the unicode text */ if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) { PRTUTF16 pwszSrcText = static_cast <PRTUTF16>(pv); size_t cwSrc = cb / 2; size_t cwDest = 0; /* How long will the converted text be? */ rc = vboxClipboardUtf16GetLinSize(pwszSrcText, cwSrc, &cwDest); if (RT_FAILURE(rc)) { Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc)); AssertRCReturn(rc, rc); } /* Empty clipboard? Not critical */ if (cwDest == 0) { Log(("writeToPasteboard: received empty clipboard data from the guest, returning false.\n")); return VINF_SUCCESS; } /* Allocate the necessary memory */ PRTUTF16 pwszDestText = static_cast <PRTUTF16>(RTMemAlloc(cwDest * 2)); if (pwszDestText == NULL) { Log(("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2)); return VERR_NO_MEMORY; } /* Convert the EOL */ rc = vboxClipboardUtf16WinToLin(pwszSrcText, cwSrc, pwszDestText, cwDest); if (RT_FAILURE(rc)) { Log(("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc)); RTMemFree(pwszDestText); AssertRCReturn(rc, rc); } CFDataRef textData = NULL; /* Item id is 1. Nothing special here. */ PasteboardItemID itemId = (PasteboardItemID)1; /* Create a CData object which we could pass to the pasteboard */ if ((textData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pwszDestText), cwDest * 2))) { /* Put the Utf-16 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeUTF16PlainText, textData, 0); } /* Create a Utf-8 version */ char *pszDestText; rc = RTUtf16ToUtf8(pwszDestText, &pszDestText); if (RT_SUCCESS(rc)) { /* Create a CData object which we could pass to the pasteboard */ if ((textData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pszDestText), strlen(pszDestText)))) { /* Put the Utf-8 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeUTF8PlainText, textData, 0); } RTStrFree(pszDestText); } RTMemFree(pwszDestText); rc = VINF_SUCCESS; } /* Handle the bitmap */ else if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) { /* Create a full BMP from it */ void *pBmp; size_t cbBmpSize; CFDataRef bmpData = NULL; /* Item id is 1. Nothing special here. */ PasteboardItemID itemId = (PasteboardItemID)1; rc = vboxClipboardDibToBmp(pv, cb, &pBmp, &cbBmpSize); if (RT_SUCCESS(rc)) { /* Create a CData object which we could pass to the pasteboard */ if ((bmpData = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8*>(pBmp), cbBmpSize))) { /* Put the Utf-8 version to the pasteboard */ PasteboardPutItemFlavor(pPasteboard, itemId, kUTTypeBMP, bmpData, 0); } RTMemFree(pBmp); } rc = VINF_SUCCESS; } else rc = VERR_NOT_IMPLEMENTED; Log(("writeToPasteboard: rc = %02X\n", rc)); return rc; }
RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget) { AssertPtr(ppszTarget); PRTUTF16 pwszNativeSymlink; int rc = RTStrToUtf16(pszSymlink, &pwszNativeSymlink); if (RT_SUCCESS(rc)) { HANDLE hSymlink = CreateFileW(pwszNativeSymlink, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hSymlink != INVALID_HANDLE_VALUE) { DWORD cbReturned = 0; union { MY_REPARSE_DATA_BUFFER Buf; uint8_t abBuf[16*_1K + sizeof(WCHAR)]; } u; if (DeviceIoControl(hSymlink, MY_FSCTL_GET_REPARSE_POINT, NULL /*pInBuffer */, 0 /*cbInBuffer */, &u.Buf, sizeof(u) - sizeof(WCHAR), &cbReturned, NULL /*pOverlapped*/)) { if (u.Buf.ReparseTag == MY_IO_REPARSE_TAG_SYMLINK) { PWCHAR pwszTarget = &u.Buf.SymbolicLinkReparseBuffer.PathBuffer[0]; pwszTarget += u.Buf.SymbolicLinkReparseBuffer.SubstituteNameOffset / 2; pwszTarget[u.Buf.SymbolicLinkReparseBuffer.SubstituteNameLength / 2] = 0; if ( !(u.Buf.SymbolicLinkReparseBuffer.Flags & MY_SYMLINK_FLAG_RELATIVE) && pwszTarget[0] == '\\' && pwszTarget[1] == '?' && pwszTarget[2] == '?' && pwszTarget[3] == '\\' && pwszTarget[4] != 0 ) pwszTarget += 4; rc = RTUtf16ToUtf8(pwszTarget, ppszTarget); } else rc = VERR_NOT_SYMLINK; } else rc = RTErrConvertFromWin32(GetLastError()); CloseHandle(hSymlink); } else rc = RTErrConvertFromWin32(GetLastError()); RTUtf16Free(pwszNativeSymlink); } if (RT_SUCCESS(rc)) LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc *ppszTarget=%p:{%s}\n", pszSymlink, pszSymlink, ppszTarget, rc, *ppszTarget, *ppszTarget)); else LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc\n", pszSymlink, pszSymlink, ppszTarget, rc)); return rc; }
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; }
/** * Internal worker which initializes or re-initializes the * program path, name and directory globals. * * @returns IPRT status code. * @param fFlags Flags, see RTR3INIT_XXX. * @param cArgs Pointer to the argument count. * @param ppapszArgs Pointer to the argument vector pointer. NULL * allowed if @a cArgs is 0. */ static int rtR3InitArgv(uint32_t fFlags, int cArgs, char ***ppapszArgs) { NOREF(fFlags); if (cArgs) { AssertPtr(ppapszArgs); AssertPtr(*ppapszArgs); char **papszOrgArgs = *ppapszArgs; /* * Normally we should only be asked to convert arguments once. If we * are though, it should be the already convered arguments. */ if (g_crtArgs != -1) { AssertReturn( g_crtArgs == cArgs && g_papszrtArgs == papszOrgArgs, VERR_WRONG_ORDER); /* only init once! */ return VINF_SUCCESS; } if (!(fFlags & RTR3INIT_FLAGS_UTF8_ARGV)) { /* * Convert the arguments. */ char **papszArgs = (char **)RTMemAllocZ((cArgs + 1) * sizeof(char *)); if (!papszArgs) return VERR_NO_MEMORY; #ifdef RT_OS_WINDOWS /* HACK ALERT! Try convert from unicode versions if possible. Unfortunately for us, __wargv is only initialized if we have a unicode main function. So, we have to use CommandLineToArgvW to get something similar. It should do the same conversion... :-) */ int cArgsW = -1; PWSTR *papwszArgs = NULL; if ( papszOrgArgs == __argv && cArgs == __argc && (papwszArgs = CommandLineToArgvW(GetCommandLineW(), &cArgsW)) != NULL ) { AssertMsg(cArgsW == cArgs, ("%d vs %d\n", cArgsW, cArgs)); for (int i = 0; i < cArgs; i++) { int rc = RTUtf16ToUtf8(papwszArgs[i], &papszArgs[i]); if (RT_FAILURE(rc)) { while (i--) RTStrFree(papszArgs[i]); RTMemFree(papszArgs); LocalFree(papwszArgs); return rc; } } LocalFree(papwszArgs); } else #endif { for (int i = 0; i < cArgs; i++) { int rc = RTStrCurrentCPToUtf8(&papszArgs[i], papszOrgArgs[i]); if (RT_FAILURE(rc)) { while (i--) RTStrFree(papszArgs[i]); RTMemFree(papszArgs); return rc; } } } papszArgs[cArgs] = NULL; g_papszrtOrgArgs = papszOrgArgs; g_papszrtArgs = papszArgs; g_crtArgs = cArgs; *ppapszArgs = papszArgs; } else { /* * The arguments are already UTF-8, no conversion needed. */ g_papszrtOrgArgs = papszOrgArgs; g_papszrtArgs = papszOrgArgs; g_crtArgs = cArgs; } } return VINF_SUCCESS; }
RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf) { AssertPtrReturn(pszBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER); *pszBuf = '\0'; AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER); /* * Figure the property name before we start. */ const char *pszPropName; switch (enmString) { case RTSYSDMISTR_PRODUCT_NAME: pszPropName = "Name"; break; case RTSYSDMISTR_PRODUCT_VERSION: pszPropName = "Version"; break; case RTSYSDMISTR_PRODUCT_UUID: pszPropName = "UUID"; break; case RTSYSDMISTR_PRODUCT_SERIAL: pszPropName = "IdentifyingNumber"; break; case RTSYSDMISTR_MANUFACTURER: pszPropName = "Vendor"; break; default: return VERR_NOT_SUPPORTED; } /* * Before we do anything with COM, we have to initialize it. */ HRESULT hrc = rtSystemDmiWinInitialize(); if (FAILED(hrc)) return VERR_NOT_SUPPORTED; int rc = VERR_NOT_SUPPORTED; BSTR pBstrPropName = rtSystemWinBstrFromUtf8(pszPropName); if (pBstrPropName) { /* * Instantiate the IWbemLocator, whatever that is and connect to the * DMI serve. */ IWbemLocator *pLoc; hrc = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc); if (SUCCEEDED(hrc)) { IWbemServices *pServices; hrc = rtSystemDmiWinConnectToServer(pLoc, "ROOT\\CIMV2", &pServices); if (SUCCEEDED(hrc)) { /* * Enumerate whatever it is we're looking at and try get * the desired property. */ BSTR pBstrFilter = rtSystemWinBstrFromUtf8("Win32_ComputerSystemProduct"); if (pBstrFilter) { IEnumWbemClassObject *pEnum; hrc = pServices->CreateInstanceEnum(pBstrFilter, 0, NULL, &pEnum); if (SUCCEEDED(hrc)) { do { IWbemClassObject *pObj; ULONG cObjRet; hrc = pEnum->Next(WBEM_INFINITE, 1, &pObj, &cObjRet); if ( SUCCEEDED(hrc) && cObjRet >= 1) { VARIANT Var; VariantInit(&Var); hrc = pObj->Get(pBstrPropName, 0, &Var, 0, 0); if ( SUCCEEDED(hrc) && V_VT(&Var) == VT_BSTR) { /* * Convert the BSTR to UTF-8 and copy it * into the return buffer. */ char *pszValue; rc = RTUtf16ToUtf8(Var.bstrVal, &pszValue); if (RT_SUCCESS(rc)) { rc = RTStrCopy(pszBuf, cbBuf, pszValue); RTStrFree(pszValue); hrc = WBEM_S_FALSE; } } VariantClear(&Var); pObj->Release(); } } while (hrc != WBEM_S_FALSE); pEnum->Release(); } SysFreeString(pBstrFilter); } else hrc = E_OUTOFMEMORY; pServices->Release(); } pLoc->Release(); } SysFreeString(pBstrPropName); } else hrc = E_OUTOFMEMORY; rtSystemDmiWinTerminate(); if (FAILED(hrc) && rc == VERR_NOT_SUPPORTED) rc = VERR_NOT_SUPPORTED; return rc; }
/* * We are always executed from one specific HGCM thread. So thread safe. */ int vbsfMappingsAdd(PSHFLSTRING pFolderName, PSHFLSTRING pMapName, bool fWritable, bool fAutoMount, bool fSymlinksCreate, bool fMissing) { unsigned i; Assert(pFolderName && pMapName); Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2)); /* check for duplicates */ for (i=0; i<SHFL_MAX_MAPPINGS; i++) { if (FolderMapping[i].fValid == true) { if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) { AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); return VERR_ALREADY_EXISTS; } } } for (i=0; i<SHFL_MAX_MAPPINGS; i++) { if (FolderMapping[i].fValid == false) { int rc = RTUtf16ToUtf8(pFolderName->String.ucs2, &FolderMapping[i].pszFolderName); AssertRCReturn(rc, rc); FolderMapping[i].pMapName = (PSHFLSTRING)RTMemAlloc(ShflStringSizeOfBuffer(pMapName)); if (!FolderMapping[i].pMapName) { RTStrFree(FolderMapping[i].pszFolderName); AssertFailed(); return VERR_NO_MEMORY; } FolderMapping[i].pMapName->u16Length = pMapName->u16Length; FolderMapping[i].pMapName->u16Size = pMapName->u16Size; memcpy(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2, pMapName->u16Size); FolderMapping[i].fValid = true; FolderMapping[i].cMappings = 0; FolderMapping[i].fWritable = fWritable; FolderMapping[i].fAutoMount = fAutoMount; FolderMapping[i].fSymlinksCreate = fSymlinksCreate; FolderMapping[i].fMissing = fMissing; /* Check if the host file system is case sensitive */ RTFSPROPERTIES prop; char *pszAsciiRoot; rc = RTStrUtf8ToCurrentCP(&pszAsciiRoot, FolderMapping[i].pszFolderName); if (RT_SUCCESS(rc)) { rc = RTFsQueryProperties(pszAsciiRoot, &prop); AssertRC(rc); RTStrFree(pszAsciiRoot); } FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false; vbsfRootHandleAdd(i); break; } } if (i == SHFL_MAX_MAPPINGS) { AssertMsgFailed(("vbsfMappingsAdd: no more room to add mapping %ls to %ls!!\n", pFolderName->String.ucs2, pMapName->String.ucs2)); return VERR_TOO_MUCH_DATA; } Log(("vbsfMappingsAdd: added mapping %ls to %ls\n", pFolderName->String.ucs2, pMapName->String.ucs2)); return VINF_SUCCESS; }