Index: /trunk/include/VBox/ssm.h
===================================================================
--- /trunk/include/VBox/ssm.h	(revision 23597)
+++ /trunk/include/VBox/ssm.h	(revision 23598)
@@ -702,8 +702,6 @@
     uint32_t    u32EndVersion;
 } SSMSTRMOPS;
-/** Pointer to a const SSM stream method table. */
-typedef SSMSTRMOPS const *PCSSMSTRMOPS;
 /** Struct magic + version (SSMSTRMOPS_VERSION). */
-#define SSMSTRMOPS_VERSION  UINT32_C(0x55aa0001)
+#define SSMSTRMOPS_VERSION      UINT32_C(0x55aa0001)
 
 
Index: /trunk/include/VBox/types.h
===================================================================
--- /trunk/include/VBox/types.h	(revision 23597)
+++ /trunk/include/VBox/types.h	(revision 23598)
@@ -373,4 +373,6 @@
 /** SSM Operation handle. */
 typedef struct SSMHANDLE *PSSMHANDLE;
+/** Pointer to a const SSM stream method table. */
+typedef struct SSMSTRMOPS const *PCSSMSTRMOPS;
 
 /** Pointer to a CPUMCTX. */
Index: /trunk/include/VBox/vmapi.h
===================================================================
--- /trunk/include/VBox/vmapi.h	(revision 23597)
+++ /trunk/include/VBox/vmapi.h	(revision 23598)
@@ -337,5 +337,8 @@
 
 VMMR3DECL(int)  VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser);
-VMMR3DECL(int)  VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int)  VMR3Migrate(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser);
+VMMR3DECL(int)  VMR3LoadFromFile(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int)  VMR3LoadFromStream(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                   PFNVMPROGRESS pfnProgress, void *pvProgressUser);
 VMMR3DECL(int)  VMR3PowerOff(PVM pVM);
 VMMR3DECL(int)  VMR3Destroy(PVM pVM);
Index: /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp	(revision 23597)
+++ /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp	(revision 23598)
@@ -333,8 +333,9 @@
  * Update progress display.
  */
-void callProgressInfo(PVM pVM, unsigned uPercent, void *pvUser)
+int callProgressInfo(PVM pVM, unsigned uPercent, void *pvUser)
 {
     if (gConsole)
         gConsole->progressInfo(pVM, uPercent, pvUser);
+    return VINF_SUCCESS;
 }
 
@@ -965,5 +966,5 @@
         {
             /* Power off VM */
-            rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMR3PowerOff, 1, pVM);
+            rc = VMR3PowerOff(pVM);
             AssertRC(rc);
         }
@@ -1276,19 +1277,18 @@
         {
             startProgressInfo("Restoring");
-            rc = VMR3ReqCallWait(pVM, VMCPUID_ANY,
-                             (PFNRT)VMR3Load, 4, pVM, g_pszStateFile, &callProgressInfo, (uintptr_t)NULL);
+            rc = VMR3LoadFromFile(pVM, g_pszStateFile, callProgressInfo, (uintptr_t)NULL);
             endProgressInfo();
             if (RT_SUCCESS(rc))
             {
-                rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMR3Resume, 1, pVM);
+                rc = VMR3Resume(pVM);
                 AssertRC(rc);
                 gDisplay->setRunning();
             }
             else
-                AssertMsgFailed(("VMR3Load failed, rc=%Rrc\n", rc));
+                AssertMsgFailed(("VMR3LoadFromFile failed, rc=%Rrc\n", rc));
         }
         else
         {
-            rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMR3PowerOn, 1, pVM);
+            rc = VMR3PowerOn(pVM);
             if (RT_FAILURE(rc))
                 AssertMsgFailed(("VMR3PowerOn failed, rc=%Rrc\n", rc));
Index: /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.h	(revision 23597)
+++ /trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.h	(revision 23598)
@@ -55,5 +55,5 @@
 
 void   startProgressInfo(const char *pszStr);
-void   callProgressInfo(PVM pVM, unsigned uPercent, void *pvUser);
+int    callProgressInfo(PVM pVM, unsigned uPercent, void *pvUser);
 void   endProgressInfo();
 bool   fActivateHGCM();
Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 23597)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 23598)
@@ -1092,5 +1092,5 @@
     AssertReturn(that, VERR_INVALID_PARAMETER);
 
