CFGM.cpp revision b39d209d32ef988462e1748213acf6197748dc84
/* $Id$ */
/** @file
* CFGM - Configuration Manager.
*/
/*
* Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/** @page pg_cfgm CFGM - The Configuration Manager
*
* The configuration manager is a directory containing the VM configuration at
* run time. It works in a manner similar to the windows registry - it's like a
* file system hierarchy, but the files (values) live in a separate name space
* and can include the path separators.
*
* The configuration is normally created via a callback passed to VMR3Create()
* via the pfnCFGMConstructor parameter. To make testcase writing a bit simpler,
* we allow the callback to be NULL, in which case a simple default
* configuration will be created by CFGMR3ConstructDefaultTree(). The
* Console::configConstructor() method in Main/ConsoleImpl2.cpp creates the
* configuration from the XML.
*
* Devices, drivers, services and other PDM stuff are given their own subtree
* where they are protected from accessing information of any parents. This is
* is implemented via the CFGMR3SetRestrictedRoot() API.
*
* Data validation out over the basic primitives is left to the caller. The
* caller is in a better position to know the proper validation rules of the
* individual properties.
*
* @see grp_cfgm
*
*
* @section sec_cfgm_primitives Data Primitives
*
* CFGM supports the following data primitives:
* - Integers. Representation is unsigned 64-bit. Boolean, unsigned and
* small integers, and pointers are all represented using this primitive.
* - Zero terminated character strings. These are of course UTF-8.
* objects like for instance RTMAC.
*
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_CFGM
#include "CFGMInternal.h"
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* Constructs the configuration for the VM.
*
* @returns VBox status code.
* @param pVM Pointer to VM which configuration has not yet been loaded.
* @param pfnCFGMConstructor Pointer to callback function for constructing the VM configuration tree.
* This is called in the EM.
* @param pvUser The user argument passed to pfnCFGMConstructor.
* @thread EMT.
*/
{
/*
* Init data members.
*/
/*
* Register DBGF into item.
*/
int rc = DBGFR3InfoRegisterInternal(pVM, "cfgm", "Dumps a part of the CFGM tree. The argument indicates where to start.", cfgmR3Info);
/*
* Root Node.
*/
if (!pRoot)
return VERR_NO_MEMORY;
/*
* Call the constructor if specified, if not use the default one.
*/
if (pfnCFGMConstructor)
else
if (RT_SUCCESS(rc))
{
Log(("CFGMR3Init: Successfully constructed the configuration\n"));
}
else
AssertMsgFailed(("Constructor failed with rc=%Rrc pfnCFGMConstructor=%p\n", rc, pfnCFGMConstructor));
return rc;
}
/**
* Terminates the configuration manager.
*
* @returns VBox status code.
* @param pVM VM handle.
*/
{
return 0;
}
/**
* Gets the root node for the VM.
*
* @returns Pointer to root node.
* @param pVM VM handle.
*/
{
}
/**
* Gets the parent of a CFGM node.
*
* @returns Pointer to the parent node.
* @returns NULL if pNode is Root or pNode is the start of a
* restricted subtree (use CFGMr3GetParentEx() for that).
*
* @param pNode The node which parent we query.
*/
{
return NULL;
}
/**
* Gets the parent of a CFGM node.
*
* @returns Pointer to the parent node.
* @returns NULL if pNode is Root or pVM is not correct.
*
* @param pVM The VM handle, used as token that the caller is trusted.
* @param pNode The node which parent we query.
*/
{
return NULL;
}
/**
* Query a child node.
*
* @returns Pointer to the specified node.
* @returns NULL if node was not found or pNode is NULL.
* @param pNode Node pszPath is relative to.
* @param pszPath Path to the child node or pNode.
* It's good style to end this with '/'.
*/
{
if (RT_SUCCESS(rc))
return pChild;
return NULL;
}
/**
* Query a child node by a format string.
*
* @returns Pointer to the specified node.
* @returns NULL if node was not found or pNode is NULL.
* @param pNode Node pszPath is relative to.
* @param pszPathFormat Path to the child node or pNode.
* It's good style to end this with '/'.
* @param ... Arguments to pszPathFormat.
*/
{
return pRet;
}
/**
* Query a child node by a format string.
*
* @returns Pointer to the specified node.
* @returns NULL if node was not found or pNode is NULL.
* @param pNode Node pszPath is relative to.
* @param pszPathFormat Path to the child node or pNode.
* It's good style to end this with '/'.
* @param Args Arguments to pszPathFormat.
*/
{
char *pszPath;
if (pszPath)
{
if (RT_SUCCESS(rc))
return pChild;
}
return NULL;
}
/**
* Gets the first child node.
* Use this to start an enumeration of child nodes.
*
* @returns Pointer to the first child.
* @returns NULL if no children.
* @param pNode Node to enumerate children for.
*/
{
}
/**
* Gets the next sibling node.
* Use this to continue an enumeration.
*
* @returns Pointer to the first child.
* @returns NULL if no children.
* @param pCur Node to returned by a call to CFGMR3GetFirstChild()
* or successive calls to this function.
*/
{
}
/**
* Gets the name of the current node.
* (Needed for enumeration.)
*
* @returns VBox status code.
* @param pCur Node to returned by a call to CFGMR3GetFirstChild()
* or successive calls to CFGMR3GetNextChild().
* @param pszName Where to store the node name.
* @param cchName Size of the buffer pointed to by pszName (with terminator).
*/
{
int rc;
if (pCur)
{
{
rc = VINF_SUCCESS;
}
else
}
else
return rc;
}
/**
* Gets the length of the current node's name.
* (Needed for enumeration.)
*
* @returns Node name length in bytes including the terminating null char.
* @returns 0 if pCur is NULL.
* @param pCur Node to returned by a call to CFGMR3GetFirstChild()
* or successive calls to CFGMR3GetNextChild().
*/
{
}
/**
* Validates that the child nodes are within a set of valid names.
*
* @returns true if all names are found in pszzAllowed.
* @returns false if not.
* @param pNode The node which children should be examined.
* @param pszzValid List of valid names separated by '\\0' and ending with
* a double '\\0'.
*
* @deprecated Use CFGMR3ValidateConfig.
*/
{
if (pNode)
{
{
/* search pszzValid for the name */
while (*psz)
{
break;
/* next */
}
/* if at end of pszzValid we didn't find it => failure */
if (!*psz)
{
return false;
}
}
}
/* all ok. */
return true;
}
/**
* Gets the first value of a node.
* Use this to start an enumeration of values.
*
* @returns Pointer to the first value.
* @param pCur The node (Key) which values to enumerate.
*/
{
}
/**
* Gets the next value in enumeration.
*
* @returns Pointer to the next value.
* @param pCur The current value as returned by this function or CFGMR3GetFirstValue().
*/
{
}
/**
* Get the value name.
* (Needed for enumeration.)
*
* @returns VBox status code.
* @param pCur Value returned by a call to CFGMR3GetFirstValue()
* or successive calls to CFGMR3GetNextValue().
* @param pszName Where to store the value name.
* @param cchName Size of the buffer pointed to by pszName (with terminator).
*/
{
int rc;
if (pCur)
{
{
rc = VINF_SUCCESS;
}
else
}
else
return rc;
}
/**
* Gets the length of the current node's name.
* (Needed for enumeration.)
*
* @returns Value name length in bytes including the terminating null char.
* @returns 0 if pCur is NULL.
* @param pCur Value returned by a call to CFGMR3GetFirstValue()
* or successive calls to CFGMR3GetNextValue().
*/
{
}
/**
* Gets the value type.
* (For enumeration.)
*
* @returns VBox status code.
* @param pCur Value returned by a call to CFGMR3GetFirstValue()
* or successive calls to CFGMR3GetNextValue().
*/
{
}
/**
* Validates that the values are within a set of valid names.
*
* @returns true if all names are found in pszzAllowed.
* @returns false if not.
* @param pNode The node which values should be examined.
* @param pszzValid List of valid names separated by '\\0' and ending with
* a double '\\0'.
* @deprecated Use CFGMR3ValidateConfig.
*/
{
if (pNode)
{
{
/* search pszzValid for the name */
while (*psz)
{
break;
/* next */
}
/* if at end of pszzValid we didn't find it => failure */
if (!*psz)
{
return false;
}
}
}
/* all ok. */
return true;
}
/**
* Query value type.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param penmType Where to store the type.
*/
{
if (RT_SUCCESS(rc))
{
if (penmType)
}
return rc;
}
/**
* Query value size.
* This works on all types of values.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pcb Where to store the value size.
*/
{
if (RT_SUCCESS(rc))
{
{
case CFGMVALUETYPE_INTEGER:
break;
case CFGMVALUETYPE_STRING:
break;
case CFGMVALUETYPE_BYTES:
break;
default:
break;
}
}
return rc;
}
/**
* Query integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu64 Where to store the integer value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu64 Where to store the integer value. This is set to the default on failure.
* @param u64Def The default value. This is always set.
*/
VMMR3DECL(int) CFGMR3QueryIntegerDef(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
{
rc = VINF_SUCCESS;
}
return rc;
}
/**
* Query zero terminated character value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of a zero terminate character value.
* @param pszString Where to store the string.
* @param cchString Size of the string buffer. (Includes terminator.)
*/
VMMR3DECL(int) CFGMR3QueryString(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString)
{
if (RT_SUCCESS(rc))
{
{
{
}
else
}
else
}
return rc;
}
/**
* Query zero terminated character value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of a zero terminate character value.
* @param pszString Where to store the string. This will not be set on overflow error.
* @param cchString Size of the string buffer. (Includes terminator.)
* @param pszDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryStringDef(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef)
{
if (RT_SUCCESS(rc))
{
{
{
}
else
}
else
}
{
{
rc = VINF_SUCCESS;
}
}
return rc;
}
/**
* Query byte string value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of a byte string value.
* @param pvData Where to store the binary data.
* @param cbData Size of buffer pvData points too.
*/
{
if (RT_SUCCESS(rc))
{
{
{
}
else
}
else
}
return rc;
}
/**
* Validate one level of a configuration node.
*
* This replaces the CFGMR3AreChildrenValid and CFGMR3AreValuesValid APIs.
*
* @returns VBox status code.
*
* When an error is returned, both VMSetError and AssertLogRelMsgFailed
* have been called. So, all the caller needs to do is to propagate
* the error status up to PDM.
*
* @param pNode The node to validate.
* @param pszNode The node path, always ends with a slash. Use
* "/" for the root config node.
* @param pszValidValues Patterns describing the valid value names. See
* RTStrSimplePatternMultiMatch for details on the
* pattern syntax.
* @param pszValidNodes Patterns describing the valid node (key) names.
* See RTStrSimplePatternMultiMatch for details on
* the pattern syntax.
* @param pszWho Who is calling.
* @param uInstance The instance number of the caller.
*/
const char *pszValidValues, const char *pszValidNodes,
{
/* Input validation. */
if (pNode)
{
/*
* Enumerate the leafs and check them against pszValidValues.
*/
{
NULL))
{
AssertLogRelMsgFailed(("%s/%u: Value '%s/%s' didn't match '%s'\n",
N_("Unknown configuration value '%s/%s' found in the configuration of %s instance #%u"),
}
}
/*
* Enumerate the child nodes and check them against pszValidNodes.
*/
{
NULL))
{
AssertLogRelMsgFailed(("%s/%u: Node '%s/%s' didn't match '%s'\n",
N_("Unknown configuration node '%s/%s' found in the configuration of %s instance #%u"),
}
}
}
/* All is well. */
return VINF_SUCCESS;
}
/**
* Populates the CFGM tree with the default configuration.
*
* This assumes an empty tree and is intended for testcases and such that only
* need to do very small adjustments to the config.
*
* @returns VBox status code.
* @param pVM VM handle.
*/
{
int rc;
int rcAll = VINF_SUCCESS;
/*
* Create VM default values.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/** @todo CFGM Defaults: RawR0, PATMEnabled and CASMEnabled needs attention later. */
UPDATERC();
UPDATERC();
UPDATERC();
/*
* PDM.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/*
* Devices
*/
UPDATERC();
/* device */
#if 0
#endif
/*
* PC Arch.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/*
* PC Bios.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
RTUuidClear(&Uuid);
UPDATERC();
/*
* PCI bus.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/*
* PS/2 keyboard & mouse
*/
UPDATERC();
UPDATERC();
UPDATERC();
#if 0
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
#endif
#if 0
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
#endif
/*
* i8254 Programmable Interval Timer And Dummy Speaker
*/
UPDATERC();
UPDATERC();
#ifdef DEBUG
UPDATERC();
#endif
UPDATERC();
/*
* i8259 Programmable Interrupt Controller.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/*
* RTC MC146818.
*/
UPDATERC();
UPDATERC();
UPDATERC();
/*
* VGA.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/* Bios logo. */
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
#if 0
UPDATERC();
UPDATERC();
#endif
/*
* IDE controller.
*/
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
/*
* ...
*/
return rcAll;
}
/**
* Resolves a path reference to a child node.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszPath Path to the child node.
* @param ppChild Where to store the pointer to the child node.
*/
{
if (!pNode)
return VERR_CFGM_NO_PARENT;
for (;;)
{
/* skip leading slashes. */
while (*pszPath == '/')
pszPath++;
/* End of path? */
if (!*pszPath)
{
if (!pChild)
return VERR_CFGM_INVALID_CHILD_PATH;
return VINF_SUCCESS;
}
/* find end of component. */
if (!pszNext)
/* search child list. */
{
if (iDiff <= 0)
{
if (iDiff != 0)
break;
}
}
if (!pChild)
return VERR_CFGM_CHILD_NOT_FOUND;
/* next iteration */
}
/* won't get here */
}
/**
* Resolves a path reference to a child node.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of a byte string value.
* @param ppLeaf Where to store the pointer to the leaf node.
*/
{
if (!pNode)
return VERR_CFGM_NO_PARENT;
while (pLeaf)
{
{
if (iDiff <= 0)
{
if (iDiff != 0)
break;
return VINF_SUCCESS;
}
}
/* next */
}
return VERR_CFGM_VALUE_NOT_FOUND;
}
/**
* Creates a CFGM tree.
*
* passed around and later attached to the main tree in the
* correct location.
*
* @returns Pointer to the root node.
* @param pVM The VM handle.
*/
{
if (pNew)
{
pNew->fRestrictedRoot = false;
}
return pNew;
}
/**
* Duplicates a CFGM sub-tree or a full tree.
*
* @returns Pointer to the root node. NULL if we run out of memory or the
* input parameter is NULL.
* @param pRoot The root of the tree to duplicate.
* @param ppCopy Where to return the root of the duplicate.
*/
{
/*
* Create a new tree.
*/
if (!pNewRoot)
return VERR_NO_MEMORY;
/*
* Duplicate the content.
*/
int rc = VINF_SUCCESS;
for (;;)
{
if ( !pDstCur->pFirstChild
&& !pDstCur->pFirstLeaf)
{
/*
* Values first.
*/
/** @todo this isn't the most efficient way to do it. */
/*
* Insert immediate child nodes.
*/
/** @todo this isn't the most efficient way to do it. */
}
/*
* Deep copy of the children.
*/
if (pSrcCur->pFirstChild)
{
Assert(pDstCur->pFirstChild && !strcmp(pDstCur->pFirstChild->szName, pSrcCur->pFirstChild->szName));
}
/*
* If it's the root node, we're done.
*/
break;
else
{
/*
* Upon reaching the end of a sibling list, we must ascend and
* resume the sibiling walk on an previous level.
*/
{
do
{
break;
}
/*
* Next sibling.
*/
}
}
if (RT_FAILURE(rc))
{
return rc;
}
return VINF_SUCCESS;
}
/**
* Insert subtree.
*
* This function inserts (no duplication) a tree created by CFGMR3CreateTree()
* into the main tree.
*
* The root node of the inserted subtree will need to be reallocated, which
* effectually means that the passed in pSubTree handle becomes invalid
* upon successful return. Use the value returned in ppChild instead
* of pSubTree.
*
* @returns VBox status code.
* @returns VERR_CFGM_NODE_EXISTS if the final child node name component exists.
* @param pNode Parent node.
* @param pszName Name or path of the new child node.
* @param pSubTree The subtree to insert. Must be returned by CFGMR3CreateTree().
* @param ppChild Where to store the address of the new child node. (optional)
*/
VMMR3DECL(int) CFGMR3InsertSubTree(PCFGMNODE pNode, const char *pszName, PCFGMNODE pSubTree, PCFGMNODE *ppChild)
{
/*
* Validate input.
*/
/*
* Use CFGMR3InsertNode to create a new node and then
* re-attach the children and leafs of the subtree to it.
*/
if (RT_SUCCESS(rc))
{
if (ppChild)
/* free the old subtree root */
}
return rc;
}
/**
* Replaces a (sub-)tree with new one.
*
* This function removes the exiting (sub-)tree, completely freeing it in the
* process, and inserts (no duplication) the specified tree. The tree can
* either be created by CFGMR3CreateTree or CFGMR3DuplicateSubTree.
*
* @returns VBox status code.
* @param pRoot The sub-tree to replace. This node will remain valid
* after the call.
* @param pNewRoot The tree to replace @a pRoot with. This not will
* become invalid after a successful call.
*/
{
/*
* Validate input.
*/
/*
* Free the current properties fo pRoot.
*/
while (pRoot->pFirstChild)
while (pRoot->pFirstLeaf)
/*
* Copy all the properties from the new root to the current one.
*/
return VINF_SUCCESS;
}
/**
* Copies all values and keys from one tree onto another.
*
* The flags control what happens to keys and values with the same name
* existing in both source and destination.
*
* @returns VBox status code.
* @param pDstTree The destination tree.
* @param pSrcTree The source tree.
* @param fFlags Copy flags, see CFGM_COPY_FLAGS_XXX.
*/
{
/*
* Input validation.
*/
AssertReturn(!(fFlags & ~(CFGM_COPY_FLAGS_VALUE_DISP_MASK | CFGM_COPY_FLAGS_KEY_DISP_MASK)), VERR_INVALID_PARAMETER);
/*
* Copy the values.
*/
int rc;
{
if (rc == VERR_CFGM_LEAF_EXISTS)
{
{
if (RT_FAILURE(rc))
break;
}
else
rc = VINF_SUCCESS;
}
}
/*
*/
for (PCFGMNODE pSrcChild = CFGMR3GetFirstChild(pSrcTree); pSrcChild; pSrcChild = CFGMR3GetNextChild(pSrcChild))
{
if ( pDstChild
{
}
if (!pDstChild)
{
}
{
}
}
return VINF_SUCCESS;
}
/**
* Compares two names.
*
* @returns Similar to memcpy.
* @param pszName1 The first name.
* @param cchName1 The length of the first name.
* @param pszName2 The second name.
* @param cchName2 The length of the second name.
*/
DECLINLINE(int) cfgmR3CompareNames(const char *pszName1, size_t cchName1, const char *pszName2, size_t cchName2)
{
int iDiff;
{
iDiff = -1;
}
else
{
if (!iDiff)
iDiff = 1;
}
return iDiff;
}
/**
* Insert a node.
*
* @returns VBox status code.
* @returns VERR_CFGM_NODE_EXISTS if the final child node name component exists.
* @param pNode Parent node.
* @param pszName Name or path of the new child node.
* @param ppChild Where to store the address of the new child node. (optional)
*/
{
int rc;
if (pNode)
{
/*
* If given a path we have to deal with it component by component.
*/
while (*pszName == '/')
pszName++;
{
if (pszDup)
{
for (;;)
{
/* Terminate at '/' and find the next component. */
if (pszNext)
{
*pszNext++ = '\0';
while (*pszNext == '/')
pszNext++;
if (*pszNext == '\0')
}
/* does it exist? */
if (!pChild)
{
/* no, insert it */
if (RT_FAILURE(rc))
break;
if (!pszNext)
{
if (ppChild)
break;
}
}
/* if last component fail */
else if (!pszNext)
{
break;
}
/* next */
}
}
else
}
/*
* Not multicomponent, just make sure it's a non-zero name.
*/
else if (*pszName)
{
/*
* Check if already exists and find last node in chain.
*/
if (pNext)
{
{
if (iDiff <= 0)
{
if (!iDiff)
return VERR_CFGM_NODE_EXISTS;
break;
}
}
}
/*
* Allocate and init node.
*/
if (pNew)
{
pNew->fRestrictedRoot = false;
/*
* Insert into child list.
*/
if (pPrev)
else
if (pNext)
if (ppChild)
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
}
else
{
}
}
else
{
}
return rc;
}
/**
* Insert a node, format string name.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param ppChild Where to store the address of the new child node. (optional)
* @param pszNameFormat Name of or path the new child node.
* @param ... Name format arguments.
*/
VMMR3DECL(int) CFGMR3InsertNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, ...)
{
return rc;
}
/**
* Insert a node, format string name.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param ppChild Where to store the address of the new child node. (optional)
* @param pszNameFormat Name or path of the new child node.
* @param Args Name format arguments.
*/
VMMR3DECL(int) CFGMR3InsertNodeFV(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, va_list Args)
{
int rc;
char *pszName;
if (pszName)
{
}
else
rc = VERR_NO_MEMORY;
return rc;
}
/**
* Marks the node as the root of a restricted subtree, i.e. the end of
* a CFGMR3GetParent() journey.
*
* @param pNode The node to mark.
*/
{
if (pNode)
pNode->fRestrictedRoot = true;
}
/**
* Insert a node.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Name of the new child node.
* @param ppLeaf Where to store the new leaf.
* The caller must fill in the enmType and Value fields!
*/
{
int rc;
if (*pszName)
{
if (pNode)
{
/*
* Check if already exists and find last node in chain.
*/
if (pNext)
{
{
if (iDiff <= 0)
{
if (!iDiff)
return VERR_CFGM_LEAF_EXISTS;
break;
}
}
}
/*
* Allocate and init node.
*/
if (pNew)
{
/*
* Insert into child list.
*/
if (pPrev)
else
if (pNext)
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
}
else
}
else
return rc;
}
/**
* Remove a node.
*
* @param pNode Parent node.
*/
{
if (pNode)
{
/*
* Free children.
*/
while (pNode->pFirstChild)
/*
* Free leafs.
*/
while (pNode->pFirstLeaf)
/*
* Unlink ourselves.
*/
else
{
}
/*
* Free ourselves. (bit of paranoia first)
*/
}
}
/**
* Removes a leaf.
*
* @param pNode Parent node.
* @param pLeaf Leaf to remove.
*/
{
{
/*
* Unlink.
*/
else
/*
* Free value and node.
*/
}
}
/**
* Frees whatever resources the leaf value is owning.
*
* Use this before assigning a new value to a leaf.
* The caller must either free the leaf or assign a new value to it.
*
* @param pLeaf Pointer to the leaf which value should be free.
*/
{
if (pLeaf)
{
{
case CFGMVALUETYPE_BYTES:
break;
case CFGMVALUETYPE_STRING:
break;
case CFGMVALUETYPE_INTEGER:
break;
}
}
}
/**
* Inserts a new integer value.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param u64Integer The value.
*/
{
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Inserts a new string value. This variant expects that the caller know the length
* of the string already so we can avoid calling strlen() here.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pszString The value. Must not be NULL.
* @param cchString The length of the string excluding the
* terminator.
*/
VMMR3DECL(int) CFGMR3InsertStringN(PCFGMNODE pNode, const char *pszName, const char *pszString, size_t cchString)
{
int rc;
if (pNode)
{
/*
* Allocate string object first.
*/
if (pszStringCopy)
{
/*
* Create value leaf and set it to string type.
*/
if (RT_SUCCESS(rc))
{
}
else
}
else
rc = VERR_NO_MEMORY;
}
else
return rc;
}
/**
* Inserts a new string value. Calls strlen(pszString) internally; if you know the
* length of the string, CFGMR3InsertStringLengthKnown() is faster.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pszString The value.
*/
{
}
/**
* Same as CFGMR3InsertString except the string value given in RTStrPrintfV
* fashion.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pszFormat The value given as a format string.
* @param va Argument to pszFormat.
*/
VMMR3DECL(int) CFGMR3InsertStringFV(PCFGMNODE pNode, const char *pszName, const char *pszFormat, va_list va)
{
int rc;
if (pNode)
{
/*
* Allocate string object first.
*/
if (pszString)
{
/*
* Create value leaf and set it to string type.
*/
if (RT_SUCCESS(rc))
{
}
else
}
else
rc = VERR_NO_MEMORY;
}
else
return rc;
}
/**
* Same as CFGMR3InsertString except the string value given in RTStrPrintf
* fashion.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pszFormat The value given as a format string.
* @param ... Argument to pszFormat.
*/
VMMR3DECL(int) CFGMR3InsertStringF(PCFGMNODE pNode, const char *pszName, const char *pszFormat, ...)
{
return rc;
}
/**
* Same as CFGMR3InsertString except the string value given as a UTF-16 string.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pwszValue The string value (UTF-16).
*/
{
char *pszValue;
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Inserts a new integer value.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Value name.
* @param pvBytes The value.
* @param cbBytes The value size.
*/
VMMR3DECL(int) CFGMR3InsertBytes(PCFGMNODE pNode, const char *pszName, const void *pvBytes, size_t cbBytes)
{
int rc;
if (pNode)
{
{
/*
* Allocate string object first.
*/
{
/*
* Create value leaf and set it to string type.
*/
if (RT_SUCCESS(rc))
{
}
}
else
rc = VERR_NO_MEMORY;
}
else
}
else
return rc;
}
/**
* Make a copy of the specified value under the given node.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pValue The value to copy and insert.
*/
{
int rc;
{
case CFGMVALUETYPE_INTEGER:
break;
case CFGMVALUETYPE_BYTES:
break;
case CFGMVALUETYPE_STRING:
rc = CFGMR3InsertStringN(pNode, pValue->szName, pValue->Value.String.psz, pValue->Value.String.cb - 1);
break;
default:
break;
}
return rc;
}
/**
* Remove a value.
*
* @returns VBox status code.
* @param pNode Parent node.
* @param pszName Name of the new child node.
*/
{
if (RT_SUCCESS(rc))
return rc;
}
/*
* -+- helper apis -+-
*/
/**
* Query unsigned 64-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu64 Where to store the integer value.
*/
{
}
/**
* Query unsigned 64-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu64 Where to store the integer value. Set to default on failure.
* @param u64Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryU64Def(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
{
}
/**
* Query signed 64-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi64 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
return rc;
}
/**
* Query signed 64-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi64 Where to store the value. Set to default on failure.
* @param i64Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryS64Def(PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def)
{
return rc;
}
/**
* Query unsigned 32-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu32 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query unsigned 32-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu32 Where to store the value. Set to default on failure.
* @param u32Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryU32Def(PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def)
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query signed 32-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi32 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query signed 32-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi32 Where to store the value. Set to default on failure.
* @param i32Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryS32Def(PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def)
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query unsigned 16-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu16 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query unsigned 16-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu16 Where to store the value. Set to default on failure.
* @param i16Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryU16Def(PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def)
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query signed 16-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi16 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query signed 16-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi16 Where to store the value. Set to default on failure.
* @param i16Def The default value.
*/
VMMR3DECL(int) CFGMR3QueryS16Def(PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def)
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query unsigned 8-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu8 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query unsigned 8-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu8 Where to store the value. Set to default on failure.
* @param u8Def The default value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query signed 8-bit integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi8 Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
return rc;
}
/**
* Query signed 8-bit integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi8 Where to store the value. Set to default on failure.
* @param i8Def The default value.
*/
{
if (RT_SUCCESS(rc))
{
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query boolean integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pf Where to store the value.
* @remark This function will interpret any non-zero value as true.
*/
{
if (RT_SUCCESS(rc))
return rc;
}
/**
* Query boolean integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pf Where to store the value. Set to default on failure.
* @param fDef The default value.
* @remark This function will interpret any non-zero value as true.
*/
{
return rc;
}
/**
* Query I/O port address value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pPort Where to store the value.
*/
{
}
/**
* Query I/O port address value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pPort Where to store the value. Set to default on failure.
* @param PortDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryPortDef(PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef)
{
}
/**
* Query unsigned int address value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu Where to store the value.
*/
{
AssertCompileSize(unsigned int, 4);
}
/**
* Query unsigned int address value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pu Where to store the value. Set to default on failure.
* @param uDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryUIntDef(PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef)
{
AssertCompileSize(unsigned int, 4);
}
/**
* Query signed int address value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi Where to store the value.
*/
{
AssertCompileSize(signed int, 4);
}
/**
* Query unsigned int address value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pi Where to store the value. Set to default on failure.
* @param iDef The default value.
*/
VMMR3DECL(int) CFGMR3QuerySIntDef(PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef)
{
AssertCompileSize(signed int, 4);
}
/**
* Query pointer integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param ppv Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*ppv = (void *)u;
else
}
return rc;
}
/**
* Query pointer integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param ppv Where to store the value. Set to default on failure.
* @param pvDef The default value.
*/
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*ppv = (void *)u;
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query Guest Context pointer integer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*pGCPtr = u;
else
}
return rc;
}
/**
* Query Guest Context pointer integer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value. Set to default on failure.
* @param GCPtrDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryGCPtrDef(PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef)
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*pGCPtr = u;
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query Guest Context unsigned pointer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*pGCPtr = u;
else
}
return rc;
}
/**
* Query Guest Context unsigned pointer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value. Set to default on failure.
* @param GCPtrDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryGCPtrUDef(PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef)
{
if (RT_SUCCESS(rc))
{
if (u64 == u)
*pGCPtr = u;
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query Guest Context signed pointer value.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value.
*/
{
if (RT_SUCCESS(rc))
{
*pGCPtr = u;
else
}
return rc;
}
/**
* Query Guest Context signed pointer value with default.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Name of an integer value.
* @param pGCPtr Where to store the value. Set to default on failure.
* @param GCPtrDef The default value.
*/
VMMR3DECL(int) CFGMR3QueryGCPtrSDef(PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef)
{
if (RT_SUCCESS(rc))
{
*pGCPtr = u;
else
}
if (RT_FAILURE(rc))
return rc;
}
/**
* Query zero terminated character value storing it in a
* buffer allocated from the MM heap.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Value name. This value must be of zero terminated character string type.
* @param ppszString Where to store the string pointer.
* Free this using MMR3HeapFree().
*/
{
if (RT_SUCCESS(rc))
{
if (pszString)
{
if (RT_SUCCESS(rc))
*ppszString = pszString;
else
}
else
rc = VERR_NO_MEMORY;
}
return rc;
}
/**
* Query zero terminated character value storing it in a
* buffer allocated from the MM heap.
*
* @returns VBox status code.
* @param pNode Which node to search for pszName in.
* @param pszName Value name. This value must be of zero terminated character string type.
* @param ppszString Where to store the string pointer. Not set on failure.
* Free this using MMR3HeapFree().
* @param pszDef The default return value. This can be NULL.
*/
VMMR3DECL(int) CFGMR3QueryStringAllocDef(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef)
{
/*
* (Don't call CFGMR3QuerySize and CFGMR3QueryStringDef here as the latter
* cannot handle pszDef being NULL.)
*/
if (RT_SUCCESS(rc))
{
{
if (pszString)
{
*ppszString = pszString;
}
else
rc = VERR_NO_MEMORY;
}
else
}
if (RT_FAILURE(rc))
{
if (!pszDef)
*ppszString = NULL;
else
rc = VINF_SUCCESS;
}
return rc;
}
/**
* Dumps the configuration (sub)tree to the release log.
*
* @param pRoot The root node of the dump.
*/
{
LogRel(("************************* CFGM dump *************************\n"));
LogRel(("********************* End of CFGM dump **********************\n"));
}
/**
* Info handler, internal version.
*
* @param pVM The VM handle.
* @param pHlp Callback functions for doing output.
* @param pszArgs Argument string. Optional and specific to the handler.
*/
{
/*
* Figure where to start.
*/
{
if (RT_FAILURE(rc))
{
return;
}
}
/*
* Dump the specified tree.
*/
}
/**
* Recursively prints a path name.
*/
{
}
/**
* Dumps a branch of a tree.
*/
{
/*
* Path.
*/
pHlp->pfnPrintf(pHlp, "] (level %d)%s\n", iLevel, pRoot->fRestrictedRoot ? " (restricted root)" : "");
/*
* Values.
*/
{
switch (CFGMR3GetValueType(pLeaf))
{
case CFGMVALUETYPE_INTEGER:
{
pHlp->pfnPrintf(pHlp, " %-*s <integer> = %#018llx (%'lld", (int)cchMax, pLeaf->szName, pLeaf->Value.Integer.u64, pLeaf->Value.Integer.u64);
{
}
break;
}
case CFGMVALUETYPE_STRING:
pHlp->pfnPrintf(pHlp, " %-*s <string> = \"%s\" (cb=%zu)\n", (int)cchMax, pLeaf->szName, pLeaf->Value.String.psz, pLeaf->Value.String.cb);
break;
case CFGMVALUETYPE_BYTES:
pHlp->pfnPrintf(pHlp, " %-*s <bytes> = \"%.*Rhxs\" (cb=%zu)\n", (int)cchMax, pLeaf->szName, pLeaf->Value.Bytes.cb, pLeaf->Value.Bytes.pau8, pLeaf->Value.Bytes.cb);
break;
default:
AssertMsgFailed(("bad leaf!\n"));
break;
}
}
/*
* Children.
*/
{
}
}