[WIN32K]
authorJérôme Gardou <jerome.gardou@reactos.org>
Thu, 29 Jul 2010 18:01:14 +0000 (18:01 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Thu, 29 Jul 2010 18:01:14 +0000 (18:01 +0000)
  - rewrite UserLoadImage so that it uses information from the BITMAPFILEHEADER and probes the right buffer.

svn path=/branches/reactos-yarotows/; revision=48364

subsystems/win32/win32k/include/dib.h
subsystems/win32/win32k/misc/file.c
subsystems/win32/win32k/objects/dibobj.c

index 16d17f4..9a25541 100644 (file)
@@ -18,3 +18,6 @@ DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi);
 
 HPALETTE FASTCALL
 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType);
+
+BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
+VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
\ No newline at end of file
index 365b099..87df7d3 100644 (file)
@@ -157,14 +157,12 @@ HBITMAP
 NTAPI
 UserLoadImage(PCWSTR pwszName)
 {
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_SUCCESS;
     HANDLE hFile, hSection;
     BITMAPFILEHEADER *pbmfh;
     LPBITMAPINFO pbmi;
-    ULONG cjInfoSize;
     PVOID pvBits;
     HBITMAP hbmp = 0;
-    BITMAPV5INFO bmiLocal;
 
     DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
 
@@ -194,40 +192,58 @@ UserLoadImage(PCWSTR pwszName)
     /* Get a pointer to the BITMAPINFO */
     pbmi = (LPBITMAPINFO)(pbmfh + 1);
 
-    /* Create a normalized local BITMAPINFO */
-    _SEH2_TRY
-    {
-        Status = ProbeAndConvertToBitmapV5Info(&bmiLocal,
-                                               pbmi,
-                                               DIB_RGB_COLORS,
-                                               0);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       _SEH2_TRY
+       {
+               ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
+               ProbeForRead(pbmfh, pbmfh->bfSize, 1);
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+               Status = _SEH2_GetExceptionCode();
+       }
+       _SEH2_END
+
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT1("Bad File?\n");
+               goto leave;
+       }
+
+    if (pbmfh->bfType == 0x4D42 /* 'BM' */)
     {
-        Status = _SEH2_GetExceptionCode();
-    }
-    _SEH2_END
+               /* Could be BITMAPCOREINFO */
+               BITMAPINFO* pConvertedInfo;
 
-    if (NT_SUCCESS(Status))
-    {
-        cjInfoSize = bmiLocal.bmiHeader.bV5Size +
-                     bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD);
-        pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
+               pvBits = (PVOID)((PCHAR)pbmi + pbmfh->bfOffBits);
+
+               pConvertedInfo = DIB_ConvertBitmapInfo(pbmi, DIB_RGB_COLORS);
+               if(!pConvertedInfo)
+               {
+                       DPRINT1("Unable to convert the bitmap Info\n");
+                       goto leave;
+               }
 
         // FIXME: use Gre... so that the BITMAPINFO doesn't get probed
         hbmp = NtGdiCreateDIBitmapInternal(NULL,
-                                           bmiLocal.bmiHeader.bV5Width,
-                                           bmiLocal.bmiHeader.bV5Height,
+                                           pConvertedInfo->bmiHeader.biWidth,
+                                           pConvertedInfo->bmiHeader.biHeight,
                                            CBM_INIT,
                                            pvBits,
                                            pbmi,
                                            DIB_RGB_COLORS,
-                                           bmiLocal.bmiHeader.bV5Size,
-                                           bmiLocal.bmiHeader.bV5SizeImage,
+                                           pConvertedInfo->bmiHeader.biSize,
+                                           pConvertedInfo->bmiHeader.biSizeImage,
                                            0,
                                            0);
+
+               DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi);
     }
+       else
+       {
+               DPRINT1("Unknown file type!\n");
+       }
 
+leave:
     /* Unmap our section, we don't need it anymore */
     ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);
 
index d61b36f..5741113 100644 (file)
@@ -674,18 +674,12 @@ NtGdiGetDIBitsInternal(
                /* We need a BITMAPINFO to create a DIB, but we have to fill
                 * the BITMAPCOREINFO we're provided */
                pbmci = (BITMAPCOREINFO*)Info;
-               Info = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD), TAG_DIB);
+               Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
                if(Info == NULL)
                {
-                       DPRINT1("Error, could not allocate another BITMAPINFO!\n");
+                       DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
                        return 0;
                }
-               RtlZeroMemory(Info, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
-               Info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-               Info->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
-               Info->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
-               Info->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
-               Info->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
                rgbQuads = Info->bmiColors;
        }
 
@@ -1050,7 +1044,7 @@ done:
 
        if(pDC) DC_UnlockDc(pDC);
        if(psurf) SURFACE_UnlockSurface(psurf);
-       if(pbmci) ExFreePoolWithTag(Info, TAG_DIB);
+       if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
 
        return ScanLines;
 }
@@ -2077,4 +2071,82 @@ ProbeAndConvertToBitmapV5Info(
     return STATUS_SUCCESS;
 }
 
+/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
+ * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
+BITMAPINFO*
+FASTCALL
+DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
+{
+       CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
+       BITMAPINFO* pNewBmi ;
+       UINT numColors = 0, ColorsSize = 0;
+
+       if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
+       if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
+
+       if(pbmci->bmciHeader.bcBitCount <= 8)
+       {
+               numColors = 1 << pbmci->bmciHeader.bcBitCount;
+               if(Usage == DIB_PAL_COLORS)
+               {
+                       ColorsSize = numColors * sizeof(WORD);
+               }
+               else
+               {
+                       ColorsSize = numColors * sizeof(RGBQUAD);
+               }
+       }
+       else if (Usage == DIB_PAL_COLORS)
+       {
+               /* Invalid at high Res */
+               return NULL;
+       }
+
+       pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
+       if(!pNewBmi) return NULL;
+
+       RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
+
+       pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+       pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
+       pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
+       pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
+       pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
+       pNewBmi->bmiHeader.biCompression = BI_RGB ;
+       pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
+                                                                                               pNewBmi->bmiHeader.biHeight,
+                                                                                               pNewBmi->bmiHeader.biBitCount);
+
+       if(Usage == DIB_PAL_COLORS)
+       {
+               RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
+       }
+       else
+       {
+               UINT i;
+               for(i=0; i<numColors; i++)
+               {
+                       pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
+                       pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
+                       pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
+               }
+       }
+
+       return pNewBmi ;
+}
+
+/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
+VOID
+FASTCALL
+DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+{
+       if(converted != orig)
+               ExFreePoolWithTag(converted, TAG_DIB);
+}
+
+
+
+
+
+
 /* EOF */