- Replace the ColorMap pointer in BITMAPOBJ with palette handle and
  correctly free it when the bitmap is about to be destroyed. Also
  get rid of some palette leaks when DIBs were selected into device
  context.
- Refine GDI32 -> Win32k interface for creating and managing brushes.
  Remove NtGdiCreateBrushIndirect, NtGdiCreateDIBPatternBrush,
  NtGdiCreateDIBPatternBrushPt and NtGdiFixBrushOrgEx syscalls and
  add NtGdiCreateDIBBrush.
- Implement basic support for DIB pattern brushes.
- Add user mode helper routine for "normalizing" BITMAPINFO structure.
- Add definition for BITMAPV5HEADER.
Modified: trunk/reactos/include/win32k/bitmaps.h
Modified: trunk/reactos/include/win32k/brush.h
Modified: trunk/reactos/lib/gdi32/gdi32.def
Modified: trunk/reactos/lib/gdi32/include/precomp.h
Modified: trunk/reactos/lib/gdi32/makefile
Modified: trunk/reactos/lib/gdi32/misc/stubs.c
Modified: trunk/reactos/lib/gdi32/objects/dc.c
Added: trunk/reactos/lib/gdi32/objects/utils.c
Modified: trunk/reactos/subsys/win32k/include/dib.h
Modified: trunk/reactos/subsys/win32k/include/intgdi.h
Modified: trunk/reactos/subsys/win32k/ntuser/winsta.c
Modified: trunk/reactos/subsys/win32k/objects/bitmaps.c
Modified: trunk/reactos/subsys/win32k/objects/brush.c
Modified: trunk/reactos/subsys/win32k/objects/color.c
Modified: trunk/reactos/subsys/win32k/objects/dc.c
Modified: trunk/reactos/subsys/win32k/objects/dib.c
Modified: trunk/reactos/subsys/win32k/objects/stockobj.c
Modified: trunk/reactos/tools/nci/w32ksvc.db
Modified: trunk/reactos/w32api/include/wingdi.h

Modified: trunk/reactos/include/win32k/bitmaps.h
--- trunk/reactos/include/win32k/bitmaps.h	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/include/win32k/bitmaps.h	2005-03-19 22:15:02 UTC (rev 14203)
@@ -18,7 +18,7 @@
 
   /* For device-independent bitmaps: */
   DIBSECTION *dib;
-  RGBQUAD *ColorMap;
+  HPALETTE hDIBPalette;
 } BITMAPOBJ, *PBITMAPOBJ;
 
 #define BITMAPOBJ_IS_APIBITMAP		0x1

Modified: trunk/reactos/include/win32k/brush.h
--- trunk/reactos/include/win32k/brush.h	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/include/win32k/brush.h	2005-03-19 22:15:02 UTC (rev 14203)
@@ -86,16 +86,13 @@
    CONST LOGBRUSH *LogBrush);
 
 HBRUSH STDCALL
-NtGdiCreateDIBPatternBrush(
-   HGLOBAL hDIBPacked,
-   UINT ColorSpec);
+NtGdiCreateDIBBrush(
+   CONST BITMAPINFO *BitmapInfoAndData,
+   UINT ColorSpec,
+   UINT BitmapInfoSize,
+   CONST VOID *PackedDIB);
 
 HBRUSH STDCALL
-NtGdiCreateDIBPatternBrushPt(
-   CONST VOID *PackedDIB,
-   UINT Usage);
-
-HBRUSH STDCALL
 NtGdiCreateHatchBrush(
    INT Style,
    COLORREF Color);

Modified: trunk/reactos/lib/gdi32/gdi32.def
--- trunk/reactos/lib/gdi32/gdi32.def	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/gdi32.def	2005-03-19 22:15:02 UTC (rev 14203)
@@ -49,7 +49,7 @@
 CopyMetaFileW@8
 CreateBitmap@20=NtGdiCreateBitmap@20
 CreateBitmapIndirect@4=NtGdiCreateBitmapIndirect@4
-CreateBrushIndirect@4=NtGdiCreateBrushIndirect@4
+CreateBrushIndirect@4
 CreateColorSpaceA@4
 CreateColorSpaceW@4
 CreateCompatibleBitmap@12=NtGdiCreateCompatibleBitmap@12
@@ -57,7 +57,7 @@
 CreateDCA@16
 CreateDCW@16
 CreateDIBPatternBrush@8
