Author: jgardou Date: Wed Jul 14 09:54:44 2010 New Revision: 48034
URL: http://svn.reactos.org/svn/reactos?rev=48034&view=rev Log: [USER32] - 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
Modified: trunk/reactos/dll/win32/user32/user32.pspec trunk/reactos/dll/win32/user32/windows/cursoricon.c trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c
Modified: trunk/reactos/dll/win32/user32/user32.pspec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/user32.psp... ============================================================================== --- trunk/reactos/dll/win32/user32/user32.pspec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/user32.pspec [iso-8859-1] Wed Jul 14 09:54:44 2010 @@ -759,7 +759,6 @@ ; @ 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)
Modified: trunk/reactos/dll/win32/user32/windows/cursoricon.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/cu... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/cursoricon.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/windows/cursoricon.c [iso-8859-1] Wed Jul 14 09:54:44 2010 @@ -66,6 +66,25 @@ 0, 0, { (DWORD_PTR)(__FILE__ ": IconCrst") } }; 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; +} +
/*********************************************************************** @@ -563,7 +582,7 @@ IconInfo.hbmColor = color; IconInfo.hbmMask = mask;
- return NtUserCreateCursorIconHandle(&IconInfo, FALSE); + return CreateCursorIconHandle(&IconInfo); }
@@ -1386,55 +1405,120 @@ 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 @@ 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 */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] Wed Jul 14 09:54:44 2010 @@ -1030,11 +1030,13 @@ }
/* 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 @@ }
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);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] Wed Jul 14 09:54:44 2010 @@ -195,6 +195,7 @@ case ONEPARAM_ROUTINE_CREATECURICONHANDLE: { PCURICON_OBJECT CurIcon; + DWORD_PTR Result ;
if (!(CurIcon = IntCreateCurIconHandle())) { @@ -202,7 +203,9 @@ RETURN(0); }
- RETURN((DWORD_PTR)CurIcon->Self); + Result = (DWORD_PTR)CurIcon->Self; + UserDereferenceObject(CurIcon); + RETURN(Result); }
case ONEPARAM_ROUTINE_GETCURSORPOSITION: