[USER32]
authorJérôme Gardou <jerome.gardou@reactos.org>
Wed, 14 Jul 2010 09:54:44 +0000 (09:54 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Wed, 14 Jul 2010 09:54:44 +0000 (09:54 +0000)
  - There is no exported "CopyCursor", it's a macro.
  - There is no "NtUserCreateCursorIconHandle" function in win32k. Use correct functions to create a cursorIcon handle.
  - Bring in WINE's CreateIconIndirect
[WIN32K]
  - Dereference CursorIcon Object in NtUserCallOneParam
  - Shared Icons need their bitmaps to be unowned

svn path=/trunk/; revision=48034

reactos/dll/win32/user32/user32.pspec
reactos/dll/win32/user32/windows/cursoricon.c
reactos/subsystems/win32/win32k/ntuser/cursoricon.c
reactos/subsystems/win32/win32k/ntuser/simplecall.c

index d58fb95..8170f9c 100644 (file)
 ; @ stdcall CharNextExW(long wstr long)
 ; @ stdcall CharPrevExW(long wstr wstr long)
 ; @ stub ClientThreadConnect
-@ stdcall CopyCursor(long) ; In msdn it is written, that function is available, but in win 2k3 r2 it is absent
 ; @ stub EnumDisplayDeviceModesA ;(str long ptr long)
 ; @ stub EnumDisplayDeviceModesW ;(wstr long ptr long)
 ; @ stdcall GetMenuIndex(ptr ptr)
index 5e01fe9..52a22a4 100644 (file)
@@ -67,6 +67,25 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 };
 static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 };
 
+/***********************************************************************
+ *                             CreateCursorIconHandle
+ *
+ * Creates a handle with everything in there
+ */
+static
+HICON
+CreateCursorIconHandle( PICONINFO IconInfo )
+{
+       HICON hIcon = (HICON)NtUserCallOneParam(0, //FIXME ?
+                                                                        ONEPARAM_ROUTINE_CREATECURICONHANDLE);
+       if(!hIcon)
+               return NULL;
+
+       NtUserSetCursorContents(hIcon, IconInfo);
+       return hIcon;
+}
+
+
 
 /***********************************************************************
  *             map_fileW
@@ -563,7 +582,7 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi,
        IconInfo.hbmColor = color;
        IconInfo.hbmMask = mask;
 
-       return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
+       return CreateCursorIconHandle(&IconInfo);
 }
 
 
@@ -1386,55 +1405,120 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
     return NtUserGetIconInfo(hIcon, iconinfo, 0, 0, 0, 0);
 }
 
+/* copy an icon bitmap, even when it can't be selected into a DC */
+/* helper for CreateIconIndirect */
+static void stretch_blt_icon( HDC hdc_dst, int dst_x, int dst_y, int dst_width, int dst_height,
+                              HBITMAP src, int width, int height )
+{
+    HDC hdc = CreateCompatibleDC( 0 );
+
+    if (!SelectObject( hdc, src ))  /* do it the hard way */
+    {
+        BITMAPINFO *info;
+        void *bits;
+
+        if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return;
+        info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+        info->bmiHeader.biWidth = width;
+        info->bmiHeader.biHeight = height;
+        info->bmiHeader.biPlanes = GetDeviceCaps( hdc_dst, PLANES );
+        info->bmiHeader.biBitCount = GetDeviceCaps( hdc_dst, BITSPIXEL );
+        info->bmiHeader.biCompression = BI_RGB;
+        info->bmiHeader.biSizeImage = height * get_dib_width_bytes( width, info->bmiHeader.biBitCount );
+        info->bmiHeader.biXPelsPerMeter = 0;
+        info->bmiHeader.biYPelsPerMeter = 0;
+        info->bmiHeader.biClrUsed = 0;
+        info->bmiHeader.biClrImportant = 0;
+        bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
+        if (bits && GetDIBits( hdc, src, 0, height, bits, info, DIB_RGB_COLORS ))
+            StretchDIBits( hdc_dst, dst_x, dst_y, dst_width, dst_height,
+                           0, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
+
+        HeapFree( GetProcessHeap(), 0, bits );
+        HeapFree( GetProcessHeap(), 0, info );
+    }
+    else StretchBlt( hdc_dst, dst_x, dst_y, dst_width, dst_height, hdc, 0, 0, width, height, SRCCOPY );
+
+    DeleteDC( hdc );
+}
+
 /**********************************************************************
  *             CreateIconIndirect (USER32.@)
  */
 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 {
-    BITMAP ColorBitmap;
-       BITMAP MaskBitmap;
-       ICONINFO safeIconInfo;
-
-       if(!iconinfo)
-       {
-               SetLastError(ERROR_INVALID_PARAMETER);
-               return (HICON)0;
-       }
-
-       safeIconInfo = *iconinfo;
-
-       if(!GetObjectW(safeIconInfo.hbmMask, sizeof(BITMAP), &MaskBitmap))
-       {
-               return (HICON)0;
-       }
-
-       /* Try to get color bitmap */
-       if (GetObjectW(safeIconInfo.hbmColor, sizeof(BITMAP), &ColorBitmap))
-       {
-               /* Compare size of color and mask bitmap*/
-               if (ColorBitmap.bmWidth != MaskBitmap.bmWidth ||
-                   ColorBitmap.bmHeight != MaskBitmap.bmHeight)
-               {
-                       ERR("Color and mask size are different!");
-                       SetLastError(ERROR_INVALID_PARAMETER);
-                       return (HICON)0;
-               }
-               /* Test if they are inverted */
-               if(ColorBitmap.bmBitsPixel == 1)
-               {
-                       if(MaskBitmap.bmBitsPixel != 1)
-                       {
-                               safeIconInfo.hbmMask = iconinfo->hbmColor;
-                               safeIconInfo.hbmColor = iconinfo->hbmMask;
-                       }
-                       else
-                       {
-                               /* Wine tests say so */
-                               safeIconInfo.hbmColor = NULL;
-                       }
-               }
-       }
-       return (HICON)NtUserCreateCursorIconHandle(&safeIconInfo, TRUE);
+    BITMAP bmpXor, bmpAnd;
+    HBITMAP color = 0, mask;
+    int width, height;
+    HDC hdc;
+       ICONINFO iinfo;
+
+    TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n",
+           iconinfo->hbmColor, iconinfo->hbmMask,
+           iconinfo->xHotspot, iconinfo->yHotspot, iconinfo->fIcon);
+
+    if (!iconinfo->hbmMask) return 0;
+
+    GetObjectW( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
+    TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
+           bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes,
+           bmpAnd.bmPlanes, bmpAnd.bmBitsPixel);
+
+    if (iconinfo->hbmColor)
+    {
+        GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
+        TRACE("color: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
+               bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes,
+               bmpXor.bmPlanes, bmpXor.bmBitsPixel);
+
+        width = bmpXor.bmWidth;
+        height = bmpXor.bmHeight;
+        if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1)
+        {
+            color = CreateCompatibleBitmap( screen_dc, width, height );
+            mask = CreateBitmap( width, height, 1, 1, NULL );
+        }
+        else mask = CreateBitmap( width, height * 2, 1, 1, NULL );
+    }
+    else
+    {
+        width = bmpAnd.bmWidth;
+        height = bmpAnd.bmHeight;
+        mask = CreateBitmap( width, height, 1, 1, NULL );
+    }
+
+    hdc = CreateCompatibleDC( 0 );
+    SelectObject( hdc, mask );
+    stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmMask, bmpAnd.bmWidth, bmpAnd.bmHeight );
+
+    if (color)
+    {
+        SelectObject( hdc, color );
+        stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmColor, width, height );
+    }
+    else if (iconinfo->hbmColor)
+    {
+        stretch_blt_icon( hdc, 0, height, width, height, iconinfo->hbmColor, width, height );
+    }
+    else height /= 2;
+
+    DeleteDC( hdc );
+
+    iinfo.hbmColor = color ;
+    iinfo.hbmMask = mask ;
+    iinfo.fIcon = iconinfo->fIcon;
+    if (iinfo.fIcon)
+    {
+        iinfo.xHotspot = width / 2;
+        iinfo.yHotspot = height / 2;
+    }
+    else
+    {
+        iinfo.xHotspot = iconinfo->xHotspot;
+        iinfo.yHotspot = iconinfo->yHotspot;
+    }
+
+       return CreateCursorIconHandle(&iinfo);
 }
 
 /******************************************************************************
@@ -2047,23 +2131,6 @@ GetCursorPos(LPPOINT lpPoint)
     return res;
 }
 
-#undef CopyCursor
-/*
- * @implemented
- */
-HCURSOR
-WINAPI
-CopyCursor(HCURSOR pcur)
-{
-    ICONINFO IconInfo;
-
-    if(GetIconInfo((HANDLE)pcur, &IconInfo))
-    {
-        return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE);
-    }
-    return (HCURSOR)0;
-}
-
 /* INTERNAL ******************************************************************/
 
 /* This callback routine is called directly after switching to gui mode */
