diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index a6a788565f4..6e735dcd065 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -217,35 +217,6 @@ int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) } -/*********************************************************************** - * copy_bitmap - * - * Helper function to duplicate a bitmap. - */ -static HBITMAP copy_bitmap( HBITMAP bitmap ) -{ - HDC src, dst = 0; - HBITMAP new_bitmap = 0; - BITMAP bmp; - - if (!bitmap) return 0; - if (!GetObjectW( bitmap, sizeof(bmp), &bmp )) return 0; - - if ((src = CreateCompatibleDC( 0 )) && (dst = CreateCompatibleDC( 0 ))) - { - SelectObject( src, bitmap ); - if ((new_bitmap = CreateCompatibleBitmap( src, bmp.bmWidth, bmp.bmHeight ))) - { - SelectObject( dst, new_bitmap ); - BitBlt( dst, 0, 0, bmp.bmWidth, bmp.bmHeight, src, 0, 0, SRCCOPY ); - } - } - DeleteDC( dst ); - DeleteDC( src ); - return new_bitmap; -} - - /*********************************************************************** * is_dib_monochrome * @@ -1886,57 +1857,31 @@ BOOL WINAPI GetIconInfoExA( HICON icon, ICONINFOEXA *info ) /********************************************************************** * GetIconInfoExW (USER32.@) */ -BOOL WINAPI GetIconInfoExW( HICON icon, ICONINFOEXW *info ) +BOOL WINAPI GetIconInfoExW( HICON handle, ICONINFOEXW *ret ) { - struct cursoricon_frame *frame; - struct cursoricon_object *ptr; - BOOL ret = TRUE; + UNICODE_STRING module, res_name; + ICONINFO info; - if (info->cbSize != sizeof(*info)) + if (ret->cbSize != sizeof(*ret)) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - if (!(ptr = get_icon_ptr( icon ))) - { - SetLastError( ERROR_INVALID_CURSOR_HANDLE ); - return FALSE; - } - frame = get_icon_frame( ptr, 0 ); - if (!frame) - { - release_user_handle_ptr( ptr ); - SetLastError( ERROR_INVALID_CURSOR_HANDLE ); - return FALSE; - } - - TRACE("%p => %dx%d\n", icon, frame->width, frame->height); - - info->fIcon = ptr->is_icon; - 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; - info->szModName[0] = 0; - info->szResName[0] = 0; - 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)) - { - DeleteObject( info->hbmMask ); - DeleteObject( info->hbmColor ); - ret = FALSE; - } - release_icon_frame( ptr, frame ); - release_user_handle_ptr( ptr ); - return ret; + module.Buffer = ret->szModName; + module.MaximumLength = sizeof(ret->szModName) - sizeof(WCHAR); + res_name.Buffer = ret->szResName; + res_name.MaximumLength = sizeof(ret->szResName) - sizeof(WCHAR); + if (!NtUserGetIconInfo( handle, &info, &module, &res_name, NULL, 0 )) return FALSE; + ret->fIcon = info.fIcon; + ret->xHotspot = info.xHotspot; + ret->yHotspot = info.yHotspot; + ret->hbmColor = info.hbmColor; + ret->hbmMask = info.hbmMask; + ret->wResID = res_name.Length ? 0 : LOWORD( res_name.Buffer ); + ret->szModName[module.Length] = 0; + ret->szResName[res_name.Length] = 0; + return TRUE; } /* copy an icon bitmap, even when it can't be selected into a DC */ diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c index 43481f09b09..b089ce97890 100644 --- a/dlls/win32u/cursoricon.c +++ b/dlls/win32u/cursoricon.c @@ -494,3 +494,101 @@ HCURSOR WINAPI NtUserGetCursorFrameInfo( HCURSOR cursor, DWORD istep, DWORD *rat release_user_handle_ptr( obj ); return ret; } + +/*********************************************************************** + * copy_bitmap + * + * Helper function to duplicate a bitmap. + */ +static HBITMAP copy_bitmap( HBITMAP bitmap ) +{ + HDC src, dst = 0; + HBITMAP new_bitmap = 0; + BITMAP bmp; + + if (!bitmap) return 0; + if (!NtGdiExtGetObjectW( bitmap, sizeof(bmp), &bmp )) return 0; + + if ((src = NtGdiCreateCompatibleDC( 0 )) && (dst = NtGdiCreateCompatibleDC( 0 ))) + { + NtGdiSelectBitmap( src, bitmap ); + if ((new_bitmap = NtGdiCreateCompatibleBitmap( src, bmp.bmWidth, bmp.bmHeight ))) + { + NtGdiSelectBitmap( dst, new_bitmap ); + NtGdiBitBlt( dst, 0, 0, bmp.bmWidth, bmp.bmHeight, src, 0, 0, SRCCOPY, 0, 0 ); + } + } + NtGdiDeleteObjectApp( dst ); + NtGdiDeleteObjectApp( src ); + return new_bitmap; +} + +/********************************************************************** + * NtUserGetIconInfo (win32u.@) + */ +BOOL WINAPI NtUserGetIconInfo( HICON icon, ICONINFO *info, UNICODE_STRING *module, + UNICODE_STRING *res_name, DWORD *bpp, LONG unk ) +{ + struct cursoricon_object *obj, *frame_obj; + BOOL ret = TRUE; + + if (!(obj = get_icon_ptr( icon ))) + { + SetLastError( ERROR_INVALID_CURSOR_HANDLE ); + return FALSE; + } + if (!(frame_obj = get_icon_frame_ptr( icon, 0 ))) + { + release_user_handle_ptr( obj ); + return FALSE; + } + + TRACE( "%p => %dx%d\n", icon, frame_obj->frame.width, frame_obj->frame.height ); + + info->fIcon = obj->is_icon; + info->xHotspot = frame_obj->frame.hotspot.x; + info->yHotspot = frame_obj->frame.hotspot.y; + info->hbmColor = copy_bitmap( frame_obj->frame.color ); + info->hbmMask = copy_bitmap( frame_obj->frame.mask ); + if (!info->hbmMask || (!info->hbmColor && frame_obj->frame.color)) + { + NtGdiDeleteObjectApp( info->hbmMask ); + NtGdiDeleteObjectApp( info->hbmColor ); + ret = FALSE; + } + else if (obj->module.Length) + { + if (module) + { + size_t size = min( module->MaximumLength, obj->module.Length ); + if (size) memcpy( module->Buffer, obj->module.Buffer, size ); + module->Length = size / sizeof(WCHAR); /* length in chars, not bytes */ + } + if (res_name) + { + if (IS_INTRESOURCE( obj->resname )) + { + res_name->Buffer = obj->resname; + res_name->Length = 0; + } + else + { + size_t size = min( res_name->MaximumLength, lstrlenW( obj->resname) * sizeof(WCHAR) ); + if (size) memcpy( res_name->Buffer, obj->resname, size ); + module->Length = size / sizeof(WCHAR); /* length in chars, not bytes */ + } + } + } + else + { + if (module) module->Length = 0; + if (res_name) + { + res_name->Length = 0; + res_name->Buffer = NULL; + } + } + release_user_handle_ptr( frame_obj ); + release_user_handle_ptr( obj ); + return ret; +} diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index e98380003b2..73044a44f5a 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1162,6 +1162,7 @@ static struct unix_funcs unix_funcs = NtUserEnumDisplaySettings, NtUserGetAsyncKeyState, NtUserGetDisplayConfigBufferSizes, + NtUserGetIconInfo, NtUserGetKeyNameText, NtUserGetKeyboardLayoutList, NtUserGetPriorityClipboardFormat, diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 77a0eaf6b9a..199a7600341 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -182,11 +182,14 @@ static void test_NtUserBuildHwndList(void) static void test_cursoricon(void) { + WCHAR module[MAX_PATH], res_buf[MAX_PATH]; + UNICODE_STRING module_str, res_str; BYTE bmp_bits[1024]; LONG width, height; DWORD rate, steps; HCURSOR frame; HANDLE handle; + ICONINFO info; unsigned int i; BOOL ret; @@ -212,6 +215,34 @@ static void test_cursoricon(void) ok( rate == 0, "rate = %lu\n", rate ); ok( steps == 1, "steps = %lu\n", steps ); + ret = NtUserGetIconInfo( handle, &info, NULL, NULL, NULL, 0 ); + ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() ); + ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon ); + ok( info.xHotspot == 8, "xHotspot = %lx\n", info.xHotspot ); + ok( info.yHotspot == 8, "yHotspot = %lx\n", info.yHotspot ); + DeleteObject( info.hbmColor ); + DeleteObject( info.hbmMask ); + + memset( module, 0xcc, sizeof(module) ); + module_str.Buffer = module; + module_str.Length = 0xdead; + module_str.MaximumLength = sizeof(module); + memset( res_buf, 0xcc, sizeof(res_buf) ); + res_str.Buffer = res_buf; + res_str.Length = 0xdead; + res_str.MaximumLength = sizeof(res_buf); + ret = NtUserGetIconInfo( handle, &info, &module_str, &res_str, NULL, 0 ); + ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() ); + ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon ); + ok( !module_str.Length, "module_str.Length = %u\n", module_str.Length ); + ok( !res_str.Length, "res_str.Length = %u\n", res_str.Length ); + ok( module_str.Buffer == module, "module_str.Buffer = %p\n", module_str.Buffer ); + ok( !res_str.Buffer, "res_str.Buffer = %p\n", res_str.Buffer ); + ok( module[0] == 0xcccc, "module[0] = %x\n", module[0] ); + ok( res_buf[0] == 0xcccc, "res_buf[0] = %x\n", res_buf[0] ); + DeleteObject( info.hbmColor ); + DeleteObject( info.hbmMask ); + ret = NtUserDestroyCursor( handle, 0 ); ok( ret, "NtUserDestroyIcon failed: %lu\n", GetLastError() ); @@ -229,6 +260,28 @@ static void test_cursoricon(void) ok( height == 64, "height = %ld\n", height ); ok( ret, "NtUserGetIconSize failed: %lu\n", GetLastError() ); + memset( module, 0xcc, sizeof(module) ); + module_str.Buffer = module; + module_str.Length = 0xdead; + module_str.MaximumLength = sizeof(module); + memset( res_buf, 0xcc, sizeof(res_buf) ); + res_str.Buffer = res_buf; + res_str.Length = 0xdead; + res_str.MaximumLength = sizeof(res_buf); + ret = NtUserGetIconInfo( handle, &info, &module_str, &res_str, NULL, 0 ); + ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() ); + ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon ); + ok( module_str.Length, "module_str.Length = 0\n" ); + ok( !res_str.Length, "res_str.Length = %u\n", res_str.Length ); + ok( module_str.Buffer == module, "module_str.Buffer = %p\n", module_str.Buffer ); + ok( res_str.Buffer == (WCHAR *)IDI_HAND, "res_str.Buffer = %p\n", res_str.Buffer ); + DeleteObject( info.hbmColor ); + DeleteObject( info.hbmMask ); + + module[module_str.Length] = 0; + ok( GetModuleHandleW(module) == GetModuleHandleW(L"user32.dll"), + "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(module) ); + ret = DestroyIcon(handle); ok(ret, "Destroy icon failed, error %lu.\n", GetLastError()); } diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 29994ffb575..7167beb20a1 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -934,7 +934,7 @@ @ stub NtUserGetGuiResources @ stub NtUserGetHDevName @ stub NtUserGetHimetricScaleFactorFromPixelLocation -@ stub NtUserGetIconInfo +@ stdcall NtUserGetIconInfo(long ptr ptr ptr ptr long) @ stdcall -syscall NtUserGetIconSize(long long ptr ptr) @ stub NtUserGetImeHotKey @ stub NtUserGetImeInfoEx diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 5d1a54fa64c..f79fdbead85 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -199,6 +199,8 @@ struct unix_funcs SHORT (WINAPI *pNtUserGetAsyncKeyState)( INT key ); LONG (WINAPI *pNtUserGetDisplayConfigBufferSizes)( UINT32 flags, UINT32 *num_path_info, UINT32 *num_mode_info ); + BOOL (WINAPI *pNtUserGetIconInfo)( HICON icon, ICONINFO *info, UNICODE_STRING *module, + UNICODE_STRING *res_name, DWORD *bpp, LONG unk ); INT (WINAPI *pNtUserGetKeyNameText)( LONG lparam, WCHAR *buffer, INT size ); UINT (WINAPI *pNtUserGetKeyboardLayoutList)( INT size, HKL *layouts ); INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count ); diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 36d17c99ea3..e75f4604588 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -777,6 +777,13 @@ LONG WINAPI NtUserGetDisplayConfigBufferSizes( UINT32 flags, UINT32 *num_path_in return unix_funcs->pNtUserGetDisplayConfigBufferSizes( flags, num_path_info, num_mode_info ); } +BOOL WINAPI NtUserGetIconInfo( HICON icon, ICONINFO *info, UNICODE_STRING *module, + UNICODE_STRING *res_name, DWORD *bpp, LONG unk ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserGetIconInfo( icon, info, module, res_name, bpp, unk ); +} + UINT WINAPI NtUserGetKeyboardLayoutList( INT size, HKL *layouts ) { if (!unix_funcs) return 0; diff --git a/include/ntuser.h b/include/ntuser.h index 37eb6500a4c..4b36177a3c2 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -206,6 +206,8 @@ LONG WINAPI NtUserGetDisplayConfigBufferSizes( UINT32 flags, UINT32 *num_path UINT WINAPI NtUserGetDoubleClickTime(void); BOOL WINAPI NtUserGetDpiForMonitor( HMONITOR monitor, UINT type, UINT *x, UINT *y ); HWND WINAPI NtUserGetForegroundWindow(void); +BOOL WINAPI NtUserGetIconInfo( HICON icon, ICONINFO *info, UNICODE_STRING *module, + UNICODE_STRING *res_name, DWORD *bpp, LONG unk ); BOOL WINAPI NtUserGetIconSize( HICON handle, UINT step, LONG *width, LONG *height ); INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size ); SHORT WINAPI NtUserGetKeyState( INT vkey );