-    /* Currently, nothing to do when we've been called from VMR3Load. */
+    /* Currently, nothing to do when we've been called from VMR3Load*. */
     return SSMR3SkipToEndOfUnit(pSSM);
 }
@@ -6167,5 +6167,6 @@
 
 /**
- * Process callback handler for VMR3Load and VMR3Save.
+ * Process callback handler for VMR3LoadFromFile, VMR3LoadFromStream, VMR3Save
+ * and VMR3Migrate.
  *
  * @param   pVM         The VM handle.
@@ -6689,8 +6690,8 @@
                                  task->mSavedStateFile.raw()));
 
-                    vrc = VMR3Load(pVM,
-                                   task->mSavedStateFile.c_str(),
-                                   Console::stateProgressCallback,
-                                   static_cast<VMProgressTask*>(task.get()));
+                    vrc = VMR3LoadFromFile(pVM,
+                                           task->mSavedStateFile.c_str(),
+                                           Console::stateProgressCallback,
+                                           static_cast<VMProgressTask*>(task.get()));
 
                     if (RT_SUCCESS(vrc))
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 23597)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 23598)
@@ -1562,20 +1562,25 @@
 
 /**
- * Worker for VMR3Save that validates the state and calls SSMR3Save.
+ * Worker for vmR3SaveMigrate that validates the state and calls SSMR3Save or
+ * SSMR3LiveSave.
  *
  * @returns VBox status code.
  *
  * @param   pVM             The VM handle.
- * @param   pszFilename     The name of the save state file.
+ * @param   pszFilename     The name of the file.  NULL if pStreamOps is used.
+ * @param   pStreamOps      The stream methods.  NULL if pszFilename is used.
+ * @param   pvStreamOpsUser The user argument to the stream methods.
  * @param   enmAfter        What to do afterwards.
  * @param   pfnProgress     Progress callback. Optional.
- * @param   pvUser          User argument for the progress callback.
+ * @param   pvProgressUser  User argument for the progress callback.
  * @param   ppSSM           Where to return the saved state handle in case of a
  *                          live snapshot scenario.
  * @thread  EMT
  */
-static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
-{
-    LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p ppSSM=%p\n", pVM, pszFilename, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM));
+static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                  SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
+{
+    LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p ppSSM=%p\n",
+             pVM, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser, ppSSM));
 
     /*
@@ -1596,11 +1601,11 @@
     if (rc == 1)
     {
-        rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress, pvUser);
+        rc = SSMR3Save(pVM, pszFilename, enmAfter, pfnProgress, pvProgressUser);
         vmR3SetState(pVM, VMSTATE_SUSPENDED, VMSTATE_SAVING);
     }
     else if (rc == 2)
     {
-        rc = SSMR3LiveSave(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
-                           enmAfter, pfnProgress, pvUser, ppSSM);
+        rc = SSMR3LiveSave(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
+                           enmAfter, pfnProgress, pvProgressUser, ppSSM);
         /* (We're not subject to cancellation just yet.) */
     }
@@ -1612,49 +1617,28 @@
 
 /**
- * Save current VM state.
- *
- * Can be used for both saving the state and creating snapshots.
- *
- * When called for a VM in the Running state, the saved state is created live
- * and the VM is only suspended when the final part of the saving is preformed.
- * The VM state will not be restored to Running in this case and it's up to the
- * caller to call VMR3Resume if this is desirable.  (The rational is that the
- * caller probably wish to reconfigure the disks before resuming the VM.)
+ * Commmon worker for VMR3Save and VMR3Migrate.
  *
  * @returns VBox status code.
  *
- * @param   pVM                 The VM which state should be saved.
- * @param   pszFilename         The name of the save state file.
- * @param   fContinueAfterwards Whether continue execution afterwards or not.
- *                              When in doubt, set this to true.
- * @param   pfnProgress         Progress callback. Optional.
- * @param   pvUser              User argument for the progress callback.
- *
- * @thread      Non-EMT.
- * @vmstate     Suspended or Running
- * @vmstateto   Saving+Suspended or
- *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
- */
-VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser)
-{
-    LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} fContinueAfterwards=%RTbool pfnProgress=%p pvUser=%p\n",
-             pVM, pszFilename, pszFilename, fContinueAfterwards, pfnProgress, pvUser));
-
-    /*
-     * Validate input.
-     */
-    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
-    VM_ASSERT_OTHER_THREAD(pVM);
-    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
-    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
-    AssertPtrNullReturn(pfnProgress, VERR_INVALID_POINTER);
-
+ * @param   pVM             The VM handle.
+ * @param   pszFilename     The name of the file.  NULL if pStreamOps is used.
+ * @param   pStreamOps      The stream methods.  NULL if pszFilename is used.
+ * @param   pvStreamOpsUser The user argument to the stream methods.
+ * @param   enmAfter        What to do afterwards.
+ * @param   pfnProgress     Progress callback. Optional.
+ * @param   pvProgressUser  User argument for the progress callback.
+ *
+ * @thread  Non-EMT
+ */
+static int vmR3SaveMigrate(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                           SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
+{
     /*
      * Request the operation in EMT(0).
      */
-    SSMAFTER    enmAfter = fContinueAfterwards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY;
-    PSSMHANDLE  pSSM;
+    PSSMHANDLE pSSM;
     int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/,
-                              (PFNRT)vmR3Save, 6, pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
+                              (PFNRT)vmR3Save, 8, pVM, pszFilename, pStreamOps, pvStreamOpsUser,
+                              enmAfter, pfnProgress, pvProgressUser, &pSSM);
     if (    RT_SUCCESS(rc)
         &&  pSSM)
@@ -1696,4 +1680,53 @@
     }
 
