Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp	(revision 29389)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp	(revision 29390)
@@ -216,8 +216,288 @@
 
 
+/**
+ * Provide information about active users.
+ */
+int VBoxServiceVMInfoWriteUsers()
+{
+    int rc;
+    char szUserList[4096] = {0};
+    uint32_t cUsersInList = 0;
+
+#ifdef RT_OS_WINDOWS
+# ifndef TARGET_NT4
+    PLUID       paSessions = NULL;
+    ULONG       cSession = 0;
+    NTSTATUS    r = 0;
+
+    /* This function can report stale or orphaned interactive logon sessions
+       of already logged off users (especially in Windows 2000). */
+    r = ::LsaEnumerateLogonSessions(&cSession, &paSessions);
+    VBoxServiceVerbose(3, "Users: Found %ld users.\n", cSession);
+    if (r != STATUS_SUCCESS)
+    {
+        VBoxServiceError("LsaEnumerate failed %lu\n", LsaNtStatusToWinError(r));
+        return RTErrConvertFromWin32(LsaNtStatusToWinError(r));
+    }
+
+    PVBOXSERVICEVMINFOPROC  paProcs;
+    DWORD                   cProcs;
+    rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
+    if (RT_SUCCESS(rc))
+    {
+        for (ULONG i = 0; i < cSession; i++)
+        {
+            VBOXSERVICEVMINFOUSER UserInfo;
+            if (   VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])
+                && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs))
+            {
+                if (cUsersInList > 0)
+                    strcat(szUserList, ",");
+
+                cUsersInList++;
+
+                char *pszTemp;
+                int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp);
+                if (RT_SUCCESS(rc2))
+                {
+                    strcat(szUserList, pszTemp);
+                    RTMemFree(pszTemp);
+                }
+                else
+                    strcat(szUserList, "<string-convertion-error>");
+            }
+        }
+        VBoxServiceVMInfoWinProcessesFree(paProcs);
+    }
+
+    ::LsaFreeReturnBuffer(paSessions);
+# endif /* TARGET_NT4 */
+#elif defined(RT_OS_FREEBSD)
+        /** @todo FreeBSD: Port logged on user info retrival. */
+#elif defined(RT_OS_OS2)
+        /** @todo OS/2: Port logged on (LAN/local/whatever) user info retrival. */
+#else
+    rc = utmpname(UTMP_FILE);
+# ifdef RT_OS_SOLARIS
+    if (rc != 1)
+# else
+    if (rc != 0)
+# endif
+    {
+        VBoxServiceError("Could not set UTMP file! Error: %ld\n", errno);
+    }
+    setutent();
+    utmp *ut_user;
+    while ((ut_user = getutent()))
+    {
+        /* Make sure we don't add user names which are not
+         * part of type USER_PROCESS and don't add same users twice. */
+        if (   ut_user->ut_type == USER_PROCESS
+            && strstr(szUserList, ut_user->ut_user) == NULL)
+        {
+            /** @todo Do we really want to filter out double user names? (Same user logged in twice)
+             *  bird: If we do, then we must add checks for buffer overflows here!  */
+            /** @todo r=bird: strstr will filtering out users with similar names. For
+             *        example: smith, smithson, joesmith and bobsmith */
+            if (cUsersInList > 0)
+                strcat(szUserList, ",");
+            strcat(szUserList, ut_user->ut_user);
+            cUsersInList++;
+        }
+    }
+    endutent();
+#endif /* !RT_OS_WINDOWS */
+
+    if (cUsersInList > 0)
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList);
+    else
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
+    VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList);
+    if (   g_cVMInfoLoggedInUsers != cUsersInList
+        || g_cVMInfoLoggedInUsers == UINT32_MAX)
+    {
+        /*
+         * Update this property ONLY if there is a real change from no users to
+         * users or vice versa. The only exception is that the initialization
+         * forces an update, but only once. This ensures consistent property
+         * settings even if the VM aborted previously.
+         */
+        if (cUsersInList == 0)
+            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true");
+        else if (g_cVMInfoLoggedInUsers == 0)
+            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false");
+    }
+    g_cVMInfoLoggedInUsers = cUsersInList;
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Provide information about the guest network.
+ */
+int VBoxServiceVMInfoWriteNetwork()
+{
+    int cIfacesReport = 0;
+    char szPropPath [FILENAME_MAX];
+
+#ifdef RT_OS_WINDOWS
+    SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
+    if (sd == SOCKET_ERROR) /* Socket invalid. */
+    {
+        VBoxServiceError("Failed to get a socket: Error %d\n", WSAGetLastError());
+        return RTErrConvertFromWin32(WSAGetLastError());
+    }
+
+    INTERFACE_INFO InterfaceList[20] = {0};
+    unsigned long nBytesReturned = 0;
+    if (WSAIoctl(sd,
+                 SIO_GET_INTERFACE_LIST,
+                 0,
+                 0,
+                 &InterfaceList,
+                 sizeof(InterfaceList),
+                 &nBytesReturned,
+                 0,
+                 0) ==  SOCKET_ERROR)
+    {
+        VBoxServiceError("Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
+        return RTErrConvertFromWin32(WSAGetLastError());
+    }
+    int cIfacesSystem = nBytesReturned / sizeof(INTERFACE_INFO);
+
+    /** @todo Use GetAdaptersInfo() and GetAdapterAddresses (IPv4 + IPv6) for more information. */
+    for (int i = 0; i < cIfacesSystem; ++i)
+    {
+        sockaddr_in *pAddress;
+        u_long nFlags = 0;
+        if (InterfaceList[i].iiFlags & IFF_LOOPBACK) /* Skip loopback device. */
+            continue;
+        nFlags = InterfaceList[i].iiFlags;
+        pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress);
+        Assert(pAddress);
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        pAddress = (sockaddr_in *) & (InterfaceList[i].iiBroadcastAddress);
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        pAddress = (sockaddr_in *)&(InterfaceList[i].iiNetmask);
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, nFlags & IFF_UP ? "Up" : "Down");
+        cIfacesReport++;
+    }
+    if (sd >= 0)
+        closesocket(sd);
+#else /* !RT_OS_WINDOWS */
+    int sd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sd < 0)
+    {
+        VBoxServiceError("Failed to get a socket: Error %d\n", errno);
+        return RTErrConvertFromErrno(errno);
+    }
+
+    ifconf ifcfg;
+    char buffer[1024] = {0};
+    ifcfg.ifc_len = sizeof(buffer);
+    ifcfg.ifc_buf = buffer;
+    if (ioctl(sd, SIOCGIFCONF, &ifcfg) < 0)
+    {
+        VBoxServiceError("Failed to ioctl(SIOCGIFCONF) on socket: Error %d\n", errno);
+        return RTErrConvertFromErrno(errno);
+    }
+
+    ifreq* ifrequest = ifcfg.ifc_req;
+    int cIfacesSystem = ifcfg.ifc_len / sizeof(ifreq);
+
+    for (int i = 0; i < cIfacesSystem; ++i)
+    {
+        sockaddr_in *pAddress;
+        if (ioctl(sd, SIOCGIFFLAGS, &ifrequest[i]) < 0)
+        {
+            VBoxServiceError("Failed to ioctl(SIOCGIFFLAGS) on socket: Error %d\n", errno);
+            close(sd);
+            return RTErrConvertFromErrno(errno);
+        }
+        if (ifrequest[i].ifr_flags & IFF_LOOPBACK) /* Skip the loopback device. */
+            continue;
+
+        bool fIfUp = !!(ifrequest[i].ifr_flags & IFF_UP);
+        pAddress = ((sockaddr_in *)&ifrequest[i].ifr_addr);
+        Assert(pAddress);
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        if (ioctl(sd, SIOCGIFBRDADDR, &ifrequest[i]) < 0)
+        {
+            VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
+            close(sd);
+            return RTErrConvertFromErrno(errno);
+        }
+        pAddress = (sockaddr_in *)&ifrequest[i].ifr_broadaddr;
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        if (ioctl(sd, SIOCGIFNETMASK, &ifrequest[i]) < 0)
+        {
+            VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
+            close(sd);
+            return RTErrConvertFromErrno(errno);
+        }
+ #if defined(RT_OS_FREEBSD) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
+        pAddress = (sockaddr_in *)&ifrequest[i].ifr_addr;
+ #else
+        pAddress = (sockaddr_in *)&ifrequest[i].ifr_netmask;
+ #endif
+
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
+
+        if (ioctl(sd, SIOCGIFHWADDR, &ifrequest[i]) < 0)
+        {
+            VBoxServiceError("Failed to ioctl(SIOCGIFHWADDR) on socket: Error %d\n", errno);
+            close(sd);
+            return RTErrConvertFromErrno(errno);
+        }
+
+        char szMac[32];
+        char *pu8Mac = ifrequest[i].ifr_hwaddr.sa_data;
+        RTStrPrintf(szMac, sizeof(szMac), "%02x:%02x:%02x:%02x:%02x:%02x",
+                    pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3],  pu8Mac[4], pu8Mac[5]);
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
+
+        RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
+        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, fIfUp ? "Up" : "Down");
+        cIfacesReport++;
+    }
+
+    close(sd);
+
+#endif /* !RT_OS_WINDOWS */
+
+    /*
+     * This property is a beacon which is _always_ written, even if the network configuration
+     * does not change. If this property is missing, the host assumes that all other GuestInfo
+     * properties are no longer valid.
+     */
+    VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count", "%d",
+                               cIfacesReport);
+
+    /** @todo r=bird: if cIfacesReport decreased compared to the previous run, zap
+     *        the stale data.  This can probably be encorporated into the cache.  */
+
+    return VINF_SUCCESS;
+}
+
+
 /** @copydoc VBOXSERVICE::pfnWorker */
 DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown)
 {
-    int rc = VINF_SUCCESS;
+    int rc;
 
     /*
@@ -242,252 +522,13 @@
      * Now enter the loop retrieving runtime data continuously.
      */
-    unsigned cErrors = 0;
     for (;;)
     {
-/** @todo r=bird: split this code up into functions!! */
-        /* Enumerate logged in users. */
-        uint32_t cUsersInList = 0;
-        char szUserList[4096] = {0};
-
-#ifdef RT_OS_WINDOWS
-# ifndef TARGET_NT4
-        PLUID       paSessions = NULL;
-        ULONG       cSession = 0;
-        NTSTATUS    r = 0;
-
-        /* This function can report stale or orphaned interactive logon sessions
-           of already logged off users (especially in Windows 2000). */
-        r = ::LsaEnumerateLogonSessions(&cSession, &paSessions);
-        VBoxServiceVerbose(3, "Users: Found %ld users.\n", cSession);
-        if (r != STATUS_SUCCESS)
-        {
-            VBoxServiceError("LsaEnumerate failed %lu\n", LsaNtStatusToWinError(r));
-            return 1;
-        }
-
-        PVBOXSERVICEVMINFOPROC  paProcs;
-        DWORD                   cProcs;
-        rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
-        if (RT_SUCCESS(rc))
-        {
-            for (ULONG i = 0; i < cSession; i++)
-            {
-                VBOXSERVICEVMINFOUSER UserInfo;
-                if (   VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i])
-                    && VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs))
-                {
-                    if (cUsersInList > 0)
-                        strcat(szUserList, ",");
-
-                    cUsersInList++;
-
-                    char *pszTemp;
-                    int rc2 = RTUtf16ToUtf8(UserInfo.wszUser, &pszTemp);
-                    if (RT_SUCCESS(rc2))
-                    {
-                        strcat(szUserList, pszTemp);
-                        RTMemFree(pszTemp);
-                    }
-                    else
-                        strcat(szUserList, "<string-convertion-error>");
-                }
-            }
-            VBoxServiceVMInfoWinProcessesFree(paProcs);
-        }
-
-        ::LsaFreeReturnBuffer(paSessions);
-# endif /* TARGET_NT4 */
-#elif defined(RT_OS_FREEBSD)
-        /** @todo FreeBSD: Port logged on user info retrival. */
-#elif defined(RT_OS_OS2)
-        /** @todo OS/2: Port logged on (LAN/local/whatever) user info retrival. */
-#else
-        rc = utmpname(UTMP_FILE);
-# ifdef RT_OS_SOLARIS
-        if (rc != 1)
-# else
-        if (rc != 0)
-# endif
-        {
-            VBoxServiceError("Could not set UTMP file! Error: %ld\n", errno);
-        }
-        setutent();
-        utmp *ut_user;
-        while ((ut_user = getutent()))
-        {
-            /* Make sure we don't add user names which are not
-             * part of type USER_PROCESS and don't add same users twice. */
-            if (   ut_user->ut_type == USER_PROCESS
-                && strstr(szUserList, ut_user->ut_user) == NULL)
-            {
-                /** @todo Do we really want to filter out double user names? (Same user logged in twice)
-                 *  bird: If we do, then we must add checks for buffer overflows here!  */
-                /** @todo r=bird: strstr will filtering out users with similar names. For
-                 *        example: smith, smithson, joesmith and bobsmith */
-                if (cUsersInList > 0)
-                    strcat(szUserList, ",");
-                strcat(szUserList, ut_user->ut_user);
-                cUsersInList++;
-            }
-        }
-        endutent();
-#endif /* !RT_OS_WINDOWS */
-
-        if (cUsersInList > 0)
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", szUserList);
-        else
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
-        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList);
-        if (   g_cVMInfoLoggedInUsers != cUsersInList
-            || g_cVMInfoLoggedInUsers == UINT32_MAX)
-        {
-            /*
-             * Update this property ONLY if there is a real change from no users to
-             * users or vice versa. The only exception is that the initialization
-             * forces an update, but only once. This ensures consistent property
-             * settings even if the VM aborted previously.
-             */
-            if (cUsersInList == 0)
-                VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "true");
-            else if (g_cVMInfoLoggedInUsers == 0)
-                VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers", "false");
-        }
-        g_cVMInfoLoggedInUsers = cUsersInList;
-
-        /*
-         * Get network configuration.
-         */
-        /** @todo Throw this code into a separate function/module? */
-       int cInterfaces = 0;
-#ifdef RT_OS_WINDOWS
-        SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
-        if (sd == SOCKET_ERROR) /* Socket invalid. */
-        {
-            VBoxServiceError("Failed to get a socket: Error %d\n", WSAGetLastError());
-            return -1;
-        }
-
-        INTERFACE_INFO InterfaceList[20] = {0};
-        unsigned long nBytesReturned = 0;
-        if (WSAIoctl(sd,
-                     SIO_GET_INTERFACE_LIST,
-                     0,
-                     0,
-                     &InterfaceList,
-                     sizeof(InterfaceList),
-                     &nBytesReturned,
-                     0,
-                     0) ==  SOCKET_ERROR)
-        {
-            VBoxServiceError("Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
-            return -1;
-        }
-        cInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
-#else
-        int sd = socket(AF_INET, SOCK_DGRAM, 0);
-        if (sd < 0) /* Socket invalid. */
-        {
-            VBoxServiceError("Failed to get a socket: Error %d\n", errno);
-            return -1;
-        }
-
-        ifconf ifcfg;
-        char buffer[1024] = {0};
-        ifcfg.ifc_len = sizeof(buffer);
-        ifcfg.ifc_buf = buffer;
-        if (ioctl(sd, SIOCGIFCONF, &ifcfg) < 0)
-        {
-            VBoxServiceError("Failed to ioctl(SIOCGIFCONF) on socket: Error %d\n", errno);
-            return -1;
-        }
-
-        ifreq* ifrequest = ifcfg.ifc_req;
-        ifreq *ifreqitem = NULL;
-        cInterfaces = ifcfg.ifc_len / sizeof(ifreq);
-#endif
-        char szPropPath [FILENAME_MAX];
-        int iCurIface = 0;
-
-        /** @todo Use GetAdaptersInfo() and GetAdapterAddresses (IPv4 + IPv6) for more information. */
-        for (int i = 0; i < cInterfaces; ++i)
-        {
-            sockaddr_in *pAddress;
-            u_long nFlags = 0;
-#ifdef RT_OS_WINDOWS
-            if (InterfaceList[i].iiFlags & IFF_LOOPBACK) /* Skip loopback device. */
-                continue;
-            nFlags = InterfaceList[i].iiFlags;
-            pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress);
-#else
-            if (ioctl(sd, SIOCGIFFLAGS, &ifrequest[i]) < 0)
-            {
-                VBoxServiceError("Failed to ioctl(SIOCGIFFLAGS) on socket: Error %d\n", errno);
-                return -1;
-            }
-            if (ifrequest[i].ifr_flags & IFF_LOOPBACK) /* Skip loopback device. */
-                continue;
-            nFlags = ifrequest[i].ifr_flags;
-            pAddress = ((sockaddr_in *)&ifrequest[i].ifr_addr);
-#endif
-            Assert(pAddress);
-            RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", iCurIface);
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
-
-#ifdef RT_OS_WINDOWS
-            pAddress = (sockaddr_in *) & (InterfaceList[i].iiBroadcastAddress);
-#else
-            if (ioctl(sd, SIOCGIFBRDADDR, &ifrequest[i]) < 0)
-            {
-                VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
-                return -1;
-            }
-            pAddress = (sockaddr_in *)&ifrequest[i].ifr_broadaddr;
-#endif
-            RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", iCurIface);
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
-
-#ifdef RT_OS_WINDOWS
-            pAddress = (sockaddr_in *)&(InterfaceList[i].iiNetmask);
-#else
-            if (ioctl(sd, SIOCGIFNETMASK, &ifrequest[i]) < 0)
-            {
-                VBoxServiceError("Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
-                return -1;
-            }
- #if defined(RT_OS_FREEBSD) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
-            pAddress = (sockaddr_in *)&ifrequest[i].ifr_addr;
- #else
-            pAddress = (sockaddr_in *)&ifrequest[i].ifr_netmask;
- #endif
-
-#endif
-            RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", iCurIface);
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
-
-            RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", iCurIface);
-            VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath,
-                                       nFlags & IFF_UP ? "Up" : "Down");
-            iCurIface++;
-        }
-        if (sd >= 0)
-#ifdef RT_OS_WINDOWS
-            closesocket(sd);
-#else
-            close(sd);
-#endif
-
-        /*
-         * This property is a beacon which is _always_ written, even if the network configuration
-         * does not change. If this property is missing, the host assumes that all other GuestInfo
-         * properties are no longer valid.
-         *
-         * cInterfaces also counts in local loopback, but we don't want to report that.
-         */
-        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count", "%d",
-                                   cInterfaces > 1 ? cInterfaces-1 : 0);
-
-        /** @todo r=bird: if cInterfaces decreased compared to the previous run, zap
-         *        the stale data.  This can probably be encorporated into the cache.  */
-
+        rc = VBoxServiceVMInfoWriteUsers();
+        if (RT_FAILURE(rc))
+            break;
+
+        rc = VBoxServiceVMInfoWriteNetwork();
+        if (RT_FAILURE(rc))
+            break;
 
         /*