-CreateDIBPatternBrushPt@8=NtGdiCreateDIBPatternBrushPt@8
+CreateDIBPatternBrushPt@8
 CreateDIBSection@24=NtGdiCreateDIBSection@24
 CreateDIBitmap@24=NtGdiCreateDIBitmap@24
 CreateDiscardableBitmap@12=NtGdiCreateDiscardableBitmap@12

Modified: trunk/reactos/lib/gdi32/include/precomp.h
--- trunk/reactos/lib/gdi32/include/precomp.h	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/include/precomp.h	2005-03-19 22:15:02 UTC (rev 14203)
@@ -53,7 +53,13 @@
 BOOL FASTCALL NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw);
 
 /* == GDI HANDLES =========================================================== */
+
 BOOL GdiIsHandleValid(HGDIOBJ hGdiObj);
 BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, PVOID *UserData);
 
+/* == BITMAP UTILITY FUNCTIONS ============================================== */
+
+BOOL STDCALL CalculateColorTableSize(LPBITMAPINFOHEADER BitmapInfoHeader, UINT *ColorSpec, UINT *ColorTableSize);
+LPBITMAPINFO STDCALL ConvertBitmapInfo(LPBITMAPINFO BitmapInfo, UINT ColorSpec, UINT *BitmapInfoSize, BOOL FollowedByData);
+
 /* EOF */

Modified: trunk/reactos/lib/gdi32/makefile
--- trunk/reactos/lib/gdi32/makefile	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/makefile	2005-03-19 22:15:02 UTC (rev 14203)
@@ -40,6 +40,8 @@
 
 OBJECTS_OBJECTS = \
  objects/bitblt.o \
+ objects/utils.o \
+ objects/brush.o \
  objects/dc.o \
  objects/font.o \
  objects/linedda.o \

Modified: trunk/reactos/lib/gdi32/misc/stubs.c
--- trunk/reactos/lib/gdi32/misc/stubs.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/misc/stubs.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -84,22 +84,7 @@
 	return 0;
 }
 
-/*
- * @unimplemented
- */
-HBRUSH
-STDCALL
-CreateDIBPatternBrush(
-	HGLOBAL			a0,
-	UINT			a1
-	)
-{
-	UNIMPLEMENTED;
-	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-	return 0;
-}
 
-
 /*
  * @unimplemented
  */

Modified: trunk/reactos/lib/gdi32/objects/dc.c
--- trunk/reactos/lib/gdi32/objects/dc.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/objects/dc.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -290,26 +290,6 @@
 /*
  * @implemented
  */
-BOOL
-STDCALL
-FixBrushOrgEx(
-	HDC	hdc,
-	int	nXOrg,
-	int	nYOrg,
-	LPPOINT	lppt
-	)
-{
-  #if 0
-  /* FIXME - Check if we're emulating win95, if so, forward to SetBrushOrgEx() */
-  return SetBrushOrgEx(hdc, nXOrg, nYOrg, lppt);
-  #endif
-  
-  return FALSE;
-}
-
-/*
- * @implemented
- */
 COLORREF 
 STDCALL
 GetDCBrushColor(

Added: trunk/reactos/lib/gdi32/objects/utils.c
--- trunk/reactos/lib/gdi32/objects/utils.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/lib/gdi32/objects/utils.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -0,0 +1,333 @@
+#include "precomp.h"
+
+/**
+ * @name CalculateColorTableSize
+ *
+ * Internal routine to calculate the number of color table entries.
+ *
+ * @param BitmapInfoHeader
+ *        Input bitmap information header, can be any version of
+ *        BITMAPINFOHEADER or BITMAPCOREHEADER.
+ *
+ * @param ColorSpec
+ *        Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
+ *        or DIB_RGB_COLORS). On successful return this value is normalized
+ *        according to the bitmap info.
+ *
+ * @param ColorTableSize
+ *        On successful return this variable is filled with number of
+ *        entries in color table for the image with specified parameters.
+ *
+ * @return
+ *    TRUE if the input values together form a valid image, FALSE otherwise.
+ */
+
+BOOL STDCALL
+CalculateColorTableSize(
+   LPBITMAPINFOHEADER BitmapInfoHeader,
+   UINT *ColorSpec,
+   UINT *ColorTableSize)
+{
+   WORD BitCount;
+   DWORD ClrUsed;
+   DWORD Compression;
+
+   /*
+    * At first get some basic parameters from the passed BitmapInfoHeader
+    * structure. It can have one of the following formats: 
+    * - BITMAPCOREHEADER (the oldest one with totally different layout
+    *                     from the others)
+    * - BITMAPINFOHEADER (the standard and most common header)
+    * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
+    * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
+    */
+
+   if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
+   {
+      BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
+      ClrUsed = 0;
+      Compression = BI_RGB;
+   }
+   else
+   {
+      BitCount = BitmapInfoHeader->biBitCount;
+      ClrUsed = BitmapInfoHeader->biClrUsed;
+      Compression = BitmapInfoHeader->biCompression;
+   }
+
+   switch (Compression)
+   {
+      case BI_BITFIELDS:
+         if (*ColorSpec == DIB_PAL_COLORS)
+            *ColorSpec = DIB_RGB_COLORS;
+
+         if (BitCount != 16 && BitCount != 32)
+            return FALSE;
+
+         /*
+          * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
+          * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
+          * For BITMAPINFOHEADER the color masks are stored in the palette.
+          */
+
+         if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
+            *ColorTableSize = 0;
+         else
+            *ColorTableSize = 3;
+         
+         return TRUE;
+
+      case BI_RGB:
+         switch (BitCount)
+         {
+            case 1:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
+               return TRUE;
+
+            case 4:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+               return TRUE;
+
+            case 8:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+               return TRUE;
+
+            default:
+               if (*ColorSpec == DIB_PAL_COLORS)
+                  *ColorSpec = DIB_RGB_COLORS;
+               if (BitCount != 16 && BitCount != 24 && BitCount != 32)
+                  return FALSE;
+               *ColorTableSize = ClrUsed;
+               return TRUE;
+         }
+         
+      case BI_RLE4:
+         if (BitCount == 4)
+         {
+            *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+            return TRUE;
+         }
+         return FALSE;
+
+      case BI_RLE8:
+         if (BitCount == 8)
+         {
+            *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+            return TRUE;
+         }
+         return FALSE;
+
+      case BI_JPEG:
+      case BI_PNG:
+         *ColorTableSize = ClrUsed;
+         return TRUE;
+
+      default:
+         return FALSE;      
+   }
+}
+
+/**
+ * @name ConvertBitmapInfo
+ *
+ * Internal routine to convert a user-passed BITMAPINFO structure into
+ * unified BITMAPINFO structure.
+ *
+ * @param BitmapInfo
+ *        Input bitmap info, can be any version of BITMAPINFO or
+ *        BITMAPCOREINFO.
+ * @param ColorSpec
+ *        Specifies whether the bmiColors member of the BITMAPINFO structure
+ *        contains a valid color table and, if so, whether the entries in
+ *        this color table contain explicit red, green, blue (DIB_RGB_COLORS)
+ *        values or palette indexes (DIB_PAL_COLORS).
+ * @param BitmapInfoSize
+ *        On successful return contains the size of the returned BITMAPINFO
+ *        structure. If FollowedByData is TRUE the size includes the number
+ *        of bytes occupied by the image data.
+ * @param FollowedByData
+ *        Specifies if the BITMAPINFO header is immediately followed
+ *        by the actual bitmap data (eg. as passed to CreateDIBPatternBrush).
+ *
+ * @return
+ *    Either the original BitmapInfo or newly allocated structure is
+ *    returned. For the later case the caller is responsible for freeing the
+ *    memory using RtlFreeHeap with the current process heap.
+ *
+ * @example
+ *    PBITMAPINFO NewBitmapInfo;
+ *    UINT NewBitmapInfoSize;
+ *
+ *    NewBitmapInfo = ConvertBitmapInfo(OldBitmapInfo, DIB_RGB_COLORS,
+ *                                      &NewBitmapInfoSize, FALSE);
+ *    if (NewBitmapInfo)
+ *    {
+ *       <do something with the bitmap info>
+ *       if (NewBitmapInfo != OldBitmapInfo)
+ *          RtlFreeHeap(RtlGetProcessHeap(), 0, NewBitmapInfo);
+ *    }
+ */
+
+LPBITMAPINFO STDCALL
+ConvertBitmapInfo(
+   LPBITMAPINFO BitmapInfo,
+   UINT ColorSpec,
+   UINT *BitmapInfoSize,
+   BOOL FollowedByData)
+{
+   LPBITMAPINFO NewBitmapInfo = BitmapInfo;
+   LPBITMAPCOREINFO CoreBitmapInfo = (LPBITMAPCOREINFO)BitmapInfo;
+   DWORD Size = 0;
+   ULONG DataSize = 0;
+   UINT PaletteEntryCount = 0;
+
+   /*
+    * At first check if the passed BitmapInfo structure has valid size. It
+    * can have one of these headers: BITMAPCOREHEADER, BITMAPINFOHEADER,
+    * BITMAPV4HEADER or BITMAPV5HEADER (see CalculateColorTableSize for
+    * description).
+    */
+
+   if (BitmapInfo->bmiHeader.biSize != sizeof(BITMAPCOREHEADER) &&
+       (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER) ||
+        BitmapInfo->bmiHeader.biSize > sizeof(BITMAPV5HEADER)))
+   {
+      return NULL;
+   }
+
+   /*
+    * Now calculate the color table size. Also if the bitmap info contains
+    * invalid color information it's rejected here.
+    */
+
+   if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
+                                &PaletteEntryCount))
+   {
+      return NULL;
+   }
+
+   /*
+    * Calculate the size of image data if applicable. We must be careful
+    * to do proper aligning on line ends.
+    */
+
+   if (FollowedByData)
+   {
+      if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+      {
+         DataSize =
+            CoreBitmapInfo->bmciHeader.bcHeight *
+            CoreBitmapInfo->bmciHeader.bcWidth *               
+            CoreBitmapInfo->bmciHeader.bcBitCount;
+         DataSize = ((DataSize + 31) & ~31) / 8;
+         DataSize *= CoreBitmapInfo->bmciHeader.bcPlanes;
+      }
+      else
+      {
+         if (BitmapInfo->bmiHeader.biCompression == BI_RGB ||
+             BitmapInfo->bmiHeader.biCompression == BI_BITFIELDS)
+         {
+            DataSize =
+               abs(BitmapInfo->bmiHeader.biHeight) *
+               BitmapInfo->bmiHeader.biWidth *
+               BitmapInfo->bmiHeader.biBitCount;
+            DataSize = ((DataSize + 31) & ~31) / 8;
+            DataSize *= BitmapInfo->bmiHeader.biPlanes;
+         }
+         else
+         {
+            DataSize = BitmapInfo->bmiHeader.biSizeImage;
+         }
+      }
+   }
+
+   /*
+    * If BitmapInfo was originally BITMAPCOREINFO then we need to convert
+    * it to the standard BITMAPINFO layout.
+    */
+
+   if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+   {
+      Size = sizeof(BITMAPINFOHEADER);
+      if (ColorSpec == DIB_RGB_COLORS)
+         Size += PaletteEntryCount * sizeof(RGBQUAD);
+      else
+         Size += PaletteEntryCount * sizeof(USHORT);
+      Size += DataSize;
+
+      NewBitmapInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
+      if (NewBitmapInfo == NULL)
+      {
+         return NULL;
+      }
+
+      NewBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+      NewBitmapInfo->bmiHeader.biWidth = CoreBitmapInfo->bmciHeader.bcWidth;
+      NewBitmapInfo->bmiHeader.biHeight = CoreBitmapInfo->bmciHeader.bcHeight;
+      NewBitmapInfo->bmiHeader.biPlanes = CoreBitmapInfo->bmciHeader.bcPlanes;
+      NewBitmapInfo->bmiHeader.biBitCount = CoreBitmapInfo->bmciHeader.bcBitCount;
+      NewBitmapInfo->bmiHeader.biCompression = BI_RGB;
+      NewBitmapInfo->bmiHeader.biSizeImage = 0;
+      NewBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
+      NewBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
+      NewBitmapInfo->bmiHeader.biClrUsed = 0;
+      NewBitmapInfo->bmiHeader.biClrImportant = 0;
+
+      if (PaletteEntryCount != 0)
+      {
+         if (ColorSpec == DIB_RGB_COLORS)
+         {
+            ULONG Index;
+
+            for (Index = 0; Index < PaletteEntryCount; Index++)
+            {
+               NewBitmapInfo->bmiColors[Index].rgbRed =
+                  CoreBitmapInfo->bmciColors[Index].rgbtRed;
+               NewBitmapInfo->bmiColors[Index].rgbGreen =
+                  CoreBitmapInfo->bmciColors[Index].rgbtGreen;
+               NewBitmapInfo->bmiColors[Index].rgbBlue =
+                  CoreBitmapInfo->bmciColors[Index].rgbtBlue;
+               NewBitmapInfo->bmiColors[Index].rgbReserved = 0;
+            }
+         }
+         else
+         {
+            RtlCopyMemory(NewBitmapInfo->bmiColors,
+                          CoreBitmapInfo->bmciColors,
+                          PaletteEntryCount * sizeof(USHORT));
+         }
+      }
+
+      if (FollowedByData)
+      {
+         ULONG_PTR NewDataPtr, OldDataPtr;
+
+         if (ColorSpec == DIB_RGB_COLORS)
+         {
+            NewDataPtr = (ULONG_PTR)(NewBitmapInfo->bmiColors +
+                         PaletteEntryCount);
+            OldDataPtr = (ULONG_PTR)(CoreBitmapInfo->bmciColors +
+                         PaletteEntryCount);
+         }
+         else
+         {
+            NewDataPtr = (ULONG_PTR)(NewBitmapInfo->bmiColors) +
+                         PaletteEntryCount * sizeof(USHORT);
+            OldDataPtr = (ULONG_PTR)(CoreBitmapInfo->bmciColors) +
+                         PaletteEntryCount * sizeof(USHORT);
+         }
+
+         RtlCopyMemory((PVOID)NewDataPtr, (PVOID)OldDataPtr, DataSize);
+      }
+   }
+
+   Size = NewBitmapInfo->bmiHeader.biSize;
+   if (ColorSpec == DIB_RGB_COLORS)
+      Size += PaletteEntryCount * sizeof(RGBQUAD);
+   else
+      Size += PaletteEntryCount * sizeof(USHORT);
+   Size += DataSize;
+   *BitmapInfoSize = Size;
+
+   return NewBitmapInfo;
+}