+    return rc;
+}
+
+
+/**
+ * Save current VM state.
+ *
+ * Can be used for both saving the state and creating snapshots.
+ *
+ * When called for a VM in the Running state, the saved state is created live
+ * and the VM is only suspended when the final part of the saving is preformed.
+ * The VM state will not be restored to Running in this case and it's up to the
+ * caller to call VMR3Resume if this is desirable.  (The rational is that the
+ * caller probably wish to reconfigure the disks before resuming the VM.)
+ *
+ * @returns VBox status code.
+ *
+ * @param   pVM                 The VM which state should be saved.
+ * @param   pszFilename         The name of the save state file.
+ * @param   fContinueAfterwards Whether continue execution afterwards or not.
+ *                              When in doubt, set this to true.
+ * @param   pfnProgress         Progress callback. Optional.
+ * @param   pvUser              User argument for the progress callback.
+ *
+ * @thread      Non-EMT.
+ * @vmstate     Suspended or Running
+ * @vmstateto   Saving+Suspended or
+ *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
+ */
+VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser)
+{
+    LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} fContinueAfterwards=%RTbool pfnProgress=%p pvUser=%p\n",
+             pVM, pszFilename, pszFilename, fContinueAfterwards, pfnProgress, pvUser));
+
+    /*
+     * Validate input.
+     */
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    VM_ASSERT_OTHER_THREAD(pVM);
+    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
+    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
+    AssertPtrNullReturn(pfnProgress, VERR_INVALID_POINTER);
+
+    /*
+     * Join paths with VMR3Migrate.
+     */
+    SSMAFTER enmAfter = fContinueAfterwards ? SSMAFTER_CONTINUE : SSMAFTER_DESTROY;
+    int rc = vmR3SaveMigrate(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
+                             enmAfter, pfnProgress, pvUser);
     LogFlow(("VMR3Save: returns %Rrc\n", rc));
     return rc;
