Index: /trunk/include/VBox/ssm.h
===================================================================
--- /trunk/include/VBox/ssm.h	(revision 23594)
+++ /trunk/include/VBox/ssm.h	(revision 23595)
@@ -730,6 +730,6 @@
 VMMR3DECL(int)          SSMR3DeregisterExternal(PVM pVM, const char *pszName);
 VMMR3DECL(int)          SSMR3Save(PVM pVM, const char *pszFilename, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
-VMMR3_INT_DECL(int)     SSMR3LiveToFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
-                                        PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM);
+VMMR3_INT_DECL(int)     SSMR3LiveSave(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
+                                      SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM);
 VMMR3_INT_DECL(int)     SSMR3LiveDoStep1(PSSMHANDLE pSSM);
 VMMR3_INT_DECL(int)     SSMR3LiveDoStep2(PSSMHANDLE pSSM);
Index: /trunk/src/VBox/VMM/SSM.cpp
===================================================================
--- /trunk/src/VBox/VMM/SSM.cpp	(revision 23594)
+++ /trunk/src/VBox/VMM/SSM.cpp	(revision 23595)
@@ -63,5 +63,5 @@
  * The live saving sequence is something like this:
  *
- *      -# SSMR3LiveToFile is called on EMT0.  It returns a saved state
+ *      -# SSMR3LiveSave is called on EMT0.  It returns a saved state
  *         handle.
  *      -# SSMR3LiveDoStep1 is called on a non-EMT.  This will save the major
@@ -3592,11 +3592,9 @@
  * Closes the SSM handle.
  *
- * This must always be called on a handled returned by SSMR3LiveToFile or
- * SSMR3LiveToRemote.
+ * This must always be called on a handled returned by SSMR3LiveSave.
  *
  * @returns VBox status.
  *
- * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
- *                          SSMR3LiveToRemote.
+ * @param   pSSM            The SSM handle returned by SSMR3LiveSave.
  *
  * @thread  EMT(0).
@@ -4004,5 +4002,5 @@
 
 /**
- * Common worker for SSMR3Save and SSMR3Migrate.
+ * Common worker for SSMR3Save and SSMR3LiveSave.
  *
  * @returns VBox status code (no need to check pSSM->rc).
@@ -4040,6 +4038,5 @@
  * @returns VBox status.
  *
- * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
- *                          SSMR3LiveToRemote.
+ * @param   pSSM            The SSM handle returned by SSMR3LiveSave.
  *
  * @thread  Non-EMT thread. Will involve the EMT at the end of the operation.
@@ -4121,5 +4118,9 @@
  * @returns VBox status code.
  * @param   pVM                 The VM handle.
- * @param   pszFilename         The name of the 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         The progress callback.
@@ -4129,6 +4130,6 @@
  *                              RTMemFree after closing the stream.
  */
-static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
-                                 PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
+static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
 {
     PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
@@ -4156,5 +4157,9 @@
     pSSM->u.Write.offDataBuffer = 0;
 
-    int rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
+    int rc;
+    if (pStreamOps)
+        rc = ssmR3StrmInit(&pSSM->Strm, pStreamOps, pvStreamOpsUser, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
+    else
+        rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename,             true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
     if (RT_FAILURE(rc))
     {
@@ -4202,5 +4207,6 @@
      */
     PSSMHANDLE pSSM;
-    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
+    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
+                                   enmAfter, pfnProgress, pvUser, &pSSM);
     if (RT_FAILURE(rc))
         return rc;
@@ -4422,6 +4428,5 @@
  * @returns VBox status.
  *
- * @param   pSSM            The SSM handle returned by SSMR3LiveToFile or
- *                          SSMR3LiveToRemote.
+ * @param   pSSM            The SSM handle returned by SSMR3LiveSave.
  *
  * @thread  Non-EMT thread. Will involve the EMT at the end of the operation.
@@ -4607,5 +4612,5 @@
 
 /**
- * Start saving the live state to a file.
+ * Start saving the live state.
  *
  * Call SSMR3LiveDoStep1, SSMR3LiveDoStep2 and finally SSMR3LiveDone on success.
@@ -4624,8 +4629,9 @@
  * @thread  EMT0
  */
-VMMR3_INT_DECL(int) SSMR3LiveToFile(PVM pVM, const char *pszFilename, SSMAFTER enmAfter,
-                                    PFNVMPROGRESS pfnProgress, void *pvUser, PSSMHANDLE *ppSSM)
-{
-    LogFlow(("SSMR3LiveToFile: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
+VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+                                  SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
+{
+    LogFlow(("SSMR3LiveSave: pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
+             pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
     VM_ASSERT_EMT0(pVM);
 
@@ -4637,4 +4643,16 @@
                     ("%d\n", enmAfter),
                     VERR_INVALID_PARAMETER);
+    AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
+    if (pStreamOps)
+    {
+        AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
+        AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
+        AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
+        AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
+        AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
+        AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
+        AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
+        AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
+    }
 
     /*
@@ -4645,5 +4663,6 @@
      */
     PSSMHANDLE pSSM;
-    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, &pSSM);
+    int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
+                                   enmAfter, pfnProgress, pvProgressUser, &pSSM);
     if (RT_FAILURE(rc))
         return rc;
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 23594)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 23595)
@@ -1601,5 +1601,6 @@
     else if (rc == 2)
     {
-        rc = SSMR3LiveToFile(pVM, pszFilename, enmAfter, pfnProgress, pvUser, ppSSM);
+        rc = SSMR3LiveSave(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOpsUser*/,
+                           enmAfter, pfnProgress, pvUser, ppSSM);
         /* (We're not subject to cancellation just yet.) */
     }
