Index: /trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp	(revision 4672)
+++ /trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp	(revision 4673)
@@ -457,6 +457,25 @@
         for (uint32_t i=pDevExt->MemBalloon.cBalloons;i<u32BalloonSize;i++)
         {
+#ifndef TARGET_NT4
+            /*
+             * Use MmAllocatePagesForMdl to specify the range of physical addresses we wish to use.
+             */
+            PHYSICAL_ADDRESS Zero;
+            PHYSICAL_ADDRESS HighAddr;
+            Zero.QuadPart = 0;
+            HighAddr.QuadPart = _4G - 1;
+            PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE);
+            if (pMdl)
+            {
+                if (MmGetMdlByteCount(pMdl) < VMMDEV_MEMORY_BALLOON_CHUNK_SIZE)
+                {
+                    MmFreePagesFromMdl(pMdl);
+                    ExFreePool(pMdl);
+                    rc = VERR_NO_MEMORY;
+                    goto end;
+                }
+            }
+#else
             PVOID pvBalloon;
-
             pvBalloon = ExAllocatePoolWithTag(PagedPool, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, 'MBAL');
             if (!pvBalloon)
@@ -482,4 +501,5 @@
                 __except(EXCEPTION_EXECUTE_HANDLER) 
                 {
+                    Log(("MmProbeAndLockPages failed!\n"));
                     rc = VERR_NO_MEMORY;
                     IoFreeMdl (pMdl);
@@ -488,4 +508,5 @@
                 }
             }
+#endif
 
             PPFN_NUMBER pPageDesc = MmGetMdlPfnArray(pMdl);
@@ -505,11 +526,20 @@
                          "rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
 
+#ifndef TARGET_NT4
+                MmFreePagesFromMdl(pMdl);
+                ExFreePool(pMdl);
+#else
                 IoFreeMdl (pMdl);
                 ExFreePoolWithTag(pvBalloon, 'MBAL');
+#endif
                 goto end;
             }
             else
             {
-                dprintf(("VBoxGuest::VBoxGuestSetBalloonSize added 1 MB chunk at %x\n", pvBalloon));
+#ifndef TARGET_NT4
+                dprintf(("VBoxGuest::VBoxGuestSetBalloonSize %d MB added chunk at %x\n", i, pMdl));
+#else
+                dprintf(("VBoxGuest::VBoxGuestSetBalloonSize %d MB added chunk at %x\n", i, pvBalloon));
+#endif
                 pDevExt->MemBalloon.paMdlMemBalloon[i] = pMdl;
                 pDevExt->MemBalloon.cBalloons++;
@@ -522,33 +552,43 @@
         for (uint32_t i=pDevExt->MemBalloon.cBalloons-1;i>=u32BalloonSize;i--)
         {
-            PMDL  pMdl      = pDevExt->MemBalloon.paMdlMemBalloon[i];
-            PVOID pvBalloon = MmGetMdlVirtualAddress(pMdl);
-
-            PPFN_NUMBER pPageDesc = MmGetMdlPfnArray(pMdl);
-
-            /* Copy manually as RTGCPHYS is always 64 bits */
-            for (uint32_t j=0;j<VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;j++)
-                req->aPhysPage[j] = pPageDesc[j];
-
-            req->header.size = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
-            req->cPages      = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
-            req->fInflate    = false;
-
-            rc = VbglGRPerform(&req->header);
-            if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
-            {
-                AssertMsgFailed(("VBoxGuest::VBoxGuestSetBalloonSize: error issuing request to VMMDev! rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
-                /* ignore error and just continue; this should never fail */
-            }
-
-            dprintf(("VBoxGuest::VBoxGuestSetBalloonSize free 1 MB chunk at %x\n", pvBalloon));
-
-            /* Free the ballooned memory */
-            MmUnlockPages (pMdl);
-            IoFreeMdl (pMdl);
-            ExFreePoolWithTag(pvBalloon, 'MBAL');
-
-            pDevExt->MemBalloon.paMdlMemBalloon[i] = NULL;
-            pDevExt->MemBalloon.cBalloons--;
+            PMDL  pMdl = pDevExt->MemBalloon.paMdlMemBalloon[i];
+
+            Assert(pMdl);
+            if (pMdl)
+            {
+                PVOID pvBalloon = MmGetMdlVirtualAddress(pMdl);
+
+                PPFN_NUMBER pPageDesc = MmGetMdlPfnArray(pMdl);
+
+                /* Copy manually as RTGCPHYS is always 64 bits */
+                for (uint32_t j=0;j<VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;j++)
+                    req->aPhysPage[j] = pPageDesc[j];
+
+                req->header.size = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]);
+                req->cPages      = VMMDEV_MEMORY_BALLOON_CHUNK_PAGES;
+                req->fInflate    = false;
+
+                rc = VbglGRPerform(&req->header);
+                if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
+                {
+                    AssertMsgFailed(("VBoxGuest::VBoxGuestSetBalloonSize: error issuing request to VMMDev! rc = %d, VMMDev rc = %Vrc\n", rc, req->header.rc));
+                    break;
+                }
+
+                dprintf(("VBoxGuest::VBoxGuestSetBalloonSize %d MB free chunk at %x\n", i, pvBalloon));
+
+                /* Free the ballooned memory */
+#ifndef TARGET_NT4
+                MmFreePagesFromMdl(pMdl);
+                ExFreePool(pMdl);
+#else
+                MmUnlockPages (pMdl);
+                IoFreeMdl (pMdl);
+                ExFreePoolWithTag(pvBalloon, 'MBAL');
+#endif
+
+                pDevExt->MemBalloon.paMdlMemBalloon[i] = NULL;
+                pDevExt->MemBalloon.cBalloons--;
+            }
         }
     }
@@ -593,4 +633,8 @@
 
             rc = VBoxGuestSetBalloonSize(pDevExt, req->u32BalloonSize);
+            /* ignore out of memory failures */
+            if (rc == VERR_NO_MEMORY)
+                rc = VINF_SUCCESS;
+
             if (pMemBalloonSize)
                 *pMemBalloonSize = pDevExt->MemBalloon.cBalloons;