@@ -1702,19 +1735,62 @@
 
 /**
- * Loads a new VM state.
- *
- * To restore a saved state on VM startup, call this function and then
- * resume the VM instead of powering it on.
+ * Migrate the VM.
  *
  * @returns VBox status code.
+ *
+ * @param   pVM                 The VM which state should be saved.
+ * @param   pStreamOps          The stream methods.
+ * @param   pvStreamOpsUser     The user argument to the stream methods.
+ * @param   pfnProgress         Progress callback. Optional.
+ * @param   pvProgressUser      User argument for the progress callback.
+ *
+ * @thread      Non-EMT.
+ * @vmstate     Suspended or Running
+ * @vmstateto   Saving+Suspended or
+ *              RunningLS+SuspeningLS+SuspendedLS+Saving+Suspended.
+ */
+VMMR3DECL(int) VMR3Migrate(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
+{
+    LogFlow(("VMR3Migrate: pVM=%p pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n",
+             pVM, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser));
+
+    /*
+     * Validate input.
+     */
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    VM_ASSERT_OTHER_THREAD(pVM);
+    AssertPtrReturn(pStreamOps, VERR_INVALID_POINTER);
+    AssertPtrNullReturn(pfnProgress, VERR_INVALID_POINTER);
+
+    /*
+     * Join paths with VMR3Save.
+     */
+    int rc = vmR3SaveMigrate(pVM, NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser,
+                             SSMAFTER_MIGRATE, pfnProgress, pvProgressUser);
+    LogFlow(("VMR3Migrate: returns %Rrc\n", rc));
+    return rc;
+}
+
+
+
+/**
+ * EMT(0) worker for VMR3LoadFromFile and VMR3LoadFromStream.
+ *
+ * @returns VBox status code.
+ *
  * @param   pVM             The VM handle.
- * @param   pszFilename     The name of the save state file.
+ * @param   pszFilename     The name of the file.  NULL if pStreamOps is used.
+ * @param   pStreamOps      The stream methods.  NULL if pszFilename is used.
+ * @param   pvStreamOpsUser The user argument to the stream methods.
  * @param   pfnProgress     Progress callback. Optional.
  * @param   pvUser          User argument for the progress callback.
+ *
  * @thread  EMT.
  */
-static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
-{
-    LogFlow(("vmR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
+static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                  PFNVMPROGRESS pfnProgress, void *pvProgressUser)
+{
+    LogFlow(("vmR3Load: pVM=%p pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p pfnProgress=%p pvProgressUser=%p\n",
+             pVM, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser));
 
     /*
@@ -1722,5 +1798,7 @@
      */
     AssertPtr(pVM);
-    AssertPtr(pszFilename);
+    AssertPtrNull(pszFilename);
+    AssertPtrNull(pStreamOps);
+    AssertPtrNull(pfnProgress);
 
     /*
@@ -1736,5 +1814,5 @@
         return rc;
 
-    rc = SSMR3Load(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pStreamOpsUser*/, SSMAFTER_RESUME, pfnProgress, pvUser);
+    rc = SSMR3Load(pVM, pszFilename, pStreamOps, pvStreamOpsUser, SSMAFTER_RESUME, pfnProgress, pvProgressUser);
     if (RT_SUCCESS(rc))
     {
@@ -1771,7 +1849,8 @@
  * @vmstateto   Loading+Suspended
  */
-VMMR3DECL(int) VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
-{
-    LogFlow(("VMR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
+VMMR3DECL(int) VMR3LoadFromFile(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
+{
+    LogFlow(("VMR3LoadFromFile: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n",
+             pVM, pszFilename, pszFilename, pfnProgress, pvUser));
 
     /*
@@ -1785,7 +1864,45 @@
      * since there is no execution taking place when this call is allowed.
      */
-    int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/,
-                              (PFNRT)vmR3Load, 4, pVM, pszFilename, pfnProgress, pvUser);
-    LogFlow(("VMR3Load: returns %Rrc\n", rc));
+    int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3Load, 6,
+                              pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/, pfnProgress, pvUser);
+    LogFlow(("VMR3LoadFromFile: returns %Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * VMR3LoadFromFile for arbritrary file streams.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pVM             The VM handle.
+ * @param   pStreamOps      The stream methods.
+ * @param   pvStreamOpsUser The user argument to the stream methods.
+ * @param   pfnProgress     Progress callback. Optional.
+ * @param   pvProgressUser  User argument for the progress callback.
+ *
+ * @thread      Any thread.
+ * @vmstate     Created, Suspended
+ * @vmstateto   Loading+Suspended
+ */
+VMMR3DECL(int) VMR3LoadFromStream(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                  PFNVMPROGRESS pfnProgress, void *pvProgressUser)
+{
+    LogFlow(("VMR3LoadFromStream: pVM=%p pStreamOps=%p pvStreamOpsUser=%p pfnProgress=%p pvProgressUser=%p\n",
+             pVM, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser));
+
+    /*
+     * Validate input.
+     */
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    AssertPtrReturn(pStreamOps, VERR_INVALID_POINTER);
+
+    /*
+     * Forward the request to EMT(0).  No need to setup a rendezvous here
+     * since there is no execution taking place when this call is allowed.
+     */
+    int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/, (PFNRT)vmR3Load, 6,
+                              pVM, NULL /*pszFilename*/, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser);
+    LogFlow(("VMR3LoadFromStream: returns %Rrc\n", rc));
     return rc;
 }