index f740d32..03f4431 100644 (file)
@@ -1030,11 +1030,13 @@ NtUserSetCursorContents(
     }
 
     /* Delete old bitmaps */
-    if (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)
+    if ((CurIcon->IconInfo.hbmColor)
+               && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
     {
         GreDeleteObject(CurIcon->IconInfo.hbmColor);
     }
-    if (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
+    if ((CurIcon->IconInfo.hbmMask)
+               && (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask))
     {
         GreDeleteObject(CurIcon->IconInfo.hbmMask);
     }
@@ -1226,6 +1228,15 @@ NtUserSetCursorIconData(
     }
 
 done:
+       if(Ret)
+       {
+               /* This icon is shared now */
+               GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
+               if(CurIcon->IconInfo.hbmColor)
+               {
+                       GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
+               }
+       }
     UserDereferenceObject(CurIcon);
     RETURN(Ret);
 
index f46a75d..d25ead5 100644 (file)
@@ -195,6 +195,7 @@ NtUserCallOneParam(
       case ONEPARAM_ROUTINE_CREATECURICONHANDLE:
          {
             PCURICON_OBJECT CurIcon;
+                       DWORD_PTR Result ;
 
             if (!(CurIcon = IntCreateCurIconHandle()))
             {
@@ -202,7 +203,9 @@ NtUserCallOneParam(
                RETURN(0);
             }
 
-            RETURN((DWORD_PTR)CurIcon->Self);
+            Result = (DWORD_PTR)CurIcon->Self;
+                       UserDereferenceObject(CurIcon);
+                       RETURN(Result);
          }
 
       case ONEPARAM_ROUTINE_GETCURSORPOSITION: