Index: trunk/src/VBox/Devices/Audio/DrvAudio.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 88210)
+++ trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 88213)
@@ -3464,6 +3464,96 @@
 }
 
+
+/*********************************************************************************************************************************
+*   PDMIBASE interface implementation.                                                                                           *
+*********************************************************************************************************************************/
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) drvAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+    LogFlowFunc(("pInterface=%p, pszIID=%s\n", pInterface, pszIID));
+
+    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
+    PDRVAUDIO  pThis   = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
+
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOCONNECTOR, &pThis->IAudioConnector);
+
+    return NULL;
+}
+
+
+/*********************************************************************************************************************************
+*   PDMDRVREG interface implementation.                                                                                          *
+*********************************************************************************************************************************/
+
+/**
+ * Power Off notification.
+ *
+ * @param   pDrvIns     The driver instance data.
+ */
+static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns)
+{
+    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
+
+    LogFlowFuncEnter();
+
+    if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
+        return;
+
+    /* Just destroy the host stream on the backend side.
+     * The rest will either be destructed by the device emulation or
+     * in drvAudioDestruct(). */
+    PPDMAUDIOSTREAM pStream;
+    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
+    {
+        drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+        drvAudioStreamDestroyInternalBackend(pThis, pStream);
+    }
+
+    /*
+     * Last call for the driver below us.
+     * Let it know that we reached end of life.
+     */
+    if (pThis->pHostDrvAudio->pfnShutdown)
+        pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
+
+    pThis->pHostDrvAudio = NULL;
+
+    LogFlowFuncLeave();
+}
+
+
+/**
+ * Detach notification.
+ *
+ * @param   pDrvIns     The driver instance data.
+ * @param   fFlags      Detach flags.
+ */
+static DECLCALLBACK(void) drvAudioDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+    RT_NOREF(fFlags);
+
+    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
+    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
+
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
+    pThis->pHostDrvAudio = NULL;
+
+    LogFunc(("%s\n", pThis->szName));
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    AssertRC(rc2);
+}
+
+
 /**
  * Does the actual backend driver attaching and queries the backend's interface.
+ *
+ * This is a worker for both drvAudioAttach and drvAudioConstruct.
  *
  * @return VBox status code.
@@ -3505,58 +3595,151 @@
 
 
-/********************************************************************/
-
-/**
- * @interface_method_impl{PDMIBASE,pfnQueryInterface}
- */
-static DECLCALLBACK(void *) drvAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
-{
-    LogFlowFunc(("pInterface=%p, pszIID=%s\n", pInterface, pszIID));
-
-    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
-    PDRVAUDIO  pThis   = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
-
-    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
-    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOCONNECTOR, &pThis->IAudioConnector);
-
-    return NULL;
-}
-
-/**
- * Power Off notification.
+/**
+ * Attach notification.
  *
  * @param   pDrvIns     The driver instance data.
- */
-static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns)
-{
+ * @param   fFlags      Attach flags.
+ */
+static DECLCALLBACK(int) drvAudioAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+    RT_NOREF(fFlags);
+
+    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
     PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
 
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
+    LogFunc(("%s\n", pThis->szName));
+
+    int rc = drvAudioDoAttachInternal(pThis, fFlags);
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
+    return rc;
+}
+
+
+/**
+ * Resume notification.
+ *
+ * @param   pDrvIns     The driver instance data.
+ */
+static DECLCALLBACK(void) drvAudioResume(PPDMDRVINS pDrvIns)
+{
+    drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_RESUME);
+}
+
+
+/**
+ * Suspend notification.
+ *
+ * @param   pDrvIns     The driver instance data.
+ */
+static DECLCALLBACK(void) drvAudioSuspend(PPDMDRVINS pDrvIns)
+{
+    drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_PAUSE);
+}
+
+
+/**
+ * Destructs an audio driver instance.
+ *
+ * @copydoc FNPDMDRVDESTRUCT
+ */
+static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns)
+{
+    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
+    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
+
     LogFlowFuncEnter();
 
-    if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
-        return;
-
-    /* Just destroy the host stream on the backend side.
-     * The rest will either be destructed by the device emulation or
-     * in drvAudioDestruct(). */
-    PPDMAUDIOSTREAM pStream;
-    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
-    {
-        drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
-        drvAudioStreamDestroyInternalBackend(pThis, pStream);
+    int rc2;
+
+    if (RTCritSectIsInitialized(&pThis->CritSect))
+    {
+        rc2 = RTCritSectEnter(&pThis->CritSect);
+        AssertRC(rc2);
     }
 
     /*
-     * Last call for the driver below us.
-     * Let it know that we reached end of life.
+     * Note: No calls here to the driver below us anymore,
+     *       as PDM already has destroyed it.
+     *       If you need to call something from the host driver,
+     *       do this in drvAudioPowerOff() instead.
      */
-    if (pThis->pHostDrvAudio->pfnShutdown)
-        pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
-
+
+    /* Thus, NULL the pointer to the host audio driver first,
+     * so that routines like drvAudioStreamDestroyInternal() don't call the driver(s) below us anymore. */
     pThis->pHostDrvAudio = NULL;
 
+    PPDMAUDIOSTREAM pStream, pStreamNext;
+    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry)
+    {
+        rc2 = drvAudioStreamUninitInternal(pThis, pStream);
+        if (RT_SUCCESS(rc2))
+        {
+            RTListNodeRemove(&pStream->ListEntry);
+
+            drvAudioStreamFree(pStream);
+            pStream = NULL;
+        }
+    }
+
+    /* Sanity. */
+    Assert(RTListIsEmpty(&pThis->lstStreams));
+
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    /*
+     * Destroy callbacks, if any.
+     */
+    PPDMAUDIOCBRECORD pCB, pCBNext;
+    RTListForEachSafe(&pThis->In.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)
+        drvAudioCallbackDestroy(pCB);
+
+    RTListForEachSafe(&pThis->Out.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)
+        drvAudioCallbackDestroy(pCB);
+#endif
+
+    if (pThis->pvScratchBuf)
+    {
+        Assert(pThis->cbScratchBuf);
+
+        RTMemFree(pThis->pvScratchBuf);
+        pThis->pvScratchBuf = NULL;
+    }
+
+    if (RTCritSectIsInitialized(&pThis->CritSect))
+    {
+        rc2 = RTCritSectLeave(&pThis->CritSect);
+        AssertRC(rc2);
+
+        rc2 = RTCritSectDelete(&pThis->CritSect);
+        AssertRC(rc2);
+    }
+
+#ifdef VBOX_WITH_STATISTICS
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsActive);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsCreated);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesRead);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesWritten);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedIn);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedOut);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostIn);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostOut);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesOut);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesIn);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesRead);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesWritten);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayIn);
+    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayOut);
+#endif
+
     LogFlowFuncLeave();
 }
 
