Index: trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp	(revision 52403)
+++ trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp	(revision 52405)
@@ -108,4 +108,6 @@
     /** The image timestamp. */
     uint32_t                uTimestamp;
+    /** The number of imports.  UINT32_MAX if not determined. */
+    uint32_t                cImports;
     /** Set if the image is 64-bit, clear if 32-bit. */
     bool                    f64Bit;
@@ -619,7 +621,9 @@
          pImps++)
     {
+        AssertReturn(pImps->Name < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
         const char *pszModName = PE_RVA2TYPE(pvBitsR, pImps->Name, const char *);
-        PIMAGE_THUNK_DATA32 pFirstThunk;    /* update this. */
-        PIMAGE_THUNK_DATA32 pThunk;         /* read from this. */
+        AssertReturn(pImps->FirstThunk < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
+        AssertReturn(pImps->u.OriginalFirstThunk < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
+
         Log3(("RTLdrPE: Import descriptor: %s\n", pszModName));
         Log4(("RTLdrPE:   OriginalFirstThunk = %#RX32\n"
@@ -634,8 +638,8 @@
          * Walk the thunks table(s).
          */
-        pFirstThunk = PE_RVA2TYPE(pvBitsW, pImps->FirstThunk, PIMAGE_THUNK_DATA32);
-        pThunk = pImps->u.OriginalFirstThunk == 0
-            ? PE_RVA2TYPE(pvBitsR, pImps->FirstThunk, PIMAGE_THUNK_DATA32)
-            : PE_RVA2TYPE(pvBitsR, pImps->u.OriginalFirstThunk, PIMAGE_THUNK_DATA32);
+        PIMAGE_THUNK_DATA32 pFirstThunk = PE_RVA2TYPE(pvBitsW, pImps->FirstThunk, PIMAGE_THUNK_DATA32); /* update this. */
+        PIMAGE_THUNK_DATA32 pThunk      = pImps->u.OriginalFirstThunk == 0                              /* read from this. */
+                                        ? PE_RVA2TYPE(pvBitsR, pImps->FirstThunk, PIMAGE_THUNK_DATA32)
+                                        : PE_RVA2TYPE(pvBitsR, pImps->u.OriginalFirstThunk, PIMAGE_THUNK_DATA32);
         while (!rc && pThunk->u1.Ordinal != 0)
         {
@@ -694,7 +698,9 @@
          pImps++)
     {
-        const char *        pszModName = PE_RVA2TYPE(pvBitsR, pImps->Name, const char *);
-        PIMAGE_THUNK_DATA64 pFirstThunk;    /* update this. */
-        PIMAGE_THUNK_DATA64 pThunk;         /* read from this. */
+        AssertReturn(pImps->Name < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
+        const char *pszModName = PE_RVA2TYPE(pvBitsR, pImps->Name, const char *);
+        AssertReturn(pImps->FirstThunk < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
+        AssertReturn(pImps->u.OriginalFirstThunk < pModPe->cbImage, VERR_BAD_EXE_FORMAT);
+
         Log3(("RTLdrPE: Import descriptor: %s\n", pszModName));
         Log4(("RTLdrPE:   OriginalFirstThunk = %#RX32\n"
@@ -709,8 +715,8 @@
          * Walk the thunks table(s).
          */
-        pFirstThunk = PE_RVA2TYPE(pvBitsW, pImps->FirstThunk, PIMAGE_THUNK_DATA64);
-        pThunk = pImps->u.OriginalFirstThunk == 0
-            ? PE_RVA2TYPE(pvBitsR, pImps->FirstThunk, PIMAGE_THUNK_DATA64)
-            : PE_RVA2TYPE(pvBitsR, pImps->u.OriginalFirstThunk, PIMAGE_THUNK_DATA64);
+        PIMAGE_THUNK_DATA64 pFirstThunk = PE_RVA2TYPE(pvBitsW, pImps->FirstThunk, PIMAGE_THUNK_DATA64); /* update this. */
+        PIMAGE_THUNK_DATA64 pThunk      = pImps->u.OriginalFirstThunk == 0                              /* read from this. */
+                                        ? PE_RVA2TYPE(pvBitsR, pImps->FirstThunk, PIMAGE_THUNK_DATA64)
+                                        : PE_RVA2TYPE(pvBitsR, pImps->u.OriginalFirstThunk, PIMAGE_THUNK_DATA64);
         while (!rc && pThunk->u1.Ordinal != 0)
         {
@@ -1729,4 +1735,37 @@
 }
 
+
+/**
+ * Worker for rtLdrPE_QueryProp and rtLdrPE_QueryImportModule that counts the
+ * number of imports, storing the result in RTLDRMODPE::cImports.
+ *
+ * @returns IPRT status code.
+ * @param   pThis           The PE module instance.
+ * @param   pvBits          Image bits if the caller had them available, NULL if
+ *                          not. Saves a couple of file accesses.
+ */
+static int rtLdrPE_CountImports(PRTLDRMODPE pThis, void const *pvBits)
+{
+    PCIMAGE_IMPORT_DESCRIPTOR paImpDescs;
+    int rc = rtldrPEReadPartByRva(pThis, pvBits, pThis->ImportDir.VirtualAddress, pThis->ImportDir.Size,
+                                  (void const **)&paImpDescs);
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t const cMax = pThis->ImportDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
+        uint32_t       i = 0;
+        while (   i < cMax
+               && paImpDescs[i].Name > pThis->offNtHdrs
+               && paImpDescs[i].Name < pThis->cbImage
+               && paImpDescs[i].FirstThunk > pThis->offNtHdrs
+               && paImpDescs[i].FirstThunk < pThis->cbImage)
+            i++;
+        pThis->cImports = i;
+
+        rtldrPEFreePart(pThis, pvBits, paImpDescs);
+    }
+    return rc;
+}
+
+
 /**
  * Worker for rtLdrPE_QueryProp that retrievs the name of an import DLL.
@@ -1747,8 +1786,18 @@
 {
     /*
+     * Make sure we got the import count.
+     */
+    int rc;
+    if (pThis->cImports == UINT32_MAX)
+    {
+        rc = rtLdrPE_CountImports(pThis, pvBits);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+
+    /*
      * Check the index first, converting it to an RVA.
      */
-    int rc;
-    if (iImport < pThis->ImportDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR))
+    if (iImport < pThis->cImports)
     {
         uint32_t offEntry = iImport * sizeof(IMAGE_IMPORT_DESCRIPTOR) + pThis->ImportDir.VirtualAddress;
@@ -1866,10 +1915,13 @@
             Assert(cbBuf == sizeof(uint32_t));
             Assert(*pcbRet == cbBuf);
-            *(uint32_t *)pvBuf = pModPe->ImportDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
-            if (*(uint32_t *)pvBuf > 0)
-                *(uint32_t *)pvBuf -= 1; /* The last entry is a NULL entry. */
-            /** @todo Is there some linkers out there that doesn't generiate a
-             *        terminator entry? */
+            if (pModPe->cImports == UINT32_MAX)
+            {
+                int rc = rtLdrPE_CountImports(pModPe, pvBits);
+                if (RT_FAILURE(rc))
+                    return rc;
+            }
+            *(uint32_t *)pvBuf = pModPe->cImports;
             break;
+
 
         case RTLDRPROP_IMPORT_MODULE:
@@ -3629,4 +3681,5 @@
                 pModPe->cbHeaders     = OptHdr.SizeOfHeaders;
                 pModPe->uTimestamp    = FileHdr.TimeDateStamp;
+                pModPe->cImports      = UINT32_MAX;
                 pModPe->f64Bit        = FileHdr.SizeOfOptionalHeader == sizeof(OptHdr);
                 pModPe->ImportDir     = OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
