2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
7 * 1998 Turchanov Sergey
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * http://www.microsoft.com/win32dev/ui/icons.htm
29 * Cursors and icons are stored in a global heap block, with the
32 * CURSORICONINFO info;
36 * The bits structures are in the format of a device-dependent bitmap.
38 * This layout is very sub-optimal, as the bitmap bits are stored in
39 * the X client instead of in the server like other bitmaps; however,
40 * some programs (notably Paint Brush) expect to be able to manipulate
41 * the bits directly :-(
43 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
51 #include "wine/winbase16.h"
52 #include "wine/winuser16.h"
53 #include "wine/exception.h"
55 #include "cursoricon.h"
57 #include "wine/debug.h"
63 #include "msvcrt/excpt.h"
65 WINE_DECLARE_DEBUG_CHANNEL(cursor);
66 WINE_DECLARE_DEBUG_CHANNEL(icon);
67 WINE_DECLARE_DEBUG_CHANNEL(resource);
69 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
73 /**********************************************************************
74 * ICONCACHE for cursors/icons loaded with LR_SHARED.
76 * FIXME: This should not be allocated on the system heap, but on a
77 * subsystem-global heap (i.e. one for all Win16 processes,
78 * and one for each Win32 process).
80 typedef struct tagICONCACHE
82 struct tagICONCACHE *next;
93 static ICONCACHE *IconAnchor = NULL;
94 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT("IconCrst");
95 static WORD ICON_HOTSPOT = 0x4242;
98 /***********************************************************************
101 * Helper function to map a file to memory:
103 * [RETURN] ptr - pointer to mapped file
105 static void *map_fileW( LPCWSTR name )
107 HANDLE hFile, hMapping;
110 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
111 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
112 if (hFile != INVALID_HANDLE_VALUE)
114 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
115 CloseHandle( hFile );
118 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
119 CloseHandle( hMapping );
126 /**********************************************************************
127 * CURSORICON_FindSharedIcon
129 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
134 EnterCriticalSection( &IconCrst );
136 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
137 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
140 handle = ptr->handle;
144 LeaveCriticalSection( &IconCrst );
149 /*************************************************************************
150 * CURSORICON_FindCache
152 * Given a handle, find the corresponding cache element
155 * Handle [I] handle to an Image
158 * Success: The cache entry
162 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
165 ICONCACHE *pRet=NULL;
166 BOOL IsFound = FALSE;
169 EnterCriticalSection( &IconCrst );
171 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
173 if ( handle == ptr->handle )
180 LeaveCriticalSection( &IconCrst );
185 /**********************************************************************
186 * CURSORICON_AddSharedIcon
188 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
190 ICONCACHE *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
193 ptr->hModule = hModule;
195 ptr->handle = handle;
196 ptr->hGroupRsrc = hGroupRsrc;
199 EnterCriticalSection( &IconCrst );
200 ptr->next = IconAnchor;
202 LeaveCriticalSection( &IconCrst );
205 /**********************************************************************
206 * CURSORICON_DelSharedIcon
208 static INT CURSORICON_DelSharedIcon( HANDLE handle )
213 EnterCriticalSection( &IconCrst );
215 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
216 if ( ptr->handle == handle )
218 if ( ptr->count > 0 ) ptr->count--;
223 LeaveCriticalSection( &IconCrst );
228 /**********************************************************************
229 * CURSORICON_FreeModuleIcons
231 void CURSORICON_FreeModuleIcons( HMODULE hModule )
233 ICONCACHE **ptr = &IconAnchor;
235 if ( HIWORD( hModule ) )
236 hModule = MapHModuleLS( hModule );
238 hModule = GetExePtr( hModule );
240 EnterCriticalSection( &IconCrst );
244 if ( (*ptr)->hModule == hModule )
246 ICONCACHE *freePtr = *ptr;
247 *ptr = freePtr->next;
249 GlobalFree16( freePtr->handle );
250 HeapFree( GetProcessHeap(), 0, freePtr );
256 LeaveCriticalSection( &IconCrst );
259 /**********************************************************************
260 * CURSORICON_FindBestIcon
262 * Find the icon closest to the requested size and number of colors.
264 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
265 int height, int colors )
268 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
269 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
270 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
272 if (dir->idCount < 1)
274 WARN_(icon)("Empty directory!\n" );
277 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
280 iTotalDiff = 0xFFFFFFFF;
281 iColorDiff = 0xFFFFFFFF;
282 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
284 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
285 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
287 if(iTotalDiff > (iTempXDiff + iTempYDiff))
291 iTotalDiff = iXDiff + iYDiff;
295 /* Find Best Colors for Best Fit */
296 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
298 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
299 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
301 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
302 if(iColorDiff > iTempColorDiff)
305 iColorDiff = iTempColorDiff;
314 /**********************************************************************
315 * CURSORICON_FindBestCursor
317 * Find the cursor closest to the requested size.
318 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
321 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
322 int width, int height, int color)
324 int i, maxwidth, maxheight;
325 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
327 if (dir->idCount < 1)
329 WARN_(cursor)("Empty directory!\n" );
332 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
334 /* Double height to account for AND and XOR masks */
338 /* First find the largest one smaller than or equal to the requested size*/
340 maxwidth = maxheight = 0;
341 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
342 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
343 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
344 (entry->wBitCount == 1))
347 maxwidth = entry->ResInfo.cursor.wWidth;
348 maxheight = entry->ResInfo.cursor.wHeight;
350 if (bestEntry) return bestEntry;
352 /* Now find the smallest one larger than the requested size */
354 maxwidth = maxheight = 255;
355 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
356 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
357 (entry->wBitCount == 1))
360 maxwidth = entry->ResInfo.cursor.wWidth;
361 maxheight = entry->ResInfo.cursor.wHeight;
367 /*********************************************************************
368 * The main purpose of this function is to create fake resource directory
369 * and fake resource entries. There are several reasons for this:
370 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
372 * There are some "bad" cursor files which do not have
373 * bColorCount initialized but instead one must read this info
374 * directly from corresponding DIB sections
375 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
377 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
378 CURSORICONDIR **res, LPBYTE **ptr)
381 CURSORICONFILEDIR *bits;
382 int entries, size, i;
386 if (!(bits = map_fileW( filename ))) return FALSE;
388 /* FIXME: test for inimated icons
389 * hack to load the first icon from the *.ani file
391 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
392 { LPBYTE pos = (LPBYTE) bits;
393 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
396 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
397 { FIXME_(cursor)("icon entry found! %p\n", bits);
399 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
402 bits=(CURSORICONFILEDIR*)(pos+4);
403 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
407 if (pos>=(LPBYTE)bits+766) goto fail;
410 if (!(entries = bits->idCount)) goto fail;
411 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
412 _free = (LPBYTE) size;
414 for (i=0; i < entries; i++)
415 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
417 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
418 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
419 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
421 _free = (LPBYTE)(*res) + (int)_free;
422 memcpy((*res), bits, 6);
423 for (i=0; i<entries; i++)
425 ((LPBYTE*)(*ptr))[i] = _free;
427 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
428 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
429 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
430 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
431 _free+=sizeof(POINT16);
433 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
434 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
435 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
437 (*res)->idEntries[i].wPlanes=1;
438 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
439 bits->idEntries[i].dwDIBOffset))->biBitCount;
440 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
441 (*res)->idEntries[i].wResId=i+1;
443 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
444 (*res)->idEntries[i].dwBytesInRes);
445 _free += (*res)->idEntries[i].dwBytesInRes;
447 UnmapViewOfFile( bits );
450 if (*res) HeapFree( GetProcessHeap(), 0, *res );
451 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
452 UnmapViewOfFile( bits );
457 /**********************************************************************
458 * CURSORICON_CreateFromResource
460 * Create a cursor or icon from in-memory resource template.
462 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
463 * with cbSize parameter as well.
465 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
466 UINT cbSize, BOOL bIcon, DWORD dwVersion,
467 INT width, INT height, UINT loadflags )
470 int sizeAnd, sizeXor;
471 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
472 BITMAP bmpXor, bmpAnd;
478 hotspot.x = ICON_HOTSPOT;
479 hotspot.y = ICON_HOTSPOT;
481 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
482 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
483 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
484 if (dwVersion == 0x00020000)
486 FIXME_(cursor)("\t2.xx resources are not supported\n");
491 bmi = (BITMAPINFO *)bits;
492 else /* get the hotspot */
494 POINT16 *pt = (POINT16 *)bits;
496 bmi = (BITMAPINFO *)(pt + 1);
498 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
500 if (!width) width = bmi->bmiHeader.biWidth;
501 if (!height) height = bmi->bmiHeader.biHeight/2;
502 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
503 (bmi->bmiHeader.biWidth != width);
505 /* Check bitmap header */
507 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
508 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
509 bmi->bmiHeader.biCompression != BI_RGB) )
511 WARN_(cursor)("\tinvalid resource bitmap header.\n");
515 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
520 /* Make sure we have room for the monochrome bitmap later on.
521 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
522 * up to and including the biBitCount. In-memory icon resource
523 * format is as follows:
525 * BITMAPINFOHEADER icHeader // DIB header
526 * RGBQUAD icColors[] // Color table
527 * BYTE icXOR[] // DIB bits for XOR mask
528 * BYTE icAND[] // DIB bits for AND mask
531 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
532 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
534 memcpy( pInfo, bmi, size );
535 pInfo->bmiHeader.biHeight /= 2;
537 /* Create the XOR bitmap */
542 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
546 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
553 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
555 hOld = SelectObject(hdcMem, hXorBits);
556 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
557 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
558 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
559 SelectObject(hdcMem, hOld);
561 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
563 } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
564 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
567 char* xbits = (char *)bmi + size +
568 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
569 bmi->bmiHeader.biHeight,
570 bmi->bmiHeader.biBitCount) / 2;
572 pInfo->bmiHeader.biBitCount = 1;
573 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
575 RGBQUAD *rgb = pInfo->bmiColors;
577 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
578 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
579 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
580 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
584 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
586 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
587 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
590 /* Create the AND bitmap */
593 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
597 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
599 hOld = SelectObject(hdcMem, hAndBits);
600 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
601 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
602 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
603 SelectObject(hdcMem, hOld);
605 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
607 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
608 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
610 if( !hAndBits ) DeleteObject( hXorBits );
612 HeapFree( GetProcessHeap(), 0, pInfo );
616 if( !hXorBits || !hAndBits )
618 WARN_(cursor)("\tunable to create an icon bitmap.\n");
622 /* Now create the CURSORICONINFO structure */
623 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
624 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
625 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
626 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
628 if (hObj) hObj = GlobalReAlloc16( hObj,
629 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
630 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
631 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
634 CURSORICONINFO *info;
636 /* Make it owned by the module */
637 if (hInstance) hInstance = GetExePtr(hInstance);
638 FarSetOwner16( hObj, hInstance );
640 info = (CURSORICONINFO *)GlobalLock16( hObj );
641 info->ptHotSpot.x = hotspot.x;
642 info->ptHotSpot.y = hotspot.y;
643 info->nWidth = bmpXor.bmWidth;
644 info->nHeight = bmpXor.bmHeight;
645 info->nWidthBytes = bmpXor.bmWidthBytes;
646 info->bPlanes = bmpXor.bmPlanes;
647 info->bBitsPerPixel = bmpXor.bmBitsPixel;
649 /* Transfer the bitmap bits to the CURSORICONINFO structure */
651 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
652 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
653 GlobalUnlock16( hObj );
656 DeleteObject( hAndBits );
657 DeleteObject( hXorBits );
662 /**********************************************************************
663 * CreateIconFromResourceEx (USER.450)
665 * FIXME: not sure about exact parameter types
667 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
668 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
670 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
671 width, height, cFlag);
675 /**********************************************************************
676 * CreateIconFromResource (USER32.@)
678 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
679 BOOL bIcon, DWORD dwVersion)
681 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
685 /**********************************************************************
686 * CreateIconFromResourceEx (USER32.@)
688 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
689 BOOL bIcon, DWORD dwVersion,
690 INT width, INT height,
693 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
694 width, height, cFlag );
697 /**********************************************************************
700 * Load a cursor or icon from resource or file.
702 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
703 INT width, INT height, INT colors,
704 BOOL fCursor, UINT loadflags )
706 HANDLE handle = 0, h = 0;
709 CURSORICONDIRENTRY *dirEntry;
712 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
715 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
718 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
720 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
721 bits = ptr[dirEntry->wResId-1];
722 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
723 !fCursor, 0x00030000, width, height, loadflags);
724 HeapFree( GetProcessHeap(), 0, dir );
725 HeapFree( GetProcessHeap(), 0, ptr );
727 else /* Load from resource */
733 if (!hInstance) /* Load OEM cursor/icon */
735 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
738 /* Normalize hInstance (must be uniquely represented for icon cache) */
740 if ( HIWORD( hInstance ) )
741 hInstance = MapHModuleLS( hInstance );
743 hInstance = GetExePtr( hInstance );
745 /* Get directory resource ID */
747 if (!(hRsrc = FindResourceW( hInstance, name,
748 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
752 /* Find the best entry in the directory */
754 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
755 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
757 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
760 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
761 width, height, colors );
762 if (!dirEntry) return 0;
763 wResId = dirEntry->wResId;
764 dwBytesInRes = dirEntry->dwBytesInRes;
765 FreeResource( handle );
767 /* Load the resource */
769 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
770 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
772 /* If shared icon, check whether it was already loaded */
773 if ( (loadflags & LR_SHARED)
774 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
777 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
778 bits = (LPBYTE)LockResource( handle );
779 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
780 !fCursor, 0x00030000, width, height, loadflags);
781 FreeResource( handle );
783 /* If shared icon, add to icon cache */
785 if ( h && (loadflags & LR_SHARED) )
786 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
792 /***********************************************************************
795 * Make a copy of a cursor or icon.
797 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
799 char *ptrOld, *ptrNew;
803 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
804 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
805 size = GlobalSize16( handle );
806 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
807 FarSetOwner16( hNew, hInstance );
808 ptrNew = (char *)GlobalLock16( hNew );
809 memcpy( ptrNew, ptrOld, size );
810 GlobalUnlock16( handle );
811 GlobalUnlock16( hNew );
815 /*************************************************************************
818 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
821 * Handle [I] handle to an Image
822 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
823 * iDesiredCX [I] The Desired width of the Image
824 * iDesiredCY [I] The desired height of the Image
825 * nFlags [I] The flags from CopyImage
828 * Success: The new handle of the Image
831 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
832 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
833 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
838 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
839 INT iDesiredCX, INT iDesiredCY,
844 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
845 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
852 /* Best Fit or Monochrome */
853 if( (nFlags & LR_COPYFROMRESOURCE
854 && (iDesiredCX > 0 || iDesiredCY > 0))
855 || nFlags & LR_MONOCHROME)
857 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
859 /* Not Found in Cache, then do a straight copy
861 if(pIconCache == NULL)
863 hNew = CURSORICON_Copy(0, Handle);
864 if(nFlags & LR_COPYFROMRESOURCE)
866 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
871 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
878 CURSORICONDIRENTRY *pDirEntry;
879 BOOL bIsIcon = (nType == IMAGE_ICON);
881 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
883 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
884 || (iDesiredCX == 0 && iDesiredCY == 0))
886 iDesiredCY = GetSystemMetrics(bIsIcon ?
887 SM_CYICON : SM_CYCURSOR);
888 iDesiredCX = GetSystemMetrics(bIsIcon ?
889 SM_CXICON : SM_CXCURSOR);
892 /* Retrieve the CURSORICONDIRENTRY
894 if (!(hMem = LoadResource( pIconCache->hModule ,
895 pIconCache->hGroupRsrc)))
899 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
908 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
909 pDir, iDesiredCX, iDesiredCY, 256);
913 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
914 pDir, iDesiredCX, iDesiredCY, 1);
917 wResId = pDirEntry->wResId;
918 dwBytesInRes = pDirEntry->dwBytesInRes;
921 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
922 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
923 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
927 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
928 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
932 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
937 pBits = (LPBYTE)LockResource( hMem );
939 if(nFlags & LR_DEFAULTSIZE)
941 iTargetCY = GetSystemMetrics(SM_CYICON);
942 iTargetCX = GetSystemMetrics(SM_CXICON);
945 /* Create a New Icon with the proper dimension
947 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
948 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
952 else hNew = CURSORICON_Copy(0, Handle);
957 /***********************************************************************
958 * LoadCursor (USER.173)
960 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
962 return LoadCursorA( hInstance, name );
966 /***********************************************************************
967 * LoadIcon (USER.174)
969 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
971 return LoadIconA( hInstance, name );
975 /***********************************************************************
976 * CreateCursor (USER.406)
978 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
979 INT16 xHotSpot, INT16 yHotSpot,
980 INT16 nWidth, INT16 nHeight,
981 LPCVOID lpANDbits, LPCVOID lpXORbits )
985 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
986 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
988 info.ptHotSpot.x = xHotSpot;
989 info.ptHotSpot.y = yHotSpot;
990 info.nWidth = nWidth;
991 info.nHeight = nHeight;
992 info.nWidthBytes = 0;
994 info.bBitsPerPixel = 1;
996 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1000 /***********************************************************************
1001 * CreateCursor (USER32.@)
1003 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1004 INT xHotSpot, INT yHotSpot,
1005 INT nWidth, INT nHeight,
1006 LPCVOID lpANDbits, LPCVOID lpXORbits )
1008 CURSORICONINFO info;
1010 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1011 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1013 info.ptHotSpot.x = xHotSpot;
1014 info.ptHotSpot.y = yHotSpot;
1015 info.nWidth = nWidth;
1016 info.nHeight = nHeight;
1017 info.nWidthBytes = 0;
1019 info.bBitsPerPixel = 1;
1021 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1025 /***********************************************************************
1026 * CreateIcon (USER.407)
1028 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1029 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1030 LPCVOID lpANDbits, LPCVOID lpXORbits )
1032 CURSORICONINFO info;
1034 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1035 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1037 info.ptHotSpot.x = ICON_HOTSPOT;
1038 info.ptHotSpot.y = ICON_HOTSPOT;
1039 info.nWidth = nWidth;
1040 info.nHeight = nHeight;
1041 info.nWidthBytes = 0;
1042 info.bPlanes = bPlanes;
1043 info.bBitsPerPixel = bBitsPixel;
1045 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1049 /***********************************************************************
1050 * CreateIcon (USER32.@)
1052 * Creates an icon based on the specified bitmaps. The bitmaps must be
1053 * provided in a device dependent format and will be resized to
1054 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1055 * depth. The provided bitmaps must be top-down bitmaps.
1056 * Although Windows does not support 15bpp(*) this API must support it
1057 * for Winelib applications.
1059 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1064 * - The provided bitmaps are not resized!
1065 * - The documentation says the lpXORbits bitmap must be in a device
1066 * dependent format. But we must still resize it and perform depth
1067 * conversions if necessary.
1068 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1069 * I did some tests on windows and found that if you provide a 16bpp bitmap
1070 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1071 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1072 * else. I don't know if this is part of the GDI specs or if this is a
1073 * quirk of the graphics card driver.
1074 * - You may think that we check whether the bit depths match or not
1075 * as an optimization. But the truth is that the conversion using
1076 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1078 * - I'm pretty sure that all the things we do in CreateIcon should
1079 * also be done in CreateIconIndirect...
1081 HICON WINAPI CreateIcon(
1082 HINSTANCE hInstance, /* [in] the application's hInstance, currently unused */
1083 INT nWidth, /* [in] the width of the provided bitmaps */
1084 INT nHeight, /* [in] the height of the provided bitmaps */
1085 BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */
1086 BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1087 LPCVOID lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */
1088 LPCVOID lpXORbits) /* [in] the icon's 'color' bitmap */
1093 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1094 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1100 if (GetDeviceCaps(hdc,BITSPIXEL)==bBitsPixel) {
1101 CURSORICONINFO info;
1103 info.ptHotSpot.x = ICON_HOTSPOT;
1104 info.ptHotSpot.y = ICON_HOTSPOT;
1105 info.nWidth = nWidth;
1106 info.nHeight = nHeight;
1107 info.nWidthBytes = 0;
1108 info.bPlanes = bPlanes;
1109 info.bBitsPerPixel = bBitsPixel;
1111 hIcon=CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1117 iinfo.xHotspot=ICON_HOTSPOT;
1118 iinfo.yHotspot=ICON_HOTSPOT;
1119 iinfo.hbmMask=CreateBitmap(nWidth,nHeight,1,1,lpANDbits);
1121 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
1122 bmi.bmiHeader.biWidth=nWidth;
1123 bmi.bmiHeader.biHeight=-nHeight;
1124 bmi.bmiHeader.biPlanes=bPlanes;
1125 bmi.bmiHeader.biBitCount=bBitsPixel;
1126 bmi.bmiHeader.biCompression=BI_RGB;
1127 bmi.bmiHeader.biSizeImage=0;
1128 bmi.bmiHeader.biXPelsPerMeter=0;
1129 bmi.bmiHeader.biYPelsPerMeter=0;
1130 bmi.bmiHeader.biClrUsed=0;
1131 bmi.bmiHeader.biClrImportant=0;
1133 iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
1134 CBM_INIT, lpXORbits,
1135 &bmi, DIB_RGB_COLORS );
1137 hIcon=CreateIconIndirect(&iinfo);
1138 DeleteObject(iinfo.hbmMask);
1139 DeleteObject(iinfo.hbmColor);
1146 /***********************************************************************
1147 * CreateCursorIconIndirect (USER.408)
1149 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1150 CURSORICONINFO *info,
1156 int sizeAnd, sizeXor;
1158 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1159 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1160 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1161 sizeXor = info->nHeight * info->nWidthBytes;
1162 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1163 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1164 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1166 FarSetOwner16( handle, hInstance );
1167 ptr = (char *)GlobalLock16( handle );
1168 memcpy( ptr, info, sizeof(*info) );
1169 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1170 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1171 GlobalUnlock16( handle );
1176 /***********************************************************************
1177 * CopyIcon (USER.368)
1179 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1181 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1182 return CURSORICON_Copy( hInstance, hIcon );
1186 /***********************************************************************
1187 * CopyIcon (USER32.@)
1189 HICON WINAPI CopyIcon( HICON hIcon )
1191 TRACE_(icon)("%04x\n", hIcon );
1192 return CURSORICON_Copy( 0, hIcon );
1196 /***********************************************************************
1197 * CopyCursor (USER.369)
1199 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1201 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1202 return CURSORICON_Copy( hInstance, hCursor );
1205 /**********************************************************************
1206 * DestroyIcon32 (USER.610)
1207 * DestroyIcon32 (USER32.@)
1209 * This routine is actually exported from Win95 USER under the name
1210 * DestroyIcon32 ... The behaviour implemented here should mimic
1211 * the Win95 one exactly, especially the return values, which
1212 * depend on the setting of various flags.
1214 WORD WINAPI DestroyIcon32( HGLOBAL16 handle, UINT16 flags )
1218 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1220 /* Check whether destroying active cursor */
1222 if ( QUEUE_Current()->cursor == handle )
1224 WARN_(cursor)("Destroying active cursor!\n" );
1228 /* Try shared cursor/icon first */
1230 if ( !(flags & CID_NONSHARED) )
1232 INT count = CURSORICON_DelSharedIcon( handle );
1235 return (flags & CID_WIN32)? TRUE : (count == 0);
1237 /* FIXME: OEM cursors/icons should be recognized */
1240 /* Now assume non-shared cursor/icon */
1242 retv = GlobalFree16( handle );
1243 return (flags & CID_RESOURCE)? retv : TRUE;
1246 /***********************************************************************
1247 * DestroyIcon (USER.457)
1249 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1251 return DestroyIcon32( hIcon, 0 );
1254 /***********************************************************************
1255 * DestroyIcon (USER32.@)
1257 BOOL WINAPI DestroyIcon( HICON hIcon )
1259 return DestroyIcon32( hIcon, CID_WIN32 );
1262 /***********************************************************************
1263 * DestroyCursor (USER.458)
1265 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1267 return DestroyIcon32( hCursor, 0 );
1270 /***********************************************************************
1271 * DestroyCursor (USER32.@)
1273 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1275 return DestroyIcon32( hCursor, CID_WIN32 );
1279 /***********************************************************************
1280 * DrawIcon (USER.84)
1282 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1284 return DrawIcon( hdc, x, y, hIcon );
1288 /***********************************************************************
1289 * DrawIcon (USER32.@)
1291 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1293 CURSORICONINFO *ptr;
1295 HBITMAP hXorBits, hAndBits;
1296 COLORREF oldFg, oldBg;
1298 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1299 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1300 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1302 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1303 ptr->bBitsPerPixel, (char *)(ptr + 1)
1304 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1305 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1306 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1308 if (hXorBits && hAndBits)
1310 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1311 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1312 SelectObject( hMemDC, hXorBits );
1313 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1314 SelectObject( hMemDC, hBitTemp );
1317 if (hXorBits) DeleteObject( hXorBits );
1318 if (hAndBits) DeleteObject( hAndBits );
1319 GlobalUnlock16( hIcon );
1320 SetTextColor( hdc, oldFg );
1321 SetBkColor( hdc, oldBg );
1326 /***********************************************************************
1327 * IconSize (USER.86)
1329 * See "Undocumented Windows". Used by W2.0 paint.exe.
1331 DWORD WINAPI IconSize16( void )
1333 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1337 /***********************************************************************
1338 * DumpIcon (USER.459)
1340 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1341 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1343 CURSORICONINFO *info = MapSL( pInfo );
1344 int sizeAnd, sizeXor;
1346 if (!info) return 0;
1347 sizeXor = info->nHeight * info->nWidthBytes;
1348 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1349 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1350 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1351 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1352 return MAKELONG( sizeXor, sizeXor );
1356 /***********************************************************************
1357 * SetCursor (USER.69)
1359 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1361 return (HCURSOR16)SetCursor( hCursor );
1365 /***********************************************************************
1366 * SetCursor (USER32.@)
1368 * A handle to the previous cursor shape.
1370 HCURSOR WINAPI SetCursor( HCURSOR hCursor /* [in] Handle of cursor to show */ )
1372 MESSAGEQUEUE *queue = QUEUE_Current();
1375 if (hCursor == queue->cursor) return hCursor; /* No change */
1376 TRACE_(cursor)("%04x\n", hCursor );
1377 hOldCursor = queue->cursor;
1378 queue->cursor = hCursor;
1379 /* Change the cursor shape only if it is visible */
1380 if (queue->cursor_count >= 0)
1382 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hCursor ) );
1383 GlobalUnlock16( hCursor );
1389 /***********************************************************************
1390 * ShowCursor (USER.71)
1392 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1394 return ShowCursor( bShow );
1398 /***********************************************************************
1399 * ShowCursor (USER32.@)
1401 INT WINAPI ShowCursor( BOOL bShow )
1403 MESSAGEQUEUE *queue = QUEUE_Current();
1405 TRACE_(cursor)("%d, count=%d\n", bShow, queue->cursor_count );
1409 if (++queue->cursor_count == 0) /* Show it */
1411 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( queue->cursor ) );
1412 GlobalUnlock16( queue->cursor );
1417 if (--queue->cursor_count == -1) /* Hide it */
1418 USER_Driver.pSetCursor( NULL );
1420 return queue->cursor_count;
1424 /***********************************************************************
1425 * GetCursor (USER.247)
1427 HCURSOR16 WINAPI GetCursor16(void)
1433 /***********************************************************************
1434 * GetCursor (USER32.@)
1436 HCURSOR WINAPI GetCursor(void)
1438 return QUEUE_Current()->cursor;
1442 /***********************************************************************
1443 * ClipCursor (USER.16)
1445 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1447 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1448 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1453 /***********************************************************************
1454 * ClipCursor (USER32.@)
1456 BOOL WINAPI ClipCursor( const RECT *rect )
1458 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1459 else CopyRect( &CURSOR_ClipRect, rect );
1464 /***********************************************************************
1465 * GetClipCursor (USER.309)
1467 void WINAPI GetClipCursor16( RECT16 *rect )
1469 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1473 /***********************************************************************
1474 * GetClipCursor (USER32.@)
1476 BOOL WINAPI GetClipCursor( RECT *rect )
1480 CopyRect( rect, &CURSOR_ClipRect );
1486 /**********************************************************************
1487 * LookupIconIdFromDirectoryEx (USER.364)
1489 * FIXME: exact parameter sizes
1491 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1492 INT16 width, INT16 height, UINT16 cFlag )
1494 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1496 if( dir && !dir->idReserved && (dir->idType & 3) )
1498 CURSORICONDIRENTRY* entry;
1503 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1506 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1511 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1513 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1515 if( entry ) retVal = entry->wResId;
1517 else WARN_(cursor)("invalid resource directory\n");
1521 /**********************************************************************
1522 * LookupIconIdFromDirectoryEx (USER32.@)
1524 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1525 INT width, INT height, UINT cFlag )
1527 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1530 /**********************************************************************
1531 * LookupIconIdFromDirectory (USER.?)
1533 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1535 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1536 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1537 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1540 /**********************************************************************
1541 * LookupIconIdFromDirectory (USER32.@)
1543 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1545 return LookupIconIdFromDirectoryEx( dir, bIcon,
1546 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1547 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1550 /**********************************************************************
1551 * GetIconID (USER.455)
1553 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1555 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1557 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1558 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1563 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1564 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1566 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1567 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1569 WARN_(cursor)("invalid res type %ld\n", resType );
1574 /**********************************************************************
1575 * LoadCursorIconHandler (USER.336)
1577 * Supposed to load resources of Windows 2.x applications.
1579 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1581 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1582 hResource, hModule, hRsrc);
1583 return (HGLOBAL16)0;
1586 /**********************************************************************
1587 * LoadDIBIconHandler (USER.357)
1589 * RT_ICON resource loader, installed by USER_SignalProc when module
1592 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1594 /* If hResource is zero we must allocate a new memory block, if it's
1595 * non-zero but GlobalLock() returns NULL then it was discarded and
1596 * we have to recommit some memory, otherwise we just need to check
1597 * the block size. See LoadProc() in 16-bit SDK for more.
1600 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1603 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1604 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1605 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1606 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1611 /**********************************************************************
1612 * LoadDIBCursorHandler (USER.356)
1614 * RT_CURSOR resource loader. Same as above.
1616 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1618 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1621 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1622 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1623 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1624 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1629 /**********************************************************************
1630 * LoadIconHandler (USER.456)
1632 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1634 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1636 TRACE_(cursor)("hRes=%04x\n",hResource);
1638 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1639 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1642 /***********************************************************************
1643 * LoadCursorW (USER32.@)
1645 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1647 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1648 LR_SHARED | LR_DEFAULTSIZE );
1651 /***********************************************************************
1652 * LoadCursorA (USER32.@)
1654 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1656 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1657 LR_SHARED | LR_DEFAULTSIZE );
1660 /***********************************************************************
1661 * LoadCursorFromFileW (USER32.@)
1663 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1665 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1666 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1669 /***********************************************************************
1670 * LoadCursorFromFileA (USER32.@)
1672 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1674 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1675 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1678 /***********************************************************************
1679 * LoadIconW (USER32.@)
1681 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1683 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1684 LR_SHARED | LR_DEFAULTSIZE );
1687 /***********************************************************************
1688 * LoadIconA (USER32.@)
1690 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1692 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1693 LR_SHARED | LR_DEFAULTSIZE );
1696 /**********************************************************************
1697 * GetIconInfo (USER.395)
1699 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1702 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1704 iconinfo->fIcon = ii32.fIcon;
1705 iconinfo->xHotspot = ii32.xHotspot;
1706 iconinfo->yHotspot = ii32.yHotspot;
1707 iconinfo->hbmMask = ii32.hbmMask;
1708 iconinfo->hbmColor = ii32.hbmColor;
1712 /**********************************************************************
1713 * GetIconInfo (USER32.@)
1715 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1716 CURSORICONINFO *ciconinfo;
1718 ciconinfo = GlobalLock16(hIcon);
1722 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1723 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1725 iconinfo->fIcon = TRUE;
1726 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1727 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1731 iconinfo->fIcon = FALSE;
1732 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1733 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1736 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1737 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1738 (char *)(ciconinfo + 1)
1739 + ciconinfo->nHeight *
1740 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1741 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1742 1, 1, (char *)(ciconinfo + 1));
1744 GlobalUnlock16(hIcon);
1749 /**********************************************************************
1750 * CreateIconIndirect (USER32.@)
1752 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1754 BITMAP bmpXor,bmpAnd;
1756 int sizeXor,sizeAnd;
1758 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1759 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1761 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1762 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1764 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1765 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1768 CURSORICONINFO *info;
1770 info = (CURSORICONINFO *)GlobalLock16( hObj );
1772 /* If we are creating an icon, the hotspot is unused */
1773 if (iconinfo->fIcon)
1775 info->ptHotSpot.x = ICON_HOTSPOT;
1776 info->ptHotSpot.y = ICON_HOTSPOT;
1780 info->ptHotSpot.x = iconinfo->xHotspot;
1781 info->ptHotSpot.y = iconinfo->yHotspot;
1784 info->nWidth = bmpXor.bmWidth;
1785 info->nHeight = bmpXor.bmHeight;
1786 info->nWidthBytes = bmpXor.bmWidthBytes;
1787 info->bPlanes = bmpXor.bmPlanes;
1788 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1790 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1792 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1793 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1794 GlobalUnlock16( hObj );
1800 /**********************************************************************
1801 * DrawIconEx (USER.394)
1803 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1804 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1805 HBRUSH16 hbr, UINT16 flags)
1807 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1812 /******************************************************************************
1813 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1816 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1819 * hdc [I] Handle to device context
1820 * x0 [I] X coordinate of upper left corner
1821 * y0 [I] Y coordinate of upper left corner
1822 * hIcon [I] Handle to icon to draw
1823 * cxWidth [I] Width of icon
1824 * cyWidth [I] Height of icon
1825 * istep [I] Index of frame in animated cursor
1826 * hbr [I] Handle to background brush
1827 * flags [I] Icon-drawing flags
1833 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1834 INT cxWidth, INT cyWidth, UINT istep,
1835 HBRUSH hbr, UINT flags )
1837 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1838 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1839 BOOL result = FALSE, DoOffscreen;
1840 HBITMAP hB_off = 0, hOld = 0;
1842 if (!ptr) return FALSE;
1843 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1844 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1848 FIXME_(icon)("Ignoring istep=%d\n", istep);
1849 if (flags & DI_COMPAT)
1850 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1853 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1857 /* Calculate the size of the destination image. */
1860 if (flags & DI_DEFAULTSIZE)
1861 cxWidth = GetSystemMetrics (SM_CXICON);
1863 cxWidth = ptr->nWidth;
1867 if (flags & DI_DEFAULTSIZE)
1868 cyWidth = GetSystemMetrics (SM_CYICON);
1870 cyWidth = ptr->nHeight;
1873 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1883 hDC_off = CreateCompatibleDC(hdc);
1884 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1885 if (hDC_off && hB_off) {
1886 hOld = SelectObject(hDC_off, hB_off);
1887 FillRect(hDC_off, &r, hbr);
1891 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1893 HBITMAP hXorBits, hAndBits;
1894 COLORREF oldFg, oldBg;
1897 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1899 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1900 ptr->bPlanes, ptr->bBitsPerPixel,
1903 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1904 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1905 1, 1, (char *)(ptr+1) );
1906 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1907 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1909 if (hXorBits && hAndBits)
1911 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1912 if (flags & DI_MASK)
1915 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1916 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1918 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1919 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1921 SelectObject( hMemDC, hXorBits );
1922 if (flags & DI_IMAGE)
1925 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1926 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1928 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1929 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1931 SelectObject( hMemDC, hBitTemp );
1935 SetTextColor( hdc, oldFg );
1936 SetBkColor( hdc, oldBg );
1937 if (hXorBits) DeleteObject( hXorBits );
1938 if (hAndBits) DeleteObject( hAndBits );
1939 SetStretchBltMode (hdc, nStretchMode);
1941 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1942 SelectObject(hDC_off, hOld);
1945 if (hMemDC) DeleteDC( hMemDC );
1946 if (hDC_off) DeleteDC(hDC_off);
1947 if (hB_off) DeleteObject(hB_off);
1948 GlobalUnlock16( hIcon );
1952 /***********************************************************************
1953 * DIB_FixColorsToLoadflags
1955 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1958 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
1961 COLORREF c_W, c_S, c_F, c_L, c_C;
1965 if (bmi->bmiHeader.biBitCount > 8) return;
1966 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
1967 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
1969 WARN_(resource)("Wrong bitmap header size!\n");
1972 colors = bmi->bmiHeader.biClrUsed;
1973 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
1974 colors = 1 << bmi->bmiHeader.biBitCount;
1975 c_W = GetSysColor(COLOR_WINDOW);
1976 c_S = GetSysColor(COLOR_3DSHADOW);
1977 c_F = GetSysColor(COLOR_3DFACE);
1978 c_L = GetSysColor(COLOR_3DLIGHT);
1979 if (loadflags & LR_LOADTRANSPARENT) {
1980 switch (bmi->bmiHeader.biBitCount) {
1981 case 1: pix = pix >> 7; break;
1982 case 4: pix = pix >> 4; break;
1985 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
1988 if (pix >= colors) {
1989 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
1992 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
1993 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
1994 ptr->rgbBlue = GetBValue(c_W);
1995 ptr->rgbGreen = GetGValue(c_W);
1996 ptr->rgbRed = GetRValue(c_W);
1998 if (loadflags & LR_LOADMAP3DCOLORS)
1999 for (i=0; i<colors; i++) {
2000 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2001 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2002 if (c_C == RGB(128, 128, 128)) {
2003 ptr->rgbRed = GetRValue(c_S);
2004 ptr->rgbGreen = GetGValue(c_S);
2005 ptr->rgbBlue = GetBValue(c_S);
2006 } else if (c_C == RGB(192, 192, 192)) {
2007 ptr->rgbRed = GetRValue(c_F);
2008 ptr->rgbGreen = GetGValue(c_F);
2009 ptr->rgbBlue = GetBValue(c_F);
2010 } else if (c_C == RGB(223, 223, 223)) {
2011 ptr->rgbRed = GetRValue(c_L);
2012 ptr->rgbGreen = GetGValue(c_L);
2013 ptr->rgbBlue = GetBValue(c_L);
2019 /**********************************************************************
2022 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2024 HBITMAP hbitmap = 0;
2028 BITMAPINFO *info, *fix_info=NULL;
2032 if (!(loadflags & LR_LOADFROMFILE))
2036 /* OEM bitmap: try to load the resource from user32.dll */
2037 if (HIWORD(name)) return 0;
2038 if (!(instance = GetModuleHandleA("user32.dll"))) return 0;
2040 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2041 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2043 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2047 if (!(ptr = map_fileW( name ))) return 0;
2048 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2050 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2051 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2055 memcpy(fix_info, info, size);
2056 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2057 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2058 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2061 char *bits = (char *)info + size;
2062 if (loadflags & LR_CREATEDIBSECTION) {
2064 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2065 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2066 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2070 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
2071 bits, fix_info, DIB_RGB_COLORS );
2077 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2082 /***********************************************************************
2083 * LoadImage (USER.389)
2086 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2087 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2089 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2092 /**********************************************************************
2093 * LoadImageA (USER32.@)
2095 * FIXME: implementation lacks some features, see LR_ defines in winuser.h
2098 /* filter for page-fault exceptions */
2099 static WINE_EXCEPTION_FILTER(page_fault)
2101 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
2102 return EXCEPTION_EXECUTE_HANDLER;
2103 return EXCEPTION_CONTINUE_SEARCH;
2106 /*********************************************************************/
2108 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2109 INT desiredx, INT desiredy, UINT loadflags)
2115 return LoadImageW(hinst, (LPWSTR)name, type, desiredx, desiredy, loadflags);
2118 DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
2119 u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2120 MultiByteToWideChar( CP_ACP, 0, name, -1, u_name, len );
2122 __EXCEPT(page_fault) {
2123 SetLastError( ERROR_INVALID_PARAMETER );
2127 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2128 HeapFree(GetProcessHeap(), 0, u_name);
2133 /******************************************************************************
2134 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2137 * hinst [I] Handle of instance that contains image
2138 * name [I] Name of image
2139 * type [I] Type of image
2140 * desiredx [I] Desired width
2141 * desiredy [I] Desired height
2142 * loadflags [I] Load flags
2145 * Success: Handle to newly loaded image
2148 * FIXME: Implementation lacks some features, see LR_ defines in winuser.h
2150 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2151 INT desiredx, INT desiredy, UINT loadflags )
2154 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2155 hinst,name,type,desiredx,desiredy,loadflags);
2157 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2158 hinst,name,type,desiredx,desiredy,loadflags);
2160 if (loadflags & LR_DEFAULTSIZE) {
2161 if (type == IMAGE_ICON) {
2162 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2163 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2164 } else if (type == IMAGE_CURSOR) {
2165 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2166 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2169 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2172 return BITMAP_Load( hinst, name, loadflags );
2175 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2178 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2179 if (palEnts == 0) palEnts = 256;
2180 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2181 palEnts, FALSE, loadflags);
2186 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2187 1, TRUE, loadflags);
2193 /******************************************************************************
2194 * CopyImage (USER.390) Creates new image and copies attributes to it
2197 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2198 INT16 desiredy, UINT16 flags )
2200 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2201 (INT)desiredy, (UINT)flags);
2204 /******************************************************************************
2205 * CopyImage (USER32.@) Creates new image and copies attributes to it
2208 * hnd [I] Handle to image to copy
2209 * type [I] Type of image to copy
2210 * desiredx [I] Desired width of new image
2211 * desiredy [I] Desired height of new image
2212 * flags [I] Copy flags
2215 * Success: Handle to newly created image
2218 * FIXME: implementation still lacks nearly all features, see LR_*
2219 * defines in winuser.h
2221 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2222 INT desiredy, UINT flags )
2227 return BITMAP_CopyBitmap(hnd);
2229 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2231 /* Should call CURSORICON_ExtCopy but more testing
2232 * needs to be done before we change this
2234 return CopyCursor(hnd);
2240 /******************************************************************************
2241 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2244 * Success: Handle to specified bitmap
2247 HBITMAP WINAPI LoadBitmapW(
2248 HINSTANCE instance, /* [in] Handle to application instance */
2249 LPCWSTR name) /* [in] Address of bitmap resource name */
2251 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2254 /**********************************************************************
2255 * LoadBitmapA (USER32.@)
2257 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2259 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2262 /**********************************************************************
2263 * LoadBitmap (USER.175)
2265 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2267 return LoadBitmapA( instance, name );