+
 /**
  * Constructs an audio driver instance.
@@ -3566,9 +3749,11 @@
 static DECLCALLBACK(int) drvAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
 {
+    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
+    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
     LogFlowFunc(("pDrvIns=%#p, pCfgHandle=%#p, fFlags=%x\n", pDrvIns, pCfg, fFlags));
 
-    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
-    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
-
+    /*
+     * Basic instance init.
+     */
     RTListInit(&pThis->lstStreams);
 #ifdef VBOX_WITH_AUDIO_CALLBACKS
@@ -3577,7 +3762,4 @@
 #endif
 
-    /*
-     * Init the static parts.
-     */
     pThis->pDrvIns                              = pDrvIns;
     /* IBase. */
@@ -3642,4 +3824,6 @@
     }
 
+    /** @todo r=bird: you're overwriting rc here. sigh.  Just return immediately on
+     *        failure, don't try make it to the end of the function! GRRR! */
     rc = drvAudioDoAttachInternal(pThis, fFlags);
     if (RT_FAILURE(rc))
@@ -3652,171 +3836,4 @@
     LogFlowFuncLeaveRC(rc);
     return rc;
-}
-
-/**
- * Destructs an audio driver instance.
- *
- * @copydoc FNPDMDRVDESTRUCT
- */
-static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns)
-{
-    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
-    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
-
-    LogFlowFuncEnter();
-
-    int rc2;
-
-    if (RTCritSectIsInitialized(&pThis->CritSect))
-    {
-        rc2 = RTCritSectEnter(&pThis->CritSect);
-        AssertRC(rc2);
-    }
-
-    /*
-     * Note: No calls here to the driver below us anymore,
-     *       as PDM already has destroyed it.
-     *       If you need to call something from the host driver,
-     *       do this in drvAudioPowerOff() instead.
-     */
-
-    /* Thus, NULL the pointer to the host audio driver first,
-     * so that routines like drvAudioStreamDestroyInternal() don't call the driver(s) below us anymore. */
-    pThis->pHostDrvAudio = NULL;
-
-    PPDMAUDIOSTREAM pStream, pStreamNext;
-    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry)
-    {
-        rc2 = drvAudioStreamUninitInternal(pThis, pStream);
-        if (RT_SUCCESS(rc2))
-        {
-            RTListNodeRemove(&pStream->ListEntry);
-
-            drvAudioStreamFree(pStream);
-            pStream = NULL;
-        }
-    }
-
-    /* Sanity. */
-    Assert(RTListIsEmpty(&pThis->lstStreams));
-
-#ifdef VBOX_WITH_AUDIO_CALLBACKS
-    /*
-     * Destroy callbacks, if any.
-     */
-    PPDMAUDIOCBRECORD pCB, pCBNext;
-    RTListForEachSafe(&pThis->In.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)
-        drvAudioCallbackDestroy(pCB);
-
-    RTListForEachSafe(&pThis->Out.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)
-        drvAudioCallbackDestroy(pCB);
-#endif
-
-    if (pThis->pvScratchBuf)
-    {
-        Assert(pThis->cbScratchBuf);
-
-        RTMemFree(pThis->pvScratchBuf);
-        pThis->pvScratchBuf = NULL;
-    }
-
-    if (RTCritSectIsInitialized(&pThis->CritSect))
-    {
-        rc2 = RTCritSectLeave(&pThis->CritSect);
-        AssertRC(rc2);
-
-        rc2 = RTCritSectDelete(&pThis->CritSect);
-        AssertRC(rc2);
-    }
-
-#ifdef VBOX_WITH_STATISTICS
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsActive);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsCreated);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesRead);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesWritten);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedIn);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedOut);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostIn);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostOut);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesOut);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesIn);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesRead);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesWritten);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayIn);
-    PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayOut);
-#endif
-
-    LogFlowFuncLeave();
-}
-
-/**
- * Suspend notification.
- *
- * @param   pDrvIns     The driver instance data.
- */
-static DECLCALLBACK(void) drvAudioSuspend(PPDMDRVINS pDrvIns)
-{
-    drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_PAUSE);
-}
-
-/**
- * Resume notification.
- *
- * @param   pDrvIns     The driver instance data.
- */
-static DECLCALLBACK(void) drvAudioResume(PPDMDRVINS pDrvIns)
-{
-    drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_RESUME);
-}
-
-/**
- * Attach notification.
- *
- * @param   pDrvIns     The driver instance data.
- * @param   fFlags      Attach flags.
- */
-static DECLCALLBACK(int) drvAudioAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
-{
-    RT_NOREF(fFlags);
-
-    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
-    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
-
-    int rc2 = RTCritSectEnter(&pThis->CritSect);
-    AssertRC(rc2);
-
-    LogFunc(("%s\n", pThis->szName));
-
-    int rc = drvAudioDoAttachInternal(pThis, fFlags);
-
-    rc2 = RTCritSectLeave(&pThis->CritSect);
-    if (RT_SUCCESS(rc))
-        rc = rc2;
-
-    return rc;
-}
-
-/**
- * Detach notification.
- *
- * @param   pDrvIns     The driver instance data.
- * @param   fFlags      Detach flags.
- */
-static DECLCALLBACK(void) drvAudioDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
-{
-    RT_NOREF(fFlags);
-
-    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
-    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
-
-    int rc2 = RTCritSectEnter(&pThis->CritSect);
-    AssertRC(rc2);
-
-    pThis->pHostDrvAudio = NULL;
-
-    LogFunc(("%s\n", pThis->szName));
-
-    rc2 = RTCritSectLeave(&pThis->CritSect);
-    AssertRC(rc2);
 }
 
