winehq.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
January
2003
December
November
October
September
August
July
June
May
April
March
February
January
2002
December
November
October
September
August
July
June
May
April
March
February
January
2001
December
November
October
September
August
July
June
May
April
March
February
List overview
wine-commits
February 2022
----- 2025 -----
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
January 2004
----- 2003 -----
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
----- 2002 -----
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
January 2002
----- 2001 -----
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
wine-commits@winehq.org
2 participants
1495 discussions
Start a n
N
ew thread
Jacek Caban : user32: Use create_cursoricon_object in CURSORICON_CreateIconFromANI.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: a771eb4405f45e7042ee1b93f7373b2f507d0b71 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=a771eb4405f45e7042ee1b93…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:42:16 2022 +0100 user32: Use create_cursoricon_object in CURSORICON_CreateIconFromANI. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 122 ++++++++++------------------------------------- 1 file changed, 24 insertions(+), 98 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 8b74f7ba4e8..5eb7ddc695a 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -109,34 +109,6 @@ static int get_display_bpp(void) return ret; } -static HICON alloc_icon_handle( BOOL is_ani, UINT num_steps ) -{ - struct cursoricon_object *obj; - HICON handle; - - if (!(obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj) ))) return NULL; - obj->delay = 0; - obj->is_ani = is_ani; - if (is_ani) - { - if (!(obj->ani.frames = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - num_steps * sizeof(*obj->ani.frames) ))) - { - HeapFree( GetProcessHeap(), 0, obj ); - return NULL; - } - obj->ani.num_steps = num_steps; - obj->ani.num_frames = num_steps; /* changed later for some animated cursors */ - } - - if (!(handle = alloc_user_handle( &obj->obj, NTUSER_OBJ_ICON ))) - { - if (obj->is_ani) HeapFree( GetProcessHeap(), 0, obj->ani.frames ); - HeapFree( GetProcessHeap(), 0, obj ); - } - return handle; -} - static struct cursoricon_object *get_icon_ptr( HICON handle ) { struct cursoricon_object *obj = get_user_handle_ptr( handle, NTUSER_OBJ_ICON ); @@ -990,6 +962,7 @@ BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNI memset( &frame_desc, 0, sizeof(frame_desc) ); frame_desc.delay = desc->frame_rates ? desc->frame_rates[i] : desc->delay; frame_desc.frames = &desc->frames[frame_id]; + frame_desc.frames->delay = frame_desc.delay; /* FIXME */ if (!(obj->ani.frames[i] = alloc_cursoricon_handle( obj->is_icon )) || !NtUserSetCursorIconData( obj->ani.frames[i], NULL, NULL, &frame_desc )) { @@ -1446,15 +1419,11 @@ static void riff_find_chunk( DWORD chunk_id, DWORD chunk_type, const riff_chunk_ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, INT width, INT height, INT depth, BOOL is_icon, UINT loadflags ) { - struct cursoricon_object *info; - DWORD *frame_rates = NULL; - DWORD *frame_seq = NULL; + struct cursoricon_desc desc = { 0 }; ani_header header; - BOOL use_seq = FALSE; HCURSOR cursor; UINT i; BOOL error = FALSE; - HICON *frames; riff_chunk_t root_chunk = { bits_size, bits }; riff_chunk_t ACON_chunk = {0}; @@ -1494,8 +1463,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, riff_find_chunk( ANI_seq__ID, 0, &ACON_chunk, &seq_chunk ); if (seq_chunk.data) { - frame_seq = (DWORD *) seq_chunk.data; - use_seq = TRUE; + desc.frame_seq = (DWORD *)seq_chunk.data; } else { @@ -1506,7 +1474,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, riff_find_chunk( ANI_rate_ID, 0, &ACON_chunk, &rate_chunk ); if (rate_chunk.data) - frame_rates = (DWORD *) rate_chunk.data; + desc.frame_rates = (DWORD *)rate_chunk.data; riff_find_chunk( ANI_fram_ID, ANI_LIST_ID, &ACON_chunk, &fram_chunk ); if (!fram_chunk.data) @@ -1515,25 +1483,16 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, return 0; } - cursor = alloc_icon_handle( TRUE, header.num_steps ); - if (!cursor) return 0; - frames = HeapAlloc( GetProcessHeap(), 0, sizeof(*frames) * header.num_frames ); - if (!frames) - { - free_icon_handle( cursor ); - return 0; - } - - info = get_icon_ptr( cursor ); - info->is_icon = is_icon; - info->ani.num_frames = header.num_frames; - /* The .ANI stores the display rate in jiffies (1/60s) */ - info->delay = header.display_rate; + desc.delay = header.display_rate; + desc.num_frames = header.num_frames; + desc.num_steps = header.num_steps; + if (!(desc.frames = HeapAlloc( GetProcessHeap(), 0, sizeof(*desc.frames) * desc.num_frames ))) + return 0; icon_chunk = fram_chunk.data; icon_data = fram_chunk.data + (2 * sizeof(DWORD)); - for (i=0; i<header.num_frames; i++) + for (i = 0; i < desc.num_frames; i++) { const DWORD chunk_size = *(const DWORD *)(icon_chunk + sizeof(DWORD)); const CURSORICONFILEDIRENTRY *entry; @@ -1558,29 +1517,28 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, frameHeight = header.height; } - frames[i] = NULL; - if (entry->dwDIBOffset < bits + bits_size - icon_data) + if (!(error = entry->dwDIBOffset >= bits + bits_size - icon_data)) { bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset); /* Grab a frame from the animation */ - frames[i] = create_icon_from_bmi( bmi, bits + bits_size - (const BYTE *)bmi, - NULL, NULL, NULL, hotspot, - is_icon, frameWidth, frameHeight, loadflags ); + error = !create_icon_frame( bmi, bits + bits_size - (const BYTE *)bmi, hotspot, + is_icon, frameWidth, frameHeight, loadflags, &desc.frames[i] ); } - if (!frames[i]) + if (error) { - FIXME_(cursor)("failed to convert animated cursor frame.\n"); - error = TRUE; if (i == 0) { FIXME_(cursor)("Completely failed to create animated cursor!\n"); - info->ani.num_frames = 0; - release_user_handle_ptr( info ); - free_icon_handle( cursor ); - HeapFree( GetProcessHeap(), 0, frames ); + HeapFree( GetProcessHeap(), 0, desc.frames ); return 0; } + /* There was an error but we at least decoded the first frame, so just use that frame */ + FIXME_(cursor)("Error creating animated cursor, only using first frame!\n"); + while (i > 1) free_icon_frame( &desc.frames[--i] ); + desc.num_frames = desc.num_steps = 1; + desc.frame_seq = NULL; + desc.delay = 0; break; } @@ -1589,41 +1547,9 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, icon_data = icon_chunk + (2 * sizeof(DWORD)); } - /* There was an error but we at least decoded the first frame, so just use that frame */ - if (error) - { - FIXME_(cursor)("Error creating animated cursor, only using first frame!\n"); - for (i=1; i < info->ani.num_frames; i++) - free_icon_handle( info->ani.frames[i] ); - use_seq = FALSE; - info->delay = 0; - info->ani.num_steps = 1; - info->ani.num_frames = 1; - } - - /* Setup the animated frames in the correct sequence */ - for (i=0; i < info->ani.num_steps; i++) - { - DWORD frame_id = use_seq ? frame_seq[i] : i; - struct cursoricon_frame *frame; - - if (frame_id >= info->ani.num_frames) - { - frame_id = info->ani.num_frames-1; - ERR_(cursor)("Sequence indicates frame past end of list, corrupt?\n"); - } - info->ani.frames[i] = frames[frame_id]; - frame = get_icon_frame( info, i ); - if (frame_rates) - frame->delay = frame_rates[i]; - else - frame->delay = ~0; - release_icon_frame( info, frame ); - } - - HeapFree( GetProcessHeap(), 0, frames ); - release_user_handle_ptr( info ); - + cursor = create_cursoricon_object( &desc, is_icon, 0, 0, 0 ); + if (!cursor) for (i = 0; i < desc.num_frames; i++) free_icon_frame( &desc.frames[i] ); + HeapFree( GetProcessHeap(), 0, desc.frames ); return cursor; }
1
0
0
0
Jacek Caban : user32: Use create_cursoricon_object in CreateIconIndirect.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: a37a0a94d40367b4885ea7438ac191c2aca9ae27 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=a37a0a94d40367b4885ea743…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:41:52 2022 +0100 user32: Use create_cursoricon_object in CreateIconIndirect. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 73 ++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 556bc1b0f91..8b74f7ba4e8 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -2373,10 +2373,10 @@ static void stretch_blt_icon( HDC hdc_dst, int dst_x, int dst_y, int dst_width, */ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) { + struct cursoricon_frame frame = { 0 }; + struct cursoricon_desc desc = { .frames = &frame }; BITMAP bmpXor, bmpAnd; - HICON hObj; - HBITMAP color = 0, mask; - int width, height; + HICON ret; HDC hdc; TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n", @@ -2397,59 +2397,48 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes, bmpXor.bmPlanes, bmpXor.bmBitsPixel); - width = bmpXor.bmWidth; - height = bmpXor.bmHeight; - color = create_color_bitmap( width, height ); + frame.width = bmpXor.bmWidth; + frame.height = bmpXor.bmHeight; + frame.color = create_color_bitmap( frame.width, frame.height ); } else { - width = bmpAnd.bmWidth; - height = bmpAnd.bmHeight; + frame.width = bmpAnd.bmWidth; + frame.height = bmpAnd.bmHeight; } - mask = CreateBitmap( width, height, 1, 1, NULL ); + frame.mask = CreateBitmap( frame.width, frame.height, 1, 1, NULL ); hdc = CreateCompatibleDC( 0 ); - SelectObject( hdc, mask ); - stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmMask, bmpAnd.bmWidth, bmpAnd.bmHeight ); + SelectObject( hdc, frame.mask ); + stretch_blt_icon( hdc, 0, 0, frame.width, frame.height, iconinfo->hbmMask, + bmpAnd.bmWidth, bmpAnd.bmHeight ); - if (color) + if (frame.color) { - SelectObject( hdc, color ); - stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmColor, width, height ); + SelectObject( hdc, frame.color ); + stretch_blt_icon( hdc, 0, 0, frame.width, frame.height, iconinfo->hbmColor, + frame.width, frame.height ); } - else height /= 2; + else frame.height /= 2; DeleteDC( hdc ); - hObj = alloc_icon_handle( FALSE, 0 ); - if (hObj) - { - struct cursoricon_object *info = get_icon_ptr( hObj ); - struct cursoricon_frame *frame; - - info->is_icon = iconinfo->fIcon; - frame = get_icon_frame( info, 0 ); - frame->delay = ~0; - frame->width = width; - frame->height = height; - frame->color = color; - frame->mask = mask; - frame->alpha = create_alpha_bitmap( iconinfo->hbmColor, NULL, NULL ); - if (info->is_icon) - { - frame->hotspot.x = width / 2; - frame->hotspot.y = height / 2; - } - else - { - frame->hotspot.x = iconinfo->xHotspot; - frame->hotspot.y = iconinfo->yHotspot; - } + frame.alpha = create_alpha_bitmap( iconinfo->hbmColor, NULL, NULL ); - release_icon_frame( info, frame ); - release_user_handle_ptr( info ); + if (iconinfo->fIcon) + { + frame.hotspot.x = frame.width / 2; + frame.hotspot.y = frame.height / 2; + } + else + { + frame.hotspot.x = iconinfo->xHotspot; + frame.hotspot.y = iconinfo->yHotspot; } - return hObj; + + ret = create_cursoricon_object( &desc, iconinfo->fIcon, 0, 0, 0 ); + if (!ret) free_icon_frame( &frame ); + return ret; } /******************************************************************************
1
0
0
0
Jacek Caban : user32: Introduce NtUserSetCursorIconData.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: f0176397adde8856c9149265121bd0b710c209cb URL:
https://source.winehq.org/git/wine.git/?a=commit;h=f0176397adde8856c9149265…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:41:40 2022 +0100 user32: Introduce NtUserSetCursorIconData. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 196 ++++++++++++++++++++++++++++++++++++----------- include/ntuser.h | 15 ++++ 2 files changed, 168 insertions(+), 43 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index b629e1412ae..556bc1b0f91 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -904,6 +904,123 @@ static const CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( const CURSORIC return &dir->idEntries[n]; } +static HICON alloc_cursoricon_handle( BOOL is_icon ) +{ + struct cursoricon_object *obj; + HICON handle; + + if (!(obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj) ))) return NULL; + obj->is_icon = is_icon; + + if (!(handle = alloc_user_handle( &obj->obj, NTUSER_OBJ_ICON ))) free( obj ); + return handle; +} + +/*********************************************************************** + * NtUserSetCursorIconData (win32u.@) + */ +BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNICODE_STRING *res_name, + struct cursoricon_desc *desc ) +{ + struct cursoricon_object *obj; + UINT i, j; + + if (!(obj = get_icon_ptr( cursor ))) return FALSE; + + if (obj->is_ani || obj->frame.width) + { + /* already initialized */ + release_user_handle_ptr( obj ); + SetLastError( ERROR_INVALID_CURSOR_HANDLE ); + return FALSE; + } + + obj->delay = desc->delay; + + if (desc->num_steps) + { + if (!(obj->ani.frames = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + desc->num_steps * sizeof(*obj->ani.frames) ))) + { + release_user_handle_ptr( obj ); + return FALSE; + } + obj->is_ani = TRUE; + obj->ani.num_steps = desc->num_steps; + obj->ani.num_frames = desc->num_frames; + } + else obj->frame = desc->frames[0]; + + if (!res_name) + obj->resname = NULL; + else if (res_name->Length) + { + obj->resname = HeapAlloc( GetProcessHeap(), 0, res_name->Length + sizeof(WCHAR) ); + if (obj->resname) + { + memcpy( obj->resname, res_name->Buffer, res_name->Length ); + obj->resname[res_name->Length / sizeof(WCHAR)] = 0; + } + } + else + obj->resname = MAKEINTRESOURCEW( LOWORD(res_name->Buffer) ); + + if (module && module->Length && (obj->module.Buffer = HeapAlloc( GetProcessHeap(), 0, module->Length ))) + { + memcpy( obj->module.Buffer, module->Buffer, module->Length ); + obj->module.Length = module->Length; + } + + if (obj->is_ani) + { + /* Setup the animated frames in the correct sequence */ + for (i = 0; i < desc->num_steps; i++) + { + struct cursoricon_desc frame_desc; + DWORD frame_id; + + if (obj->ani.frames[i]) continue; /* already set */ + + frame_id = desc->frame_seq ? desc->frame_seq[i] : i; + if (frame_id >= obj->ani.num_frames) + { + frame_id = obj->ani.num_frames - 1; + ERR_(cursor)( "Sequence indicates frame past end of list, corrupt?\n" ); + } + memset( &frame_desc, 0, sizeof(frame_desc) ); + frame_desc.delay = desc->frame_rates ? desc->frame_rates[i] : desc->delay; + frame_desc.frames = &desc->frames[frame_id]; + if (!(obj->ani.frames[i] = alloc_cursoricon_handle( obj->is_icon )) || + !NtUserSetCursorIconData( obj->ani.frames[i], NULL, NULL, &frame_desc )) + { + release_user_handle_ptr( obj ); + return 0; + } + + if (desc->frame_seq) + { + for (j = i + 1; j < obj->ani.num_steps; j++) + { + if (desc->frame_seq[j] == frame_id) obj->ani.frames[j] = obj->ani.frames[i]; + } + } + } + } + + if (desc->flags & LR_SHARED) + { + obj->is_shared = TRUE; + if (obj->module.Length) + { + obj->rsrc = desc->rsrc; + list_add_head( &icon_cache, &obj->entry ); + } + } + + release_user_handle_ptr( obj ); + return TRUE; +} + /*********************************************************************** * bmi_has_alpha */ @@ -1167,6 +1284,35 @@ done: return ret; } +static HICON create_cursoricon_object( struct cursoricon_desc *desc, BOOL is_icon, HINSTANCE module, + const WCHAR *resname, HRSRC rsrc ) +{ + WCHAR buf[MAX_PATH]; + UNICODE_STRING module_name = { 0, sizeof(buf), buf }; + UNICODE_STRING res_str = { 0 }; + HICON handle; + + if (!(handle = alloc_cursoricon_handle( is_icon ))) return 0; + + if (module) LdrGetDllFullName( module, &module_name ); + + res_str.Buffer = (WCHAR *)resname; + if (!IS_INTRESOURCE(resname)) + { + res_str.Length = lstrlenW( resname ) * sizeof(WCHAR); + res_str.MaximumLength = res_str.Length + sizeof(WCHAR); + } + desc->rsrc = rsrc; /* FIXME: we should probably avoid storing rsrc */ + + if (!NtUserSetCursorIconData( handle, &module_name, &res_str, desc )) + { + DestroyCursor( handle ); + return 0; + } + + return handle; +} + /*********************************************************************** * create_icon_from_bmi * @@ -1177,53 +1323,17 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE UINT flags ) { struct cursoricon_frame frame; + struct cursoricon_desc desc = + { + .flags = flags, + .frames = &frame, + }; HICON ret; if (!create_icon_frame( bmi, maxsize, hotspot, bIcon, width, height, flags, &frame )) return 0; - ret = alloc_icon_handle( FALSE, 0 ); - if (ret) - { - struct cursoricon_object *info = get_icon_ptr( ret ); - - info->is_icon = bIcon; - info->frame = frame; - - if (!IS_INTRESOURCE(resname)) - { - info->resname = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(resname) + 1) * sizeof(WCHAR) ); - if (info->resname) lstrcpyW( info->resname, resname ); - } - else info->resname = MAKEINTRESOURCEW( LOWORD(resname) ); - - if (module) - { - WCHAR buf[MAX_PATH]; - UNICODE_STRING module_name = { 0, sizeof(buf), buf }; - - if (!LdrGetDllFullName( module, &module_name ) && - (info->module.Buffer = HeapAlloc( GetProcessHeap(), 0, module_name.Length ))) - { - memcpy( info->module.Buffer, module_name.Buffer, module_name.Length ); - info->module.Length = module_name.Length; - } - } - - if (flags & LR_SHARED) - { - info->is_shared = TRUE; - if (module) - { - info->rsrc = rsrc; - list_add_head( &icon_cache, &info->entry ); - } - } - release_user_handle_ptr( info ); - } - else - { - free_icon_frame( &frame ); - } + ret = create_cursoricon_object( &desc, bIcon, module, resname, rsrc ); + if (!ret) free_icon_frame( &frame ); return ret; } diff --git a/include/ntuser.h b/include/ntuser.h index c34270653ea..a54da6095f1 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -113,6 +113,19 @@ enum #define NTUSER_OBJ_ACCEL 0x08 #define NTUSER_OBJ_HOOK 0x0f +/* NtUserSetCursorIconData parameter, not compatible with Windows */ +struct cursoricon_desc +{ + UINT flags; + UINT num_steps; + UINT num_frames; + UINT delay; + struct cursoricon_frame *frames; + DWORD *frame_seq; + DWORD *frame_rates; + HRSRC rsrc; +}; + /* internal messages codes */ enum wine_internal_message { @@ -199,6 +212,8 @@ HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str ); BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip, HRGN ret_update_rgn, RECT *update_rect ); HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE palette, WORD force_background ); +BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNICODE_STRING *res_name, + struct cursoricon_desc *desc ); BOOL WINAPI NtUserSetCursorPos( INT x, INT y ); BOOL WINAPI NtUserSetKeyboardState( BYTE *state ); BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unknown );
1
0
0
0
Jacek Caban : user32: Factor out create_icon_frame.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: 8ce4c07f507984bd948d2f525c5a3825824e4eab URL:
https://source.winehq.org/git/wine.git/?a=commit;h=8ce4c07f507984bd948d2f52…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:41:01 2022 +0100 user32: Factor out create_icon_frame. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 134 ++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 70 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index d2739278f21..b629e1412ae 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -173,6 +173,13 @@ static UINT get_icon_steps( struct cursoricon_object *obj ) return obj->is_ani ? obj->ani.num_steps : 1; } +static void free_icon_frame( struct cursoricon_frame *frame ) +{ + if (frame->color) DeleteObject( frame->color ); + if (frame->alpha) DeleteObject( frame->alpha ); + if (frame->mask) DeleteObject( frame->mask ); +} + static BOOL free_icon_handle( HICON handle ) { struct cursoricon_object *obj = free_user_handle( handle, NTUSER_OBJ_ICON ); @@ -187,12 +194,7 @@ static BOOL free_icon_handle( HICON handle ) if (!obj->is_ani) { - struct cursoricon_frame *frame = get_icon_frame( obj, 0 ); - - if (frame->alpha) DeleteObject( frame->alpha ); - if (frame->color) DeleteObject( frame->color ); - DeleteObject( frame->mask ); - release_icon_frame( obj, frame ); + free_icon_frame( &obj->frame ); } else { @@ -984,54 +986,42 @@ done: return alpha; } - -/*********************************************************************** - * create_icon_from_bmi - * - * Create an icon from its BITMAPINFO. - */ -static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname, - HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height, - UINT cFlag ) +static BOOL create_icon_frame( const BITMAPINFO *bmi, DWORD maxsize, POINT hotspot, BOOL is_icon, + INT width, INT height, UINT flags, struct cursoricon_frame *frame ) { - DWORD size, color_size, mask_size; - HBITMAP color = 0, mask = 0, alpha = 0; + DWORD size, color_size, mask_size, compr; const void *color_bits, *mask_bits; void *alpha_mask_bits = NULL; + LONG bmi_width, bmi_height; BITMAPINFO *bmi_copy; - BOOL ret = FALSE; BOOL do_stretch; - HICON hObj = 0; HDC hdc = 0; - LONG bmi_width, bmi_height; WORD bpp; - DWORD compr; + BOOL ret = FALSE; + + memset( frame, 0, sizeof(*frame) ); /* Check bitmap header */ if (bmi->bmiHeader.biSize == PNG_SIGN) { - BITMAPINFO *bmi_png = load_png( (const char *)bmi, &maxsize ); + BITMAPINFO *bmi_png; - if (bmi_png) - { - hObj = create_icon_from_bmi( bmi_png, maxsize, module, resname, - rsrc, hotspot, bIcon, width, height, cFlag ); - HeapFree( GetProcessHeap(), 0, bmi_png ); - return hObj; - } - return 0; + if (!(bmi_png = load_png( (const char *)bmi, &maxsize ))) return FALSE; + ret = create_icon_frame( bmi_png, maxsize, hotspot, is_icon, width, height, flags, frame ); + HeapFree( GetProcessHeap(), 0, bmi_png ); + return ret; } if (maxsize < sizeof(BITMAPCOREHEADER)) { WARN( "invalid size %u\n", maxsize ); - return 0; + return FALSE; } if (maxsize < bmi->bmiHeader.biSize) { WARN( "invalid header size %u\n", bmi->bmiHeader.biSize ); - return 0; + return FALSE; } if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || @@ -1039,7 +1029,7 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE bmi->bmiHeader.biCompression != BI_BITFIELDS)) ) { WARN( "invalid bitmap header %u\n", bmi->bmiHeader.biSize ); - return 0; + return FALSE; } size = bitmap_info_size( bmi, DIB_RGB_COLORS ); @@ -1054,21 +1044,20 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE } if (mask_size > maxsize - size - color_size) mask_size = 0; /* no mask */ - if (cFlag & LR_DEFAULTSIZE) + if (flags & LR_DEFAULTSIZE) { - if (!width) width = GetSystemMetrics( bIcon ? SM_CXICON : SM_CXCURSOR ); - if (!height) height = GetSystemMetrics( bIcon ? SM_CYICON : SM_CYCURSOR ); + if (!width) width = GetSystemMetrics( is_icon ? SM_CXICON : SM_CXCURSOR ); + if (!height) height = GetSystemMetrics( is_icon ? SM_CYICON : SM_CYCURSOR ); } else { if (!width) width = bmi_width; if (!height) height = bmi_height/2; } - do_stretch = (bmi_height/2 != height) || - (bmi_width != width); + do_stretch = (bmi_height/2 != height) || (bmi_width != width); /* Scale the hotspot */ - if (bIcon) + if (is_icon) { hotspot.x = width / 2; hotspot.y = height / 2; @@ -1093,34 +1082,28 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE color_bits = (const char*)bmi + size; mask_bits = (const char*)color_bits + color_size; - alpha = 0; if (is_dib_monochrome( bmi )) { - if (!(mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; - color = 0; + if (!(frame->mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; /* copy color data into second half of mask bitmap */ - SelectObject( hdc, mask ); + SelectObject( hdc, frame->mask ); StretchDIBits( hdc, 0, height, width, height, 0, 0, bmi_width, bmi_height, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } else { - if (!(mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done; - if (!(color = create_color_bitmap( width, height ))) - { - DeleteObject( mask ); - goto done; - } - SelectObject( hdc, color ); + if (!(frame->mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done; + if (!(frame->color = create_color_bitmap( width, height ))) goto done; + SelectObject( hdc, frame->color ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_width, bmi_height, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); if (bmi_has_alpha( bmi_copy, color_bits )) { - alpha = create_alpha_bitmap( color, bmi_copy, color_bits ); + frame->alpha = create_alpha_bitmap( frame->color, bmi_copy, color_bits ); if (!mask_size) /* generate mask from alpha */ { LONG x, y, dst_stride = ((bmi_width + 31) / 8) & ~3; @@ -1164,35 +1147,48 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE if (mask_size) { - SelectObject( hdc, mask ); + SelectObject( hdc, frame->mask ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_width, bmi_height, mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } + + frame->delay = ~0; + frame->width = width; + frame->height = height; + frame->hotspot = hotspot; ret = TRUE; done: + if (!ret) free_icon_frame( frame ); DeleteDC( hdc ); HeapFree( GetProcessHeap(), 0, bmi_copy ); HeapFree( GetProcessHeap(), 0, alpha_mask_bits ); + return ret; +} + +/*********************************************************************** + * create_icon_from_bmi + * + * Create an icon from its BITMAPINFO. + */ +static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname, + HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height, + UINT flags ) +{ + struct cursoricon_frame frame; + HICON ret; + if (!create_icon_frame( bmi, maxsize, hotspot, bIcon, width, height, flags, &frame )) return 0; + + ret = alloc_icon_handle( FALSE, 0 ); if (ret) - hObj = alloc_icon_handle( FALSE, 0 ); - if (hObj) { - struct cursoricon_object *info = get_icon_ptr( hObj ); - struct cursoricon_frame *frame; + struct cursoricon_object *info = get_icon_ptr( ret ); info->is_icon = bIcon; - frame = get_icon_frame( info, 0 ); - frame->delay = ~0; - frame->width = width; - frame->height = height; - frame->color = color; - frame->mask = mask; - frame->alpha = alpha; - frame->hotspot = hotspot; - release_icon_frame( info, frame ); + info->frame = frame; + if (!IS_INTRESOURCE(resname)) { info->resname = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(resname) + 1) * sizeof(WCHAR) ); @@ -1213,7 +1209,7 @@ done: } } - if (cFlag & LR_SHARED) + if (flags & LR_SHARED) { info->is_shared = TRUE; if (module) @@ -1226,11 +1222,9 @@ done: } else { - DeleteObject( color ); - DeleteObject( alpha ); - DeleteObject( mask ); + free_icon_frame( &frame ); } - return hObj; + return ret; }
1
0
0
0
Jacek Caban : user32: Simplify cursor hotspot handling.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: 064838c5809ee8d43a202ce4ec72465f649e3b91 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=064838c5809ee8d43a202ce4…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:40:42 2022 +0100 user32: Simplify cursor hotspot handling. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 8f8774b0b4e..d2739278f21 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -66,6 +66,7 @@ struct cursoricon_frame HBITMAP color; /* color bitmap */ HBITMAP alpha; /* pre-multiplied alpha bitmap for 32-bpp icons */ HBITMAP mask; /* mask bitmap (followed by color for 1-bpp icons) */ + POINT hotspot; }; struct cursoricon_object @@ -80,7 +81,6 @@ struct cursoricon_object BOOL is_icon; /* whether icon or cursor */ BOOL is_ani; /* whether this object is a static cursor or an animated cursor */ UINT delay; /* delay between this frame and the next (in jiffies) */ - POINT hotspot; union { struct cursoricon_frame frame; /* frame-specific icon data */ @@ -1184,7 +1184,6 @@ done: struct cursoricon_frame *frame; info->is_icon = bIcon; - info->hotspot = hotspot; frame = get_icon_frame( info, 0 ); frame->delay = ~0; frame->width = width; @@ -1192,6 +1191,7 @@ done: frame->color = color; frame->mask = mask; frame->alpha = alpha; + frame->hotspot = hotspot; release_icon_frame( info, frame ); if (!IS_INTRESOURCE(resname)) { @@ -1435,13 +1435,14 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, const CURSORICONFILEDIRENTRY *entry; INT frameWidth, frameHeight; const BITMAPINFO *bmi; + POINT hotspot; entry = CURSORICON_FindBestIconFile((const CURSORICONFILEDIR *) icon_data, bits + bits_size - icon_data, width, height, depth, loadflags ); - info->hotspot.x = entry->xHotspot; - info->hotspot.y = entry->yHotspot; + hotspot.x = entry->xHotspot; + hotspot.y = entry->yHotspot; if (!header.width || !header.height) { frameWidth = entry->bWidth; @@ -1459,7 +1460,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset); /* Grab a frame from the animation */ frames[i] = create_icon_from_bmi( bmi, bits + bits_size - (const BYTE *)bmi, - NULL, NULL, NULL, info->hotspot, + NULL, NULL, NULL, hotspot, is_icon, frameWidth, frameHeight, loadflags ); } @@ -2201,8 +2202,8 @@ BOOL WINAPI GetIconInfoExW( HICON icon, ICONINFOEXW *info ) TRACE("%p => %dx%d\n", icon, frame->width, frame->height); info->fIcon = ptr->is_icon; - info->xHotspot = ptr->hotspot.x; - info->yHotspot = ptr->hotspot.y; + info->xHotspot = frame->hotspot.x; + info->yHotspot = frame->hotspot.y; info->hbmColor = copy_bitmap( frame->color ); info->hbmMask = copy_bitmap( frame->mask ); info->wResID = 0; @@ -2330,18 +2331,18 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) frame->color = color; frame->mask = mask; frame->alpha = create_alpha_bitmap( iconinfo->hbmColor, NULL, NULL ); - release_icon_frame( info, frame ); if (info->is_icon) { - info->hotspot.x = width / 2; - info->hotspot.y = height / 2; + frame->hotspot.x = width / 2; + frame->hotspot.y = height / 2; } else { - info->hotspot.x = iconinfo->xHotspot; - info->hotspot.y = iconinfo->yHotspot; + frame->hotspot.x = iconinfo->xHotspot; + frame->hotspot.y = iconinfo->yHotspot; } + release_icon_frame( info, frame ); release_user_handle_ptr( info ); } return hObj; @@ -3052,8 +3053,8 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, } info.fIcon = icon->is_icon; - info.xHotspot = icon->hotspot.x; - info.yHotspot = icon->hotspot.y; + info.xHotspot = frame->hotspot.x; + info.yHotspot = frame->hotspot.y; if (desiredx == frame->width && desiredy == frame->height) {
1
0
0
0
Jacek Caban : user32: Use ntuser object type constants.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: b86842bb15775ce8df997aafe44d6a52a5c0d2a3 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=b86842bb15775ce8df997aaf…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:40:33 2022 +0100 user32: Use ntuser object type constants. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 10 +++++----- dlls/user32/menu.c | 8 ++++---- dlls/user32/resource.c | 10 +++++----- dlls/user32/user_private.h | 19 +++++-------------- dlls/user32/win.c | 14 +++++++------- dlls/user32/winpos.c | 6 +++--- include/ntuser.h | 8 ++++++++ 7 files changed, 37 insertions(+), 38 deletions(-) Diff:
https://source.winehq.org/git/wine.git/?a=commitdiff;h=b86842bb15775ce8df99…
1
0
0
0
Jacek Caban : user32: Store module as unicode string in cursoricon_object.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: dd2dd0066519800373b2f26100ecb6bd7b0ee33b URL:
https://source.winehq.org/git/wine.git/?a=commit;h=dd2dd0066519800373b2f261…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:40:22 2022 +0100 user32: Store module as unicode string in cursoricon_object. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 51 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 2b421cd1bf1..6da3e398db1 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -73,7 +73,7 @@ struct cursoricon_object struct user_object obj; /* object header */ struct list entry; /* entry in shared icons list */ ULONG_PTR param; /* opaque param used by 16-bit code */ - HMODULE module; /* module for icons loaded from resources */ + UNICODE_STRING module; /* module for icons loaded from resources */ LPWSTR resname; /* resource name for icons loaded from resources */ HRSRC rsrc; /* resource for shared icons */ BOOL is_shared; /* whether this object is shared */ @@ -1184,7 +1184,6 @@ done: struct cursoricon_frame *frame; info->is_icon = bIcon; - info->module = module; info->hotspot = hotspot; frame = get_icon_frame( info, 0 ); frame->delay = ~0; @@ -1201,6 +1200,19 @@ done: } else info->resname = MAKEINTRESOURCEW( LOWORD(resname) ); + if (module) + { + WCHAR buf[MAX_PATH]; + UNICODE_STRING module_name = { 0, sizeof(buf), buf }; + + if (!LdrGetDllFullName( module, &module_name ) && + (info->module.Buffer = HeapAlloc( GetProcessHeap(), 0, module_name.Length ))) + { + memcpy( info->module.Buffer, module_name.Buffer, module_name.Length ); + info->module.Length = module_name.Length; + } + } + if (cFlag & LR_SHARED) { info->is_shared = TRUE; @@ -1687,18 +1699,24 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, /* If shared icon, check whether it was already loaded */ if (loadflags & LR_SHARED) { + WCHAR buf[MAX_PATH]; + UNICODE_STRING module = { 0, sizeof(buf) - sizeof(WCHAR), buf }; struct cursoricon_object *ptr; - USER_Lock(); - LIST_FOR_EACH_ENTRY( ptr, &icon_cache, struct cursoricon_object, entry ) + if (!LdrGetDllFullName( hInstance, &module )) { - if (ptr->module != hInstance) continue; - if (ptr->rsrc != hRsrc) continue; - hIcon = ptr->obj.handle; - break; + USER_Lock(); + LIST_FOR_EACH_ENTRY( ptr, &icon_cache, struct cursoricon_object, entry ) + { + if (ptr->module.Length != module.Length) continue; + if (memcmp( ptr->module.Buffer, module.Buffer, module.Length )) continue; + if (ptr->rsrc != hRsrc) continue; + hIcon = ptr->obj.handle; + break; + } + USER_Unlock(); + if (hIcon) return hIcon; } - USER_Unlock(); - if (hIcon) return hIcon; } if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; @@ -2159,7 +2177,6 @@ BOOL WINAPI GetIconInfoExW( HICON icon, ICONINFOEXW *info ) { struct cursoricon_frame *frame; struct cursoricon_object *ptr; - HMODULE module; BOOL ret = TRUE; if (info->cbSize != sizeof(*info)) @@ -2191,10 +2208,12 @@ BOOL WINAPI GetIconInfoExW( HICON icon, ICONINFOEXW *info ) info->wResID = 0; info->szModName[0] = 0; info->szResName[0] = 0; - if (ptr->module) + if (ptr->module.Length) { if (IS_INTRESOURCE( ptr->resname )) info->wResID = LOWORD( ptr->resname ); else lstrcpynW( info->szResName, ptr->resname, MAX_PATH ); + memcpy( info->szModName, ptr->module.Buffer, ptr->module.Length ); + info->szModName[ptr->module.Length / sizeof(WCHAR)] = 0; } if (!info->hbmMask || (!info->hbmColor && frame->color)) { @@ -2202,10 +2221,8 @@ BOOL WINAPI GetIconInfoExW( HICON icon, ICONINFOEXW *info ) DeleteObject( info->hbmColor ); ret = FALSE; } - module = ptr->module; release_icon_frame( ptr, frame ); release_user_handle_ptr( ptr ); - if (ret && module) GetModuleFileNameW( module, info->szModName, MAX_PATH ); return ret; } @@ -3003,14 +3020,16 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, struct cursoricon_object *icon; int depth = (flags & LR_MONOCHROME) ? 1 : get_display_bpp(); HICON resource_icon = NULL; + HINSTANCE module; ICONINFO info; HICON res; if (!(icon = get_icon_ptr( hnd ))) return 0; - if (icon->rsrc && (flags & LR_COPYFROMRESOURCE)) + if (icon->rsrc && (flags & LR_COPYFROMRESOURCE) && icon->module.Length && + !LdrGetDllHandle( NULL, 0, &icon->module, &module )) { - resource_icon = CURSORICON_Load( icon->module, icon->resname, desiredx, + resource_icon = CURSORICON_Load( module, icon->resname, desiredx, desiredy, depth, !icon->is_icon, flags ); release_user_handle_ptr( icon ); if (!(icon = get_icon_ptr( resource_icon )))
1
0
0
0
Jacek Caban : user32: Use a single struct for static and animated cursor icons.
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: 64bc66846327f7f1a3975ea3de6a9c31e759d6a4 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=64bc66846327f7f1a3975ea3…
Author: Jacek Caban <jacek(a)codeweavers.com> Date: Tue Feb 22 13:40:10 2022 +0100 user32: Use a single struct for static and animated cursor icons. Handle allocation should use a separate from data initialization, so its object layout needs to be independent on data. Signed-off-by: Jacek Caban <jacek(a)codeweavers.com> Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/user32/cursoricon.c | 117 ++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 72 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 59c50ae53d8..2b421cd1bf1 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -81,20 +81,16 @@ struct cursoricon_object BOOL is_ani; /* whether this object is a static cursor or an animated cursor */ UINT delay; /* delay between this frame and the next (in jiffies) */ POINT hotspot; -}; - -struct static_cursoricon_object -{ - struct cursoricon_object shared; - struct cursoricon_frame frame; /* frame-specific icon data */ -}; - -struct animated_cursoricon_object -{ - struct cursoricon_object shared; - UINT num_frames; /* number of frames in the icon/cursor */ - UINT num_steps; /* number of sequence steps in the icon/cursor */ - HICON frames[1]; /* list of animated cursor frames */ + union + { + struct cursoricon_frame frame; /* frame-specific icon data */ + struct + { + UINT num_frames; /* number of frames in the icon/cursor */ + UINT num_steps; /* number of sequence steps in the icon/cursor */ + HICON *frames; /* list of animated cursor frames */ + } ani; + }; }; static HBITMAP create_color_bitmap( int width, int height ) @@ -116,28 +112,28 @@ static int get_display_bpp(void) static HICON alloc_icon_handle( BOOL is_ani, UINT num_steps ) { struct cursoricon_object *obj; - int icon_size; HICON handle; - if (is_ani) - icon_size = FIELD_OFFSET( struct animated_cursoricon_object, frames[num_steps] ); - else - icon_size = sizeof( struct static_cursoricon_object ); - obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, icon_size ); - if (!obj) return NULL; - + if (!(obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj) ))) return NULL; obj->delay = 0; obj->is_ani = is_ani; if (is_ani) { - struct animated_cursoricon_object *ani_icon_data = (struct animated_cursoricon_object *) obj; - - ani_icon_data->num_steps = num_steps; - ani_icon_data->num_frames = num_steps; /* changed later for some animated cursors */ + if (!(obj->ani.frames = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + num_steps * sizeof(*obj->ani.frames) ))) + { + HeapFree( GetProcessHeap(), 0, obj ); + return NULL; + } + obj->ani.num_steps = num_steps; + obj->ani.num_frames = num_steps; /* changed later for some animated cursors */ } if (!(handle = alloc_user_handle( &obj->obj, USER_ICON ))) + { + if (obj->is_ani) HeapFree( GetProcessHeap(), 0, obj->ani.frames ); HeapFree( GetProcessHeap(), 0, obj ); + } return handle; } @@ -154,21 +150,10 @@ static struct cursoricon_object *get_icon_ptr( HICON handle ) static struct cursoricon_frame *get_icon_frame( struct cursoricon_object *obj, int istep ) { - struct static_cursoricon_object *req_frame; - - if (obj->is_ani) - { - struct animated_cursoricon_object *ani_icon_data; - struct cursoricon_object *frameobj; - - ani_icon_data = (struct animated_cursoricon_object *) obj; - if (!(frameobj = get_icon_ptr( ani_icon_data->frames[istep] ))) - return 0; - req_frame = (struct static_cursoricon_object *) frameobj; - } - else - req_frame = (struct static_cursoricon_object *) obj; + struct cursoricon_object *req_frame; + if (!obj->is_ani) return &obj->frame; + if (!(req_frame = get_icon_ptr( obj->ani.frames[istep] ))) return 0; return &req_frame->frame; } @@ -178,21 +163,14 @@ static void release_icon_frame( struct cursoricon_object *obj, struct cursoricon { struct cursoricon_object *frameobj; - frameobj = (struct cursoricon_object *) (((char *)frame) - FIELD_OFFSET(struct static_cursoricon_object, frame)); + frameobj = (struct cursoricon_object *) (((char *)frame) - FIELD_OFFSET(struct cursoricon_object, frame)); release_user_handle_ptr( frameobj ); } } static UINT get_icon_steps( struct cursoricon_object *obj ) { - if (obj->is_ani) - { - struct animated_cursoricon_object *ani_icon_data; - - ani_icon_data = (struct animated_cursoricon_object *) obj; - return ani_icon_data->num_steps; - } - return 1; + return obj->is_ani ? obj->ani.num_steps : 1; } static BOOL free_icon_handle( HICON handle ) @@ -218,24 +196,22 @@ static BOOL free_icon_handle( HICON handle ) } else { - struct animated_cursoricon_object *ani_icon_data = (struct animated_cursoricon_object *) obj; - - for (i=0; i<ani_icon_data->num_steps; i++) + for (i = 0; i < obj->ani.num_steps; i++) { - HICON hFrame = ani_icon_data->frames[i]; + HICON hFrame = obj->ani.frames[i]; if (hFrame) { UINT j; - free_icon_handle( ani_icon_data->frames[i] ); - for (j=0; j<ani_icon_data->num_steps; j++) + free_icon_handle( obj->ani.frames[i] ); + for (j=0; j < obj->ani.num_steps; j++) { - if (ani_icon_data->frames[j] == hFrame) - ani_icon_data->frames[j] = 0; + if (obj->ani.frames[j] == hFrame) obj->ani.frames[j] = 0; } } } + HeapFree( GetProcessHeap(), 0, obj->ani.frames ); } if (!IS_INTRESOURCE( obj->resname )) HeapFree( GetProcessHeap(), 0, obj->resname ); HeapFree( GetProcessHeap(), 0, obj ); @@ -1354,7 +1330,6 @@ static void riff_find_chunk( DWORD chunk_id, DWORD chunk_type, const riff_chunk_ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, INT width, INT height, INT depth, BOOL is_icon, UINT loadflags ) { - struct animated_cursoricon_object *ani_icon_data; struct cursoricon_object *info; DWORD *frame_rates = NULL; DWORD *frame_seq = NULL; @@ -1434,9 +1409,8 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, } info = get_icon_ptr( cursor ); - ani_icon_data = (struct animated_cursoricon_object *) info; info->is_icon = is_icon; - ani_icon_data->num_frames = header.num_frames; + info->ani.num_frames = header.num_frames; /* The .ANI stores the display rate in jiffies (1/60s) */ info->delay = header.display_rate; @@ -1484,7 +1458,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, if (i == 0) { FIXME_(cursor)("Completely failed to create animated cursor!\n"); - ani_icon_data->num_frames = 0; + info->ani.num_frames = 0; release_user_handle_ptr( info ); free_icon_handle( cursor ); HeapFree( GetProcessHeap(), 0, frames ); @@ -1502,26 +1476,26 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, if (error) { FIXME_(cursor)("Error creating animated cursor, only using first frame!\n"); - for (i=1; i<ani_icon_data->num_frames; i++) - free_icon_handle( ani_icon_data->frames[i] ); + for (i=1; i < info->ani.num_frames; i++) + free_icon_handle( info->ani.frames[i] ); use_seq = FALSE; info->delay = 0; - ani_icon_data->num_steps = 1; - ani_icon_data->num_frames = 1; + info->ani.num_steps = 1; + info->ani.num_frames = 1; } /* Setup the animated frames in the correct sequence */ - for (i=0; i<ani_icon_data->num_steps; i++) + for (i=0; i < info->ani.num_steps; i++) { DWORD frame_id = use_seq ? frame_seq[i] : i; struct cursoricon_frame *frame; - if (frame_id >= ani_icon_data->num_frames) + if (frame_id >= info->ani.num_frames) { - frame_id = ani_icon_data->num_frames-1; + frame_id = info->ani.num_frames-1; ERR_(cursor)("Sequence indicates frame past end of list, corrupt?\n"); } - ani_icon_data->frames[i] = frames[frame_id]; + info->ani.frames[i] = frames[frame_id]; frame = get_icon_frame( info, i ); if (frame_rates) frame->delay = frame_rates[i]; @@ -2094,13 +2068,12 @@ HCURSOR WINAPI GetCursorFrameInfo(HCURSOR hCursor, DWORD reserved, DWORD istep, icon_steps = get_icon_steps(ptr); if (istep < icon_steps || !ptr->is_ani) { - struct animated_cursoricon_object *ani_icon_data = (struct animated_cursoricon_object *) ptr; UINT icon_frames = 1; if (ptr->is_ani) - icon_frames = ani_icon_data->num_frames; + icon_frames = ptr->ani.num_frames; if (ptr->is_ani && icon_frames > 1) - ret = ani_icon_data->frames[istep]; + ret = ptr->ani.frames[istep]; else ret = hCursor; if (icon_frames == 1)
1
0
0
0
Alexandre Julliard : kernelbase: Implement IsApiSetImplemented().
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: 77973e7e720dabb57c76b0a971c07ff7e70d36b4 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=77973e7e720dabb57c76b0a9…
Author: Alexandre Julliard <julliard(a)winehq.org> Date: Tue Feb 22 12:38:37 2022 +0100 kernelbase: Implement IsApiSetImplemented(). Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/kernel32/tests/module.c | 1 - dlls/kernelbase/kernelbase.spec | 1 + dlls/kernelbase/loader.c | 16 ++++++++++++++++ include/winbase.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 58dcfaaec99..6d44b50e122 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -1469,7 +1469,6 @@ static void test_apisets(void) return; } if (!pApiSetQueryApiSetPresenceEx) win_skip( "ApiSetQueryApiSetPresenceEx not implemented\n" ); - todo_wine if (!pIsApiSetImplemented) win_skip( "IsApiSetImplemented not implemented\n" ); for (i = 0; i < ARRAY_SIZE(tests); i++) diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index a4c14184452..c1175af2f9f 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -868,6 +868,7 @@ # @ stub InternetTimeToSystemTimeW # @ stub InvalidateAppModelVersionCache @ stub InvalidateTzSpecificCache +@ stdcall IsApiSetImplemented(str) @ stdcall IsCharAlphaA(long) @ stdcall IsCharAlphaNumericA(long) @ stdcall IsCharAlphaNumericW(long) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index 02d72cfbfbf..0fd2d7b7c99 100644 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -467,6 +467,22 @@ FARPROC WINAPI DECLSPEC_HOTPATCH GetProcAddress( HMODULE module, LPCSTR function #endif /* __x86_64__ */ +/*********************************************************************** + * IsApiSetImplemented (kernelbase.@) + */ +BOOL WINAPI IsApiSetImplemented( LPCSTR name ) +{ + UNICODE_STRING str; + NTSTATUS status; + BOOLEAN in_schema, present; + + if (!RtlCreateUnicodeStringFromAsciiz( &str, name )) return FALSE; + status = ApiSetQueryApiSetPresenceEx( &str, &in_schema, &present ); + RtlFreeUnicodeString( &str ); + return !status && present; +} + + /*********************************************************************** * LoadLibraryA (kernelbase.@) */ diff --git a/include/winbase.h b/include/winbase.h index a8744eb417a..a0c62d710b9 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2406,6 +2406,7 @@ WINBASEAPI VOID WINAPI InitOnceInitialize(PINIT_ONCE); WINBASEAPI PSLIST_ENTRY WINAPI InterlockedFlushSList(PSLIST_HEADER); WINBASEAPI PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER); WINBASEAPI PSLIST_ENTRY WINAPI InterlockedPushEntrySList(PSLIST_HEADER, PSLIST_ENTRY); +WINBASEAPI BOOL WINAPI IsApiSetImplemented(LPCSTR); WINBASEAPI BOOL WINAPI IsBadCodePtr(FARPROC); WINBASEAPI BOOL WINAPI IsBadHugeReadPtr(LPCVOID,UINT_PTR); WINBASEAPI BOOL WINAPI IsBadHugeWritePtr(LPVOID,UINT_PTR);
1
0
0
0
Alexandre Julliard : ntdll: Implement ApiSetQueryApiSetPresence/Ex().
by Alexandre Julliard
22 Feb '22
22 Feb '22
Module: wine Branch: master Commit: cb2fb8c25eb641f96e0b5d84f8049d67f50c0f30 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=cb2fb8c25eb641f96e0b5d84…
Author: Alexandre Julliard <julliard(a)winehq.org> Date: Tue Feb 22 12:35:18 2022 +0100 ntdll: Implement ApiSetQueryApiSetPresence/Ex(). Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/kernel32/tests/module.c | 3 --- dlls/ntdll/loader.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/misc.c | 12 ------------ dlls/ntdll/ntdll.spec | 1 + include/winternl.h | 2 ++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index bd151708220..58dcfaaec99 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -1468,7 +1468,6 @@ static void test_apisets(void) win_skip( "ApiSetQueryApiSetPresence not implemented\n" ); return; } - todo_wine if (!pApiSetQueryApiSetPresenceEx) win_skip( "ApiSetQueryApiSetPresenceEx not implemented\n" ); todo_wine if (!pIsApiSetImplemented) win_skip( "IsApiSetImplemented not implemented\n" ); @@ -1480,9 +1479,7 @@ static void test_apisets(void) winetest_push_context( "%u:%s", i, tests[i].name ); present = 0xff; status = pApiSetQueryApiSetPresence( &name, &present ); - todo_wine ok( status == STATUS_SUCCESS, "wrong ret %x\n", status ); - todo_wine_if( !tests[i].present ) ok( present == tests[i].present || broken(!present && tests[i].broken) /* win8 */, "wrong present %u\n", present ); if (pApiSetQueryApiSetPresenceEx) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 49911d6c707..d3b63dc7ada 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -4526,6 +4526,51 @@ void WINAPI RtlReleasePath( PWSTR path ) } +/********************************************************************* + * ApiSetQueryApiSetPresence (NTDLL.@) + */ +NTSTATUS WINAPI ApiSetQueryApiSetPresence( const UNICODE_STRING *name, BOOLEAN *present ) +{ + const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap; + const API_SET_NAMESPACE_ENTRY *entry; + UNICODE_STRING str; + + *present = (!get_apiset_entry( map, name->Buffer, name->Length / sizeof(WCHAR), &entry ) && + !get_apiset_target( map, entry, NULL, &str )); + return STATUS_SUCCESS; +} + + +/********************************************************************* + * ApiSetQueryApiSetPresenceEx (NTDLL.@) + */ +NTSTATUS WINAPI ApiSetQueryApiSetPresenceEx( const UNICODE_STRING *name, BOOLEAN *in_schema, BOOLEAN *present ) +{ + const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap; + const API_SET_NAMESPACE_ENTRY *entry; + NTSTATUS status; + UNICODE_STRING str; + ULONG i, len = name->Length / sizeof(WCHAR); + + /* extension not allowed */ + for (i = 0; i < len; i++) if (name->Buffer[i] == '.') return STATUS_INVALID_PARAMETER; + + status = get_apiset_entry( map, name->Buffer, len, &entry ); + if (status == STATUS_APISET_NOT_PRESENT) + { + *in_schema = *present = FALSE; + return STATUS_SUCCESS; + } + if (status) return status; + + /* the name must match exactly */ + *in_schema = (entry->NameLength == name->Length && + !wcsnicmp( (WCHAR *)((char *)map + entry->NameOffset), name->Buffer, len )); + *present = *in_schema && !get_apiset_target( map, entry, NULL, &str ); + return STATUS_SUCCESS; +} + + /****************************************************************** * DllMain (NTDLL.@) */ diff --git a/dlls/ntdll/misc.c b/dlls/ntdll/misc.c index 3bef5a561c8..bce8d7db54e 100644 --- a/dlls/ntdll/misc.c +++ b/dlls/ntdll/misc.c @@ -381,15 +381,3 @@ ULONG WINAPIV EtwTraceMessage( TRACEHANDLE handle, ULONG flags, LPGUID guid, /*U va_end( valist ); return ret; } - -/********************************************************************* - * ApiSetQueryApiSetPresence (NTDLL.@) - */ -BOOL WINAPI ApiSetQueryApiSetPresence(const UNICODE_STRING *namespace, BOOLEAN *present) -{ - FIXME("(%s, %p) stub!\n", debugstr_us(namespace), present); - - if(present) - *present = TRUE; - return TRUE; -} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 29174965394..d514bca5e11 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -7,6 +7,7 @@ @ stdcall A_SHAInit(ptr) @ stdcall A_SHAUpdate(ptr ptr long) @ stdcall ApiSetQueryApiSetPresence(ptr ptr) +@ stdcall ApiSetQueryApiSetPresenceEx(ptr ptr ptr) @ stub CsrAllocateCaptureBuffer @ stub CsrAllocateCapturePointer @ stub CsrAllocateMessagePointer diff --git a/include/winternl.h b/include/winternl.h index ae331562026..6a95c4e0fdc 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3866,6 +3866,8 @@ typedef struct _API_SET_VALUE_ENTRY * Function declarations */ +NTSYSAPI NTSTATUS WINAPI ApiSetQueryApiSetPresence(const UNICODE_STRING*,BOOLEAN*); +NTSYSAPI NTSTATUS WINAPI ApiSetQueryApiSetPresenceEx(const UNICODE_STRING*,BOOLEAN*,BOOLEAN*); NTSYSAPI void WINAPI DbgBreakPoint(void); NTSYSAPI NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...); NTSYSAPI NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...);
1
0
0
0
← Newer
1
...
31
32
33
34
35
36
37
...
150
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
Results per page:
10
25
50
100
200