GuestCtrlIO.cpp revision 22866e6b8e8304e8604724f7509c33253e7eedcf
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/* $Id$ */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/** @file
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * IO helper for IGuest COM class implementations.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Copyright (C) 2011 Oracle Corporation
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * available from http://www.virtualbox.org. This file is free software;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * you can redistribute it and/or modify it under the terms of the GNU
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * General Public License (GPL) as published by the Free Software
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/******************************************************************************
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Header Files *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync ******************************************************************************/
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync#include "GuestCtrlImplPrivate.h"
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/******************************************************************************
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Structures and Typedefs *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync ******************************************************************************/
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/** @todo *NOT* thread safe yet! */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/** @todo Add exception handling for STL stuff! */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncGuestProcessStreamBlock::GuestProcessStreamBlock()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/*
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncGuestProcessStreamBlock::GuestProcessStreamBlock(const GuestProcessStreamBlock &otherBlock)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync for (GuestCtrlStreamPairsIter it = otherBlock.m_mapPairs.begin();
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync it != otherBlock.end(); it++)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync m_mapPairs[it->first] = new
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync if (it->second.pszValue)
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync {
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync RTMemFree(it->second.pszValue);
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync it->second.pszValue = NULL;
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync }
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync }
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync}*/
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsyncGuestProcessStreamBlock::~GuestProcessStreamBlock()
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync{
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync Clear();
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync}
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync/**
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * Destroys the currently stored stream pairs.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync *
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * @return IPRT status code.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync */
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsyncvoid GuestProcessStreamBlock::Clear()
5e08248e91d26e48931e78837c050a7210b10f52vboxsync{
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync m_mapPairs.clear();
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync}
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync/**
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * Returns a 64-bit signed integer of a specified key.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync *
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * @return IPRT status code. VERR_NOT_FOUND if key was not found.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * @param pszKey Name of key to get the value for.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync * @param piVal Pointer to value to return.
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync */
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsyncint GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal)
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync{
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync AssertPtrReturn(piVal, VERR_INVALID_POINTER);
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync const char *pszValue = GetString(pszKey);
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync if (pszValue)
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync {
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync *piVal = RTStrToInt64(pszValue);
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync return VINF_SUCCESS;
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync }
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync return VERR_NOT_FOUND;
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync}
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns a 64-bit integer of a specified key.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return int64_t Value to return, 0 if not found / on failure.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszKey Name of key to get the value for.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncint64_t GuestProcessStreamBlock::GetInt64(const char *pszKey)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int64_t iVal;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return iVal;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns the current number of stream pairs.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return uint32_t Current number of stream pairs.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncsize_t GuestProcessStreamBlock::GetCount()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return m_mapPairs.size();
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns a string value of a specified key.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return uint32_t Pointer to string to return, NULL if not found / on failure.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @param pszKey Name of key to get the value for.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncconst char* GuestProcessStreamBlock::GetString(const char *pszKey)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pszKey, NULL);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync try
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (itPairs != m_mapPairs.end())
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return itPairs->second.mValue.c_str();
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync catch (const std::exception &ex)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync NOREF(ex);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return NULL;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns a 32-bit unsigned integer of a specified key.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return IPRT status code. VERR_NOT_FOUND if key was not found.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszKey Name of key to get the value for.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param puVal Pointer to value to return.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncint GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(puVal, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync const char *pszValue = GetString(pszKey);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pszValue)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *puVal = RTStrToUInt32(pszValue);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VINF_SUCCESS;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return VERR_NOT_FOUND;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns a 32-bit unsigned integer of a specified key.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return uint32_t Value to return, 0 if not found / on failure.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszKey Name of key to get the value for.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncuint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync uint32_t uVal;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return uVal;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Sets a value to a key or deletes a key by setting a NULL value.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return IPRT status code.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszKey Key name to process.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pszValue Value to set. Set NULL for deleting the key.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncint GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync int rc = VINF_SUCCESS;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync try
bd51228d218e2f43d2d5d7f0559901dfaac31c9cvboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync Utf8Str Utf8Key(pszKey);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* Take a shortcut and prevent crashes on some funny versions
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * of STL if map is empty initially. */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (!m_mapPairs.empty())
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync GuestCtrlStreamPairMapIter it = m_mapPairs.find(Utf8Key);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (it != m_mapPairs.end())
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_mapPairs.erase(it);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pszValue)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync VBOXGUESTCTRL_STREAMVALUE val(pszValue);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_mapPairs[Utf8Key] = val;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync catch (const std::exception &ex)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync NOREF(ex);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync///////////////////////////////////////////////////////////////////////////////
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncGuestProcessStream::GuestProcessStream()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync : m_cbAllocated(0),
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize(0),
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbOffset(0),
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_pbBuffer(NULL)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncGuestProcessStream::~GuestProcessStream()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync Destroy();
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Adds data to the internal parser buffer. Useful if there
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * are multiple rounds of adding data needed.
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync *
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync * @return IPRT status code.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pbData Pointer to data to add.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param cbData Size (in bytes) of data to add.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncint GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertPtrReturn(pbData, VERR_INVALID_POINTER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync AssertReturn(cbData, VERR_INVALID_PARAMETER);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
45c4c3d2db1a166b7b1e92960adb823960821386vboxsync int rc = VINF_SUCCESS;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* Rewind the buffer if it's empty. */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync size_t cbInBuf = m_cbSize - m_cbOffset;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync bool const fAddToSet = cbInBuf == 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (fAddToSet)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize = m_cbOffset = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* Try and see if we can simply append the data. */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cbData + m_cbSize <= m_cbAllocated)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize += cbData;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* Move any buffered data to the front. */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync cbInBuf = m_cbSize - m_cbOffset;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cbInBuf == 0)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize = m_cbOffset = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else if (m_cbOffset) /* Do we have something to move? */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memmove(m_pbBuffer, &m_pbBuffer[m_cbOffset], cbInBuf);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize = cbInBuf;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbOffset = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* Do we need to grow the buffer? */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cbData + m_cbSize > m_cbAllocated)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync size_t cbAlloc = m_cbSize + cbData;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync void *pvNew = RTMemRealloc(m_pbBuffer, cbAlloc);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (pvNew)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_pbBuffer = (uint8_t *)pvNew;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbAllocated = cbAlloc;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync else
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync rc = VERR_NO_MEMORY;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /* Finally, copy the data. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (RT_SUCCESS(rc))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync if (cbData + m_cbSize <= m_cbAllocated)
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync m_cbSize += cbData;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync else
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync rc = VERR_BUFFER_OVERFLOW;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return rc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/**
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Destroys the the internal data buffer.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncvoid GuestProcessStream::Destroy()
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync{
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (m_pbBuffer)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync RTMemFree(m_pbBuffer);
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_pbBuffer = NULL;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync }
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbAllocated = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbSize = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync m_cbOffset = 0;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns the current offset of the parser within
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * the internal data buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @return uint32_t Parser offset.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync */
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncuint32_t GuestProcessStream::GetOffset()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return m_cbOffset;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsyncuint32_t GuestProcessStream::GetSize()
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync{
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync return m_cbSize;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync}
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync
3ba795251a7b9f108fb01a3cfb37d763db9188b9vboxsync/**
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Tries to parse the next upcoming pair block within the internal
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * buffer.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns VERR_NO_DATA is no data is in internal buffer or buffer has been
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * completely parsed already.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync *
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * Returns VERR_MORE_DATA if current block was parsed (with zero or more pairs
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * stored in stream block) but still contains incomplete (unterminated)
* data.
*
* Returns VINF_SUCCESS if current block was parsed until the next upcoming
* block (with zero or more pairs stored in stream block).
*
* @return IPRT status code.
* @param streamBlock Reference to guest stream block to fill.
*
*/
int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
{
if ( !m_pbBuffer
|| !m_cbSize)
{
return VERR_NO_DATA;
}
AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER);
if (m_cbOffset == m_cbSize)
return VERR_NO_DATA;
int rc = VINF_SUCCESS;
char *pszOff = (char*)&m_pbBuffer[m_cbOffset];
char *pszStart = pszOff;
while (*pszStart)
{
size_t pairLen = strlen(pszStart);
if ((pszStart - pszOff) + pairLen + 1 >= m_cbSize)
{
rc = VERR_MORE_DATA;
break;
}
else
{
char *pszSep = strchr(pszStart, '=');
char *pszVal = NULL;
if (pszSep)
pszVal = pszSep + 1;
if (!pszSep || !pszVal)
{
rc = VERR_MORE_DATA;
break;
}
/* Terminate the separator so that we can
* use pszStart as our key from now on. */
*pszSep = '\0';
rc = streamBlock.SetValue(pszStart, pszVal);
if (RT_FAILURE(rc))
return rc;
}
/* Next pair. */
pszStart += pairLen + 1;
}
/* If we did not do any movement but we have stuff left
* in our buffer just skip the current termination so that
* we can try next time. */
uint32_t uDistance = (pszStart - pszOff);
if ( !uDistance
&& *pszStart == '\0'
&& m_cbOffset < m_cbSize)
{
uDistance++;
}
m_cbOffset += uDistance;
return rc;
}