Modified: trunk/reactos/subsys/win32k/include/dib.h
--- trunk/reactos/subsys/win32k/include/dib.h	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/subsys/win32k/include/dib.h	2005-03-19 22:15:02 UTC (rev 14203)
@@ -17,6 +17,6 @@
 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi);
 
 HPALETTE FASTCALL
-BuildDIBPalette (PBITMAPINFO bmi, PINT paletteType);
+BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType);
 
 #endif /* _WIN32K_DIB_H */

Modified: trunk/reactos/subsys/win32k/include/intgdi.h
--- trunk/reactos/subsys/win32k/include/intgdi.h	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/subsys/win32k/include/intgdi.h	2005-03-19 22:15:02 UTC (rev 14203)
@@ -9,17 +9,30 @@
 VOID FASTCALL
 IntGdiInitBrushInstance(GDIBRUSHINST *BrushInst, PGDIBRUSHOBJ BrushObj, XLATEOBJ *XlateObj);
 
-HBRUSH FASTCALL
-IntGdiCreateBrushIndirect(PLOGBRUSH lb);
 
-HBRUSH FASTCALL
-IntGdiCreateDIBPatternBrush(HGLOBAL hDIBPacked,
-                            UINT    ColorSpec);
+HBRUSH STDCALL
+IntGdiCreateDIBBrush(
+   CONST BITMAPINFO *BitmapInfo,
+   UINT ColorSpec,
+   UINT BitmapInfoSize,
+   CONST VOID *PackedDIB);
 
-HBRUSH FASTCALL
-IntGdiCreateDIBPatternBrushPt(CONST VOID *PackedDIB,
-                              UINT       Usage);
+HBRUSH STDCALL
+IntGdiCreateHatchBrush(
+   INT Style,
+   COLORREF Color);
 
+HBRUSH STDCALL
+IntGdiCreatePatternBrush(
+   HBITMAP hBitmap);
+
+HBRUSH STDCALL
+IntGdiCreateSolidBrush(
+   COLORREF Color);
+
+HBRUSH STDCALL
+IntGdiCreateNullBrush(VOID);
+
 BOOL FASTCALL
 IntPatBlt(
    PDC dc,

Modified: trunk/reactos/subsys/win32k/ntuser/winsta.c
--- trunk/reactos/subsys/win32k/ntuser/winsta.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/subsys/win32k/ntuser/winsta.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -309,6 +309,13 @@
 {
    NTSTATUS Status;
   
+   if (WindowStation == NULL)
+   {
+//      DPRINT1("Invalid window station handle\n");
+      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      return STATUS_INVALID_HANDLE;
+   }
+
    Status = ObReferenceObjectByHandle(
       WindowStation,
       DesiredAccess,

Modified: trunk/reactos/subsys/win32k/objects/bitmaps.c
--- trunk/reactos/subsys/win32k/objects/bitmaps.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/subsys/win32k/objects/bitmaps.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -463,6 +463,10 @@
 		{
 			EngFreeUserMem(pBmp->SurfObj.pvBits);
 		}
+		if (pBmp->hDIBPalette)
+		{
+			NtGdiDeleteObject(pBmp->hDIBPalette);
+		}
 	}
 
 	return TRUE;

Modified: trunk/reactos/subsys/win32k/objects/brush.c
--- trunk/reactos/subsys/win32k/objects/brush.c	2005-03-19 21:48:33 UTC (rev 14202)
+++ trunk/reactos/subsys/win32k/objects/brush.c	2005-03-19 22:15:02 UTC (rev 14203)
@@ -72,6 +72,10 @@
          if (Dc->w.bitsPerPixel != 1)
             Result = IntEngCreateSrcMonoXlate(Dc->w.hPalette, Dc->w.textColor, Dc->w.backgroundColor);
       }
+      else if (BrushObj->flAttrs & GDIBRUSH_IS_DIB)
+      {
+         Result = IntEngCreateXlate(0, 0, Dc->w.hPalette, Pattern->hDIBPalette);
+      }
 
       BITMAPOBJ_UnlockBitmap(BrushObj->hbmPattern);
       *Failed = FALSE;
@@ -97,83 +101,332 @@
    BrushInst->XlateObject = XlateObj;
 }
 
-HBRUSH FASTCALL
-IntGdiCreateBrushIndirect(PLOGBRUSH LogBrush)
+/**
+ * @name CalculateColorTableSize
+ *
+ * Internal routine to calculate the number of color table entries.
+ *
+ * @param BitmapInfoHeader
+ *        Input bitmap information header, can be any version of
+ *        BITMAPINFOHEADER or BITMAPCOREHEADER.
+ *
+ * @param ColorSpec
+ *        Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
+ *        or DIB_RGB_COLORS). On successful return this value is normalized
+ *        according to the bitmap info.
+ *
+ * @param ColorTableSize
+ *        On successful return this variable is filled with number of
+ *        entries in color table for the image with specified parameters.
+ *
+ * @return
+ *    TRUE if the input values together form a valid image, FALSE otherwise.
+ */
+
+BOOL STDCALL
+CalculateColorTableSize(
+   CONST BITMAPINFOHEADER *BitmapInfoHeader,
+   UINT *ColorSpec,
+   UINT *ColorTableSize)
 {
-   PGDIBRUSHOBJ BrushObject;
-   HBRUSH hBrush;
-   HBITMAP hPattern = 0;
-   
-   switch (LogBrush->lbStyle)
+   WORD BitCount;
+   DWORD ClrUsed;
+   DWORD Compression;
+
+   /*
+    * At first get some basic parameters from the passed BitmapInfoHeader
+    * structure. It can have one of the following formats: 
+    * - BITMAPCOREHEADER (the oldest one with totally different layout
+    *                     from the others)
+    * - BITMAPINFOHEADER (the standard and most common header)
+    * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
+    * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
+    */
+
+   if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
    {
-      case BS_HATCHED:
-         hPattern = NtGdiCreateBitmap(8, 8, 1, 1, HatchBrushes[LogBrush->lbHatch]);
-         if (hPattern == NULL)
+      BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
+      ClrUsed = 0;
+      Compression = BI_RGB;
+   }
+   else
+   {
+      BitCount = BitmapInfoHeader->biBitCount;
+      ClrUsed = BitmapInfoHeader->biClrUsed;
+      Compression = BitmapInfoHeader->biCompression;
+   }
+
+   switch (Compression)
+   {
+      case BI_BITFIELDS:
+         if (*ColorSpec == DIB_PAL_COLORS)
+            *ColorSpec = DIB_RGB_COLORS;
+
+         if (BitCount != 16 && BitCount != 32)
+            return FALSE;
+
+         /*
+          * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
+          * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
+          * For BITMAPINFOHEADER the color masks are stored in the palette.
+          */
+
+         if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
+            *ColorTableSize = 0;
+         else
+            *ColorTableSize = 3;
+         
+         return TRUE;
+
+      case BI_RGB:
+         switch (BitCount)
          {
-            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-            return NULL;
+            case 1:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
+               return TRUE;
+
+            case 4:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+               return TRUE;
+
+            case 8:
+               *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+               return TRUE;
+
+            default:
+               if (*ColorSpec == DIB_PAL_COLORS)
+                  *ColorSpec = DIB_RGB_COLORS;
+               if (BitCount != 16 && BitCount != 24 && BitCount != 32)
+                  return FALSE;
+               *ColorTableSize = ClrUsed;
+               return TRUE;
          }
-         break;
-     
-      case BS_PATTERN:
-         hPattern = BITMAPOBJ_CopyBitmap((HBITMAP)LogBrush->lbHatch);
-         if (hPattern == NULL)
+         
+      case BI_RLE4:
+         if (BitCount == 4)
          {
-            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-            return NULL;
+            *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+            return TRUE;
          }
-         break;
+         return FALSE;
+
+      case BI_RLE8:
+         if (BitCount == 8)
+         {
+            *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+            return TRUE;
+         }
+         return FALSE;
+
+      case BI_JPEG:
+      case BI_PNG:
+         *ColorTableSize = ClrUsed;
+         return TRUE;
+
+      default:
+         return FALSE;      
    }
+}
+
+HBRUSH STDCALL
+IntGdiCreateDIBBrush(
+   CONST BITMAPINFO *BitmapInfo,
+   UINT ColorSpec,
+   UINT BitmapInfoSize,
+   CONST VOID *PackedDIB)
+{
+   HBRUSH hBrush;
+   PGDIBRUSHOBJ BrushObject;
+   HBITMAP hPattern;
+   ULONG_PTR DataPtr;
+   UINT PaletteEntryCount;
+   PBITMAPOBJ BitmapObject;
+   UINT PaletteType;
+
+   if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return NULL;
+   }
+
+   if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
+                                &PaletteEntryCount))
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return NULL;
+   }
+
+   DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
+   if (ColorSpec == DIB_RGB_COLORS)
+      DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
+   else
+      DataPtr += PaletteEntryCount * sizeof(USHORT);
+
+   hPattern = NtGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
+                                BitmapInfo->bmiHeader.biHeight,
+                                BitmapInfo->bmiHeader.biPlanes,
+                                BitmapInfo->bmiHeader.biBitCount,
+                                (PVOID)DataPtr);
+   if (hPattern == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+
+   BitmapObject = BITMAPOBJ_LockBitmap(hPattern);
+   ASSERT(BitmapObject != NULL);
+   BitmapObject->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
+   BITMAPOBJ_UnlockBitmap(hPattern);
+
+   hBrush = BRUSHOBJ_AllocBrush();
+   if (hBrush == NULL)
+   {
+      NtGdiDeleteObject(hPattern);
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+
+   BrushObject = BRUSHOBJ_LockBrush(hBrush);
+   ASSERT(BrushObject != NULL);
+
+   BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP | GDIBRUSH_IS_DIB;
+   BrushObject->hbmPattern = hPattern;
+   /* FIXME: Fill in the rest of fields!!! */
+
+   GDIOBJ_SetOwnership(hPattern, NULL);
+
+   BRUSHOBJ_UnlockBrush(hBrush);
    
+   return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreateHatchBrush(
+   INT Style,
+   COLORREF Color)
+{
+   HBRUSH hBrush;
+   PGDIBRUSHOBJ BrushObject;
+   HBITMAP hPattern;
+   
+   if (Style < 0 || Style >= NB_HATCH_STYLES)
+   {
+      return 0;
+   }
+
+   hPattern = NtGdiCreateBitmap(8, 8, 1, 1, HatchBrushes[Style]);
+   if (hPattern == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+
    hBrush = BRUSHOBJ_AllocBrush();
    if (hBrush == NULL)
    {
+      NtGdiDeleteObject(hPattern);
       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
       return NULL;
    }
 
    BrushObject = BRUSHOBJ_LockBrush(hBrush);
-   if(BrushObject != NULL)
+   ASSERT(BrushObject != NULL);
+
+   BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
+   BrushObject->hbmPattern = hPattern;
+   BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
+
+   GDIOBJ_SetOwnership(hPattern, NULL);
+
+   BRUSHOBJ_UnlockBrush(hBrush);
+   
+   return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreatePatternBrush(
+   HBITMAP hBitmap)
+{
+   HBRUSH hBrush;
+   PGDIBRUSHOBJ BrushObject;
+   HBITMAP hPattern;
+   
+   hPattern = BITMAPOBJ_CopyBitmap(hBitmap);
+   if (hPattern == NULL)
    {
-     switch (LogBrush->lbStyle)
-     {
-        case BS_NULL:
-           BrushObject->flAttrs |= GDIBRUSH_IS_NULL;
-           break;
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+   
+   hBrush = BRUSHOBJ_AllocBrush();
+   if (hBrush == NULL)
+   {
+      NtGdiDeleteObject(hPattern);
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
 
-        case BS_SOLID:
-           BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
-           BrushObject->BrushAttr.lbColor = LogBrush->lbColor & 0xFFFFFF;
-           /* FIXME: Fill in the rest of fields!!! */
-           break;
+   BrushObject = BRUSHOBJ_LockBrush(hBrush);
+   ASSERT(BrushObject != NULL);
 
-        case BS_HATCHED:
-           BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
-           BrushObject->hbmPattern = hPattern;
-           BrushObject->BrushAttr.lbColor = LogBrush->lbColor & 0xFFFFFF;
-           break;
+   BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP;
+   BrushObject->hbmPattern = hPattern;
+   /* FIXME: Fill in the rest of fields!!! */
 
-        case BS_PATTERN:
-           BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-           BrushObject->hbmPattern = hPattern;
-           /* FIXME: Fill in the rest of fields!!! */
-           break;
+   GDIOBJ_SetOwnership(hPattern, NULL);
 
-        default:
-           DPRINT1("Brush Style: %d\n", LogBrush->lbStyle);
-           UNIMPLEMENTED;
-           break;
-     }
-     
-     BRUSHOBJ_UnlockBrush(hBrush);
+   BRUSHOBJ_UnlockBrush(hBrush);
+   
+   return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreateSolidBrush(
+   COLORREF Color)
+{
+   HBRUSH hBrush;
+   PGDIBRUSHOBJ BrushObject;
+   
+   hBrush = BRUSHOBJ_AllocBrush();
+   if (hBrush == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
    }
 
-   if (hPattern != 0)
-      GDIOBJ_SetOwnership(hPattern, NULL);
+   BrushObject = BRUSHOBJ_LockBrush(hBrush);
+   ASSERT(BrushObject != NULL);
+
+   BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
+   BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
+   /* FIXME: Fill in the rest of fields!!! */
+
+   BRUSHOBJ_UnlockBrush(hBrush);
    
    return hBrush;
 }
 
+HBRUSH STDCALL
+IntGdiCreateNullBrush(VOID)
+{
+   HBRUSH hBrush;
+   PGDIBRUSHOBJ BrushObject;
+   
+   hBrush = BRUSHOBJ_AllocBrush();
+   if (hBrush == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+
+   BrushObject = BRUSHOBJ_LockBrush(hBrush);
+   ASSERT(BrushObject != NULL);
+   BrushObject->flAttrs |= GDIBRUSH_IS_NULL;
+   BRUSHOBJ_UnlockBrush(hBrush);
+   
+   return hBrush;
+}
+
 BOOL FASTCALL
 IntPatBlt(
    PDC dc,
@@ -299,82 +552,60 @@
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 HBRUSH STDCALL
-NtGdiCreateBrushIndirect(CONST LOGBRUSH *LogBrush)
+NtGdiCreateDIBBrush(
+   CONST BITMAPINFO *BitmapInfoAndData,
+   UINT ColorSpec,
+   UINT BitmapInfoSize,
+   CONST VOID *PackedDIB)
 {
-   LOGBRUSH SafeLogBrush;
+   BITMAPINFO *SafeBitmapInfoAndData;
    NTSTATUS Status;
-  
-   Status = MmCopyFromCaller(&SafeLogBrush, LogBrush, sizeof(LOGBRUSH));
+   HBRUSH hBrush;
+
+   SafeBitmapInfoAndData = EngAllocMem(0, BitmapInfoSize, 0);
+   if (SafeBitmapInfoAndData == NULL)
+   {
+      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+      return NULL;
+   }
+
+   Status = MmCopyFromCaller(SafeBitmapInfoAndData, BitmapInfoAndData,
[truncated at 1000 lines; 398 more skipped]