SSM.cpp revision c98fb3e16fcd571a790eab772c0c66173d225205
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * SSM - Saved State Manager.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2007 innotek GmbH
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License as published by the Free Software Foundation,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** @page pg_ssm SSM - The Saved State Manager
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * The Saved State Manager (SSM) implements facilities for saving and loading
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * a VM state in a structural manner using callbacks for each collection of
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * data which needs saving.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * At init time each of the VM components will register data entities which
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * they need to save and restore. Each entity have a unique name (ascii) and
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * a set of callbacks associated with it. The name will be used to identify
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * the entity during restore. The callbacks are for the two operations, save
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * and restore. There are three callbacks for each of the two - a prepare,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * a execute and a what-now.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * The SSM provides a number of APIs for encoding and decoding the data.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Header Files *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync* Defined Constants And Macros *
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** Start structure magic. (Isacc Asimov) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** End structure magic. (Isacc Asimov) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Structures and Typedefs *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Handle structure.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsynctypedef struct SSMHANDLE
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The file handle. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** The VM handle. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The current operation. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** What to do after save completes. (move the enum) */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** The current rc of the save operation. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** The compressor of the current data unit. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** The decompressor of the current data unit. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** Number of bytes left in the current data unit. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Pointer to the progress callback function. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** User specified arguemnt to the callback function. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Next completion percentage. (corresponds to offEstProgress) */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** The position of the next progress callback in the estimated file. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The estimated total byte count.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * (Only valid after the prep.) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Current position in the estimated file. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** End of current unit in the estimated file. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** the amount of % we reserve for the 'prepare' phase */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /** the amount of % we reserve for the 'done' stage */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Header of the saved state file.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsynctypedef struct SSMFILEHDR
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Magic string which identifies this file as a version of VBox saved state file format. */
80626cd34607c5dbf3f0af51b32396ce58bf493bvboxsync /** The size of this file. Used to check
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * whether the save completed and that things are fine otherwise. */
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync /** File checksum. The actual calculation skips past the u32CRC field. */
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync /** The machine UUID. (Ignored if NIL.) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** Saved state file magic base string. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define SSMFILEHDR_MAGIC_BASE "\177VirtualBox SavedState "
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** Saved state file v1.0 magic. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define SSMFILEHDR_MAGIC_V1 "\177VirtualBox SavedState V1.0\n"
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Data unit header.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Magic. */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync /** Number of bytes in this data unit including the header. */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync /** Data version. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Instance number. */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /** Size of the data unit name including the terminator. (bytes) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** Data unit name. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** Data unit magic. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** Data end marker magic. */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Internal Functions *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic int smmr3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, PSSMUNIT *ppUnit);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic int ssmr3CalcChecksum(RTFILE File, uint64_t cbFile, uint32_t *pu32CRC);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic int ssmr3Validate(RTFILE File, PSSMFILEHDR pHdr);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic PSSMUNIT ssmr3Find(PVM pVM, const char *pszName, uint32_t u32Instance);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic int ssmr3Write(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic DECLCALLBACK(int) ssmr3WriteOut(void *pvSSM, const void *pvBuf, size_t cbBuf);
5f2909f8dd32d40a7e87f636c1a7c9de674be94bvboxsyncstatic int ssmr3Read(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsyncstatic DECLCALLBACK(int) ssmr3ReadIn(void *pvSSM, void *pvBuf, size_t cbBuf, size_t *pcbRead);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync * Internal registration worker.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status code.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pVM The VM handle.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pszName Data unit name.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param u32Instance The instance id.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param u32Version The data unit version.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param cbGuess The guessed data unit size.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param ppUnit Where to store the insterted unit node.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Caller must fill in the missing details.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic int smmr3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, PSSMUNIT *ppUnit)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Walk to the end of the list checking for duplicates as we go.
a771f44b96a464259788456c0c68e049e7588066vboxsync AssertMsgFailed(("Duplicate registration %s\n", pszName));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Allocate new node.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pUnit = (PSSMUNIT)MMR3HeapAllocZ(pVM, MM_TAG_SSM, RT_OFFSETOF(SSMUNIT, szName[cchName + 1]));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Fill in (some) data. (Stuff is zero'ed.)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Register a PDM Devices data unit.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM handle.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pDevIns Device instance.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pszName Data unit name.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param u32Instance The instance identifier of the data unit.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * This must together with the name be unique.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param u32Version Data layout version number.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param cbGuess The approximate amount of data in the unit.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * Only for progress indicators.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * @param pfnSavePrep Prepare save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnSaveExec Execute save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnSaveDone Done save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadPrep Prepare load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadExec Execute load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadDone Done load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsyncSSMR3DECL(int) SSMR3Register(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync int rc = smmr3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * Register a PDM driver data unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @returns VBox status.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pVM The VM handle.
eb381fae3bd3bff1dc6b4a194a9dab770961691evboxsync * @param pDrvIns Driver instance.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pszName Data unit name.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param u32Instance The instance identifier of the data unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * This must together with the name be unique.
41c24e185aa1d6b5dc290edbd061c5a3c23a9e2fvboxsync * @param u32Version Data layout version number.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param cbGuess The approximate amount of data in the unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * Only for progress indicators.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSavePrep Prepare save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSaveExec Execute save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSaveDone Done save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadPrep Prepare load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadExec Execute load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadDone Done load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsyncSSMR3DECL(int) SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
eb381fae3bd3bff1dc6b4a194a9dab770961691evboxsync PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync int rc = smmr3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * Register a internal data unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @returns VBox status.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pVM The VM handle.
41c24e185aa1d6b5dc290edbd061c5a3c23a9e2fvboxsync * @param pszName Data unit name.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param u32Instance The instance identifier of the data unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * This must together with the name be unique.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param u32Version Data layout version number.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param cbGuess The approximate amount of data in the unit.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * Only for progress indicators.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSavePrep Prepare save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSaveExec Execute save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnSaveDone Done save callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadPrep Prepare load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadExec Execute load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync * @param pfnLoadDone Done load callback, optional.
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsyncSSMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone)
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync int rc = smmr3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Register an external data unit.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pVM The VM handle.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pszName Data unit name.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param u32Instance The instance identifier of the data unit.
9f2784134174d879b339a957156bb14151f39fd8vboxsync * This must together with the name be unique.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param u32Version Data layout version number.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param cbGuess The approximate amount of data in the unit.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * Only for progress indicators.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnSavePrep Prepare save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnSaveExec Execute save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnSaveDone Done save callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadPrep Prepare load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadExec Execute load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pfnLoadDone Done load callback, optional.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pvUser User argument.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsyncSSMR3DECL(int) SSMR3RegisterExternal(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync int rc = smmr3Register(pVM, pszName, u32Instance, u32Version, cbGuess, &pUnit);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Deregister one or more PDM Device data units.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pDevIns Device instance.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pszName Data unit name.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Use NULL to deregister all data units for that device instance.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param u32Instance The instance identifier of the data unit.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This must together with the name be unique.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @remark Only for dynmaic data units and dynamic unloaded modules.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncSSMR3DECL(int) SSMR3Deregister(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Validate input.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Search the list.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Unlink it, advance pointer, and free the node.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync Log(("SSM: Removed data unit '%s' (pdm dev).\n", pFree->szName));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AssertMsgFailed(("Caller is not owner! Owner=%p Caller=%p %s\n",
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Deregister one ore more PDM Driver data units.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM handle.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pDrvIns Driver instance.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pszName Data unit name.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Use NULL to deregister all data units for that driver instance.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param u32Instance The instance identifier of the data unit.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This must together with the name be unique. Ignored if pszName is NULL.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @remark Only for dynmaic data units and dynamic unloaded modules.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncSSMR3DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t u32Instance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Validate input.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Search the list.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Unlink it, advance pointer, and free the node.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync Log(("SSM: Removed data unit '%s' (pdm drv).\n", pFree->szName));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AssertMsgFailed(("Caller is not owner! Owner=%p Caller=%p %s\n",
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Deregister a data unit.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM handle.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param enmType Unit type
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pszName Data unit name.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @remark Only for dynmaic data units.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic int ssmR3DeregisterByNameAndType(PVM pVM, const char *pszName, SSMUNITTYPE enmType)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Validate input.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Search the list.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Unlink it, advance pointer, and free the node.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync Log(("SSM: Removed data unit '%s' (type=%d).\n", pFree->szName, enmType));
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * Deregister an internal data unit.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pVM The VM handle.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param pszName Data unit name.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @remark Only for dynmaic data units.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncSSMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_INTERNAL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Deregister an external data unit.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * @param pVM The VM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pszName Data unit name.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @remark Only for dynmaic data units.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncSSMR3DECL(int) SSMR3DeregisterExternal(PVM pVM, const char *pszName)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_EXTERNAL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Calculate the checksum of a file portion.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * The current implementation is a cut&past of the libkern/crc32.c file from FreeBSD.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns VBox status.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @param File Handle to the file.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param cbFile Size of the file.
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync * @param pu32CRC Where to store the calculated checksum.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic int ssmr3CalcChecksum(RTFILE File, uint64_t cbFile, uint32_t *pu32CRC)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Allocate a buffer.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Loop reading and calculating CRC32.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* read chunk */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AssertMsgFailed(("Failed with rc=%Vrc while calculating crc.\n", rc));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* update total */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* calc crc32. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* store the calculated crc */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Works the progress calculation.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pSSM The SSM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param cbAdvance Number of bytes to advance
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic void ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Can't advance it beyond the estimated end of the unit. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync uint64_t cbLeft = pSSM->offEstUnitEnd - pSSM->offEst;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* uPercentPrepare% prepare, xx% exec, uPercentDone% done+crc */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync while (pSSM->offEst >= pSSM->offEstProgress && pSSM->uPercent <= 100-pSSM->uPercentDone)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pSSM->pfnProgress(pSSM->pVM, pSSM->uPercent, pSSM->pvUser);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare) * pSSM->cbEstTotal /
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Start VM save operation.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * The caller must be the emulation thread!
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync * @returns VBox status.
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync * @param pVM The VM handle.
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync * @param pszFilename Name of the file to save the state in.
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync * @param enmAfter What is planned after a successful save operation.
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync * @param pfnProgress Progress callback. Optional.
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync * @param pvUser User argument for the progress callback.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncSSMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Validate input.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (enmAfter != SSMAFTER_DESTROY && enmAfter != SSMAFTER_CONTINUE)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AssertMsgFailed(("Invalid enmAfter=%d!\n", enmAfter));
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * Try open the file.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * The 'done' part might take much time:
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * (1) Call the SaveDone function of each module
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * (2) Calculate the Checksum
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * (3) RTFileClose() will probably flush the write cache
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync Handle.uPercentDone = 20; /* reserve substantial time for crc-checking the image */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int rc = RTFileOpen(&Handle.File, pszFilename, RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogRel(("SSM: Failed to create save state file '%s', rc=%Vrc.\n", pszFilename, rc));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Write header.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = RTFileWrite(Handle.File, &Hdr, sizeof(Hdr), NULL);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Clear the per unit flags.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Do the prepare run.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, &Handle);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, &Handle);
b306a397b157898e6f769f640b0dfdffbf8beec7vboxsync rc = pUnit->u.External.pfnSavePrep(&Handle, pUnit->u.External.pvUser);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogRel(("SSM: Prepare save failed with rc=%Vrc for data unit '%s.\n", rc, pUnit->szName));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Progress. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pfnProgress(pVM, Handle.uPercentPrepare-1, pvUser);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Do the execute run.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Estimate.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync ssmR3Progress(&Handle, Handle.offEstUnitEnd - Handle.offEst);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Does this unit have a callback? If, not skip it.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case SSMUNITTYPE_DEV: fSkip = pUnit->u.Dev.pfnSaveExec == NULL; break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case SSMUNITTYPE_DRV: fSkip = pUnit->u.Drv.pfnSaveExec == NULL; break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case SSMUNITTYPE_INTERNAL: fSkip = pUnit->u.Internal.pfnSaveExec == NULL; break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case SSMUNITTYPE_EXTERNAL: fSkip = pUnit->u.External.pfnSaveExec == NULL; break;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync default: fSkip = true; break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Write data unit header
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync SSMFILEUNITHDR UnitHdr = { SSMFILEUNITHDR_MAGIC, 0, pUnit->u32Version, pUnit->u32Instance, pUnit->cchName + 1, { '\0' } };
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = RTFileWrite(Handle.File, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDR, szName[0]), NULL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = RTFileWrite(Handle.File, &pUnit->szName[0], pUnit->cchName + 1, NULL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Call the execute handler.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, &Handle);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, &Handle);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pUnit->u.External.pfnSaveExec(&Handle, pUnit->u.External.pvUser);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Flush buffer / end compression stream.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Update header with correct length.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = RTFileSeek(Handle.File, offHdr, RTFILE_SEEK_BEGIN, NULL);
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync rc = RTFileWrite(Handle.File, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDR, szName[0]), NULL);
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync rc = RTFileSeek(Handle.File, offEnd, RTFILE_SEEK_BEGIN, NULL);
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync Log(("SSM: Data unit: offset %#9llx size %9lld '%s'\n", offHdr, UnitHdr.cbUnit, pUnit->szName));
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync LogRel(("SSM: Failed ending compression stream. rc=%Vrc\n", rc));
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync LogRel(("SSM: Execute save failed with rc=%Vrc for data unit '%s.\n", rc, pUnit->szName));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogRel(("SSM: Failed to write unit header. rc=%Vrc\n", rc));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync } /* for each unit */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* finish the progress. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync ssmR3Progress(&Handle, Handle.offEstUnitEnd - Handle.offEst);
AssertMsg(VBOX_FAILURE(rc) || Handle.uPercent == (101-Handle.uPercentDone), ("%d\n", Handle.uPercent));
case SSMUNITTYPE_DEV:
case SSMUNITTYPE_DRV:
case SSMUNITTYPE_INTERNAL:
case SSMUNITTYPE_EXTERNAL:
rc = RTFileSeek(Handle.File, RT_OFFSETOF(SSMFILEHDR, u32CRC) + sizeof(Hdr.u32CRC), RTFILE_SEEK_BEGIN, NULL);
if (pfnProgress)
if (pfnProgress)
return VINF_SUCCESS;
return rc;
return rc;
return VERR_SSM_INTEGRITY_MAGIC;
Log(("SSM: Unknown file format version. magic=%.*s\n", sizeof(pHdr->achMagic) - 1, pHdr->achMagic));
return VERR_SSM_INTEGRITY_VERSION;
return rc;
return VERR_SSM_INTEGRITY_SIZE;
rc = RTFileSeek(File, RT_OFFSETOF(SSMFILEHDR, u32CRC) + sizeof(pHdr->u32CRC), RTFILE_SEEK_BEGIN, NULL);
return rc;
return rc;
return VERR_SSM_INTEGRITY_CRC;
return VERR_SMM_INTEGRITY_MACHINE;
return VINF_SUCCESS;
while ( pUnit
return pUnit;
SSMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
LogFlow(("SSMR3Load: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
return VERR_INVALID_PARAMETER;
int rc = RTFileOpen(&Handle.File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
return rc;
case SSMUNITTYPE_DEV:
case SSMUNITTYPE_DRV:
case SSMUNITTYPE_INTERNAL:
case SSMUNITTYPE_EXTERNAL:
if (pfnProgress)
if (pszName)
if (pszName)
if (pUnit)
case SSMUNITTYPE_DEV:
case SSMUNITTYPE_DRV:
case SSMUNITTYPE_INTERNAL:
case SSMUNITTYPE_EXTERNAL:
if (!rc)
if (i64Diff < 0)
else if (i64Diff > 0)
AssertMsg(VBOX_FAILURE(rc) || Handle.uPercent == (101-Handle.uPercentDone), ("%d\n", Handle.uPercent));
case SSMUNITTYPE_DEV:
case SSMUNITTYPE_DRV:
case SSMUNITTYPE_INTERNAL:
case SSMUNITTYPE_EXTERNAL:
if (pfnProgress)
if (pfnProgress)
return rc;
return rc;
LogFlow(("SSMR3Open: pszFilename=%p:{%s} fFlags=%#x ppSSM=%p\n", pszFilename, pszFilename, fFlags, ppSSM));
return VINF_SUCCESS;
return rc;
AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
return rc;
SSMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
if (pszName)
if (pszName)
if (piVersion)
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
Log2(("ssmr3Write: pvBuf=%p cbBuf=%#x %.*Vhxs%s\n", pvBuf, cbBuf, RT_MIN(cbBuf, 128), pvBuf, cbBuf > 128 ? "..." : ""));
return rc;
while (cbBuf > 0)
return rc;
return rc;
return rc;
pCur++)
return rc;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_TOO_MUCH_DATA;
if (rc)
return rc;
return VERR_SSM_INVALID_STATE;
Log2(("ssmr3Read: pvBuf=%p cbBuf=%#x %.*Vhxs%s\n", pvBuf, cbBuf, RT_MIN(cbBuf, 128), pvBuf, cbBuf > 128 ? "..." : ""));
if (cbRead)
if (pcbRead)
return VINF_SUCCESS;
return rc;
return VERR_SSM_LOADED_TOO_MUCH;
return rc;
pCur++)
return rc;
return rc;
return rc;
return rc;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
return VERR_SSM_INVALID_STATE;
if (pcbStr)
return VERR_TOO_MUCH_DATA;
return rc;
return VERR_SSM_INVALID_STATE;
return VERR_INVALID_PARAMETER;