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