1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS user32.dll
3c2c66affSColin Finck * COPYRIGHT: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: win32ss/user/user32/windows/cursoricon.c
5c2c66affSColin Finck * PURPOSE: cursor and icons implementation
6c2c66affSColin Finck * PROGRAMMER: Jérôme Gardou (jerome.gardou@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include <user32.h>
10c2c66affSColin Finck
11c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(cursor);
12c2c66affSColin Finck WINE_DECLARE_DEBUG_CHANNEL(icon);
13c2c66affSColin Finck //WINE_DECLARE_DEBUG_CHANNEL(resource);
14c2c66affSColin Finck
15c2c66affSColin Finck /* We only use Wide string functions */
16c2c66affSColin Finck #undef MAKEINTRESOURCE
17c2c66affSColin Finck #define MAKEINTRESOURCE MAKEINTRESOURCEW
18c2c66affSColin Finck
19c2c66affSColin Finck /************* USER32 INTERNAL FUNCTIONS **********/
20c2c66affSColin Finck
LoadSystemCursors(VOID)21c2c66affSColin Finck VOID LoadSystemCursors(VOID)
22c2c66affSColin Finck {
23c2c66affSColin Finck if (!gpsi->hIconSmWindows)
24c2c66affSColin Finck {
25c2c66affSColin Finck ERR("Loading System Cursors\n");
26c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_NORMAL);
27c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_IBEAM, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_IBEAM);
28c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_WAIT, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_WAIT);
29c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_CROSS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_CROSS);
30c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_UPARROW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_UP);
31c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_ICON, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_ICON);
32c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZE);
33c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENWSE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENWSE);
34c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENESW, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENESW);
35c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZEWE);
36c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZENS);
37c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_SIZEALL, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_SIZEALL);
38c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_NO, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_NO);
39c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_HAND);
40c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_APPSTARTING, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_APPSTARTING);
41c2c66affSColin Finck NtUserSetSystemCursor(LoadImageW( 0, IDC_HELP, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE ), OCR_HELP);
42c2c66affSColin Finck }
43c2c66affSColin Finck }
44c2c66affSColin Finck
45c2c66affSColin Finck /* This callback routine is called directly after switching to gui mode */
46c2c66affSColin Finck NTSTATUS
47c2c66affSColin Finck WINAPI
User32SetupDefaultCursors(PVOID Arguments,ULONG ArgumentLength)48c2c66affSColin Finck User32SetupDefaultCursors(PVOID Arguments,
49c2c66affSColin Finck ULONG ArgumentLength)
50c2c66affSColin Finck {
51c2c66affSColin Finck BOOL *DefaultCursor = (BOOL*)Arguments;
52c2c66affSColin Finck HCURSOR hCursor;
53c2c66affSColin Finck
54c2c66affSColin Finck /* Load system cursors first */
55c2c66affSColin Finck LoadSystemCursors();
56c2c66affSColin Finck
57c2c66affSColin Finck if(*DefaultCursor)
58c2c66affSColin Finck {
59c2c66affSColin Finck /* set default cursor */
60c2c66affSColin Finck hCursor = LoadCursorW(0, IDC_ARROW);
61c2c66affSColin Finck SetCursor(hCursor);
62c2c66affSColin Finck }
63c2c66affSColin Finck else
64c2c66affSColin Finck {
65c2c66affSColin Finck /* FIXME load system cursor scheme */
66c2c66affSColin Finck SetCursor(0);
67c2c66affSColin Finck hCursor = LoadCursorW(0, IDC_ARROW);
68c2c66affSColin Finck SetCursor(hCursor);
69c2c66affSColin Finck }
70c2c66affSColin Finck
71c2c66affSColin Finck return(ZwCallbackReturn(&hCursor, sizeof(HCURSOR), STATUS_SUCCESS));
72c2c66affSColin Finck }
73c2c66affSColin Finck
get_icon_size(HICON hIcon,SIZE * size)74c2c66affSColin Finck BOOL get_icon_size(HICON hIcon, SIZE *size)
75c2c66affSColin Finck {
76c2c66affSColin Finck return NtUserGetIconSize(hIcon, 0, &size->cx, &size->cy);
77c2c66affSColin Finck }
78c2c66affSColin Finck
CursorIconToCursor(HICON hIcon,BOOL SemiTransparent)79c2c66affSColin Finck HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent)
80c2c66affSColin Finck {
81c2c66affSColin Finck UNIMPLEMENTED;
82c2c66affSColin Finck return NULL;
83c2c66affSColin Finck }
84c2c66affSColin Finck
85c2c66affSColin Finck /************* IMPLEMENTATION HELPERS ******************/
86c2c66affSColin Finck
87c2c66affSColin Finck static const WCHAR DISPLAYW[] = L"DISPLAY";
88c2c66affSColin Finck
map_fileW(LPCWSTR name,LPDWORD filesize)89c2c66affSColin Finck static void *map_fileW( LPCWSTR name, LPDWORD filesize )
90c2c66affSColin Finck {
91c2c66affSColin Finck HANDLE hFile, hMapping;
92c2c66affSColin Finck LPVOID ptr = NULL;
93c2c66affSColin Finck
94c2c66affSColin Finck hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
95c2c66affSColin Finck OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
96c2c66affSColin Finck if (hFile != INVALID_HANDLE_VALUE)
97c2c66affSColin Finck {
98c2c66affSColin Finck hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
99c2c66affSColin Finck if (hMapping)
100c2c66affSColin Finck {
101c2c66affSColin Finck ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
102c2c66affSColin Finck CloseHandle( hMapping );
103c2c66affSColin Finck if (filesize)
104c2c66affSColin Finck *filesize = GetFileSize( hFile, NULL );
105c2c66affSColin Finck }
106c2c66affSColin Finck CloseHandle( hFile );
107c2c66affSColin Finck }
108c2c66affSColin Finck return ptr;
109c2c66affSColin Finck }
110c2c66affSColin Finck
get_dib_image_size(int width,int height,int depth)111c2c66affSColin Finck static int get_dib_image_size( int width, int height, int depth )
112c2c66affSColin Finck {
113c2c66affSColin Finck return (((width * depth + 31) / 8) & ~3) * abs( height );
114c2c66affSColin Finck }
115c2c66affSColin Finck
is_dib_monochrome(const BITMAPINFO * info)116c2c66affSColin Finck static BOOL is_dib_monochrome( const BITMAPINFO* info )
117c2c66affSColin Finck {
118c2c66affSColin Finck if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
119c2c66affSColin Finck {
120c2c66affSColin Finck const RGBTRIPLE *rgb = ((const BITMAPCOREINFO*)info)->bmciColors;
121c2c66affSColin Finck
122c2c66affSColin Finck if (((const BITMAPCOREINFO*)info)->bmciHeader.bcBitCount != 1) return FALSE;
123c2c66affSColin Finck
124c2c66affSColin Finck /* Check if the first color is black */
125c2c66affSColin Finck if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
126c2c66affSColin Finck {
127c2c66affSColin Finck rgb++;
128c2c66affSColin Finck
129c2c66affSColin Finck /* Check if the second color is white */
130c2c66affSColin Finck return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
131c2c66affSColin Finck && (rgb->rgbtBlue == 0xff));
132c2c66affSColin Finck }
133c2c66affSColin Finck else return FALSE;
134c2c66affSColin Finck }
135c2c66affSColin Finck else /* assume BITMAPINFOHEADER */
136c2c66affSColin Finck {
137c2c66affSColin Finck const RGBQUAD *rgb = info->bmiColors;
138c2c66affSColin Finck
139c2c66affSColin Finck if (info->bmiHeader.biBitCount != 1) return FALSE;
140c2c66affSColin Finck
141c2c66affSColin Finck /* Check if the first color is black */
142c2c66affSColin Finck if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
143c2c66affSColin Finck (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
144c2c66affSColin Finck {
145c2c66affSColin Finck rgb++;
146c2c66affSColin Finck
147c2c66affSColin Finck /* Check if the second color is white */
148c2c66affSColin Finck return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
149c2c66affSColin Finck && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
150c2c66affSColin Finck }
151c2c66affSColin Finck else return FALSE;
152c2c66affSColin Finck }
153c2c66affSColin Finck }
154c2c66affSColin Finck
155116c0cd9SDoug Lyons /* Return the size of the bitmap info structure including color table and
156116c0cd9SDoug Lyons * the bytes required for 3 DWORDS if this is a BI_BITFIELDS bmp. */
bitmap_info_size(const BITMAPINFO * info,WORD coloruse)157c2c66affSColin Finck static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
158c2c66affSColin Finck {
159c2c66affSColin Finck unsigned int colors, size, masks = 0;
160c2c66affSColin Finck
161c2c66affSColin Finck if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
162c2c66affSColin Finck {
163c2c66affSColin Finck const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
164c2c66affSColin Finck colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
165c2c66affSColin Finck return sizeof(BITMAPCOREHEADER) + colors *
166c2c66affSColin Finck ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
167c2c66affSColin Finck }
168c2c66affSColin Finck else /* assume BITMAPINFOHEADER */
169c2c66affSColin Finck {
170c2c66affSColin Finck colors = info->bmiHeader.biClrUsed;
171c2c66affSColin Finck if (colors > 256) /* buffer overflow otherwise */
172c2c66affSColin Finck colors = 256;
173c2c66affSColin Finck if (!colors && (info->bmiHeader.biBitCount <= 8))
174c2c66affSColin Finck colors = 1 << info->bmiHeader.biBitCount;
175116c0cd9SDoug Lyons /* Account for BI_BITFIELDS in BITMAPINFOHEADER(v1-v3) bmp's. The
176116c0cd9SDoug Lyons * 'max' selection using biSize below will exclude v4 & v5's. */
177c2c66affSColin Finck if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
178c2c66affSColin Finck size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
179116c0cd9SDoug Lyons /* Test for BI_BITFIELDS format and either 16 or 32 bpp.
180116c0cd9SDoug Lyons * If so, account for the 3 DWORD masks (RGB Order).
181116c0cd9SDoug Lyons * BITMAPCOREHEADER tested above has no 16 or 32 bpp types.
182116c0cd9SDoug Lyons * See table "All of the possible pixel formats in a DIB"
183116c0cd9SDoug Lyons * at https://en.wikipedia.org/wiki/BMP_file_format. */
184116c0cd9SDoug Lyons if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER) &&
185116c0cd9SDoug Lyons info->bmiHeader.biCompression == BI_BITFIELDS &&
186116c0cd9SDoug Lyons (info->bmiHeader.biBitCount == 16 || info->bmiHeader.biBitCount == 32))
187116c0cd9SDoug Lyons {
188116c0cd9SDoug Lyons size += 3 * sizeof(DWORD); // BI_BITFIELDS
189116c0cd9SDoug Lyons }
190c2c66affSColin Finck return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
191c2c66affSColin Finck }
192c2c66affSColin Finck }
193c2c66affSColin Finck
DIB_GetBitmapInfo(const BITMAPINFOHEADER * header,LONG * width,LONG * height,WORD * bpp,DWORD * compr)194c2c66affSColin Finck static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
195c2c66affSColin Finck LONG *height, WORD *bpp, DWORD *compr )
196c2c66affSColin Finck {
197afd39cbcSDoug Lyons #define CR 13
198afd39cbcSDoug Lyons #define LF 10
199afd39cbcSDoug Lyons #define EOFM 26 // DOS End Of File Marker
200afd39cbcSDoug Lyons #define HighBitDetect 0x89 // Byte with high bit set to test if not 7-bit
201afd39cbcSDoug Lyons /* wine's definition */
202afd39cbcSDoug Lyons static const BYTE png_sig_pattern[] = { HighBitDetect, 'P', 'N', 'G', CR, LF, EOFM, LF };
203c2c66affSColin Finck if (header->biSize == sizeof(BITMAPCOREHEADER))
204c2c66affSColin Finck {
205c2c66affSColin Finck const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
206c2c66affSColin Finck *width = core->bcWidth;
207c2c66affSColin Finck *height = core->bcHeight;
208c2c66affSColin Finck *bpp = core->bcBitCount;
209c2c66affSColin Finck *compr = 0;
210c2c66affSColin Finck return 0;
211c2c66affSColin Finck }
212c2c66affSColin Finck else if (header->biSize == sizeof(BITMAPINFOHEADER) ||
213c2c66affSColin Finck header->biSize == sizeof(BITMAPV4HEADER) ||
214c2c66affSColin Finck header->biSize == sizeof(BITMAPV5HEADER))
215c2c66affSColin Finck {
216c2c66affSColin Finck *width = header->biWidth;
217c2c66affSColin Finck *height = header->biHeight;
218c2c66affSColin Finck *bpp = header->biBitCount;
219c2c66affSColin Finck *compr = header->biCompression;
220c2c66affSColin Finck return 1;
221c2c66affSColin Finck }
222afd39cbcSDoug Lyons if (memcmp(&header->biSize, png_sig_pattern, sizeof(png_sig_pattern)) == 0)
223afd39cbcSDoug Lyons {
224afd39cbcSDoug Lyons ERR("Cannot yet display PNG icons\n");
225afd39cbcSDoug Lyons /* for PNG format details see https://en.wikipedia.org/wiki/PNG */
226afd39cbcSDoug Lyons }
227afd39cbcSDoug Lyons else
228afd39cbcSDoug Lyons {
229afd39cbcSDoug Lyons ERR("Unknown/wrong size for header of 0x%x\n", header->biSize );
230afd39cbcSDoug Lyons }
231c2c66affSColin Finck return -1;
232c2c66affSColin Finck }
233c2c66affSColin Finck
234c2c66affSColin Finck /* copy an icon bitmap, even when it can't be selected into a DC */
235c2c66affSColin Finck /* helper for CreateIconIndirect */
stretch_blt_icon(HDC hdc_dst,int dst_width,int dst_height,HBITMAP src)236c2c66affSColin Finck static void stretch_blt_icon(HDC hdc_dst, int dst_width, int dst_height, HBITMAP src)
237c2c66affSColin Finck {
238c2c66affSColin Finck HDC hdc = CreateCompatibleDC( 0 );
239c2c66affSColin Finck BITMAP bm;
240c2c66affSColin Finck HBITMAP hbmpPrev;
241c2c66affSColin Finck
242c2c66affSColin Finck GetObjectW(src, sizeof(bm), &bm);
243c2c66affSColin Finck
244c2c66affSColin Finck hbmpPrev = SelectObject(hdc, src);
245c2c66affSColin Finck
246c2c66affSColin Finck if (!hbmpPrev) /* do it the hard way */
247c2c66affSColin Finck {
248c2c66affSColin Finck BITMAPINFO *info;
249c2c66affSColin Finck void *bits;
250c2c66affSColin Finck
251c2c66affSColin Finck if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return;
252c2c66affSColin Finck info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
253c2c66affSColin Finck info->bmiHeader.biWidth = bm.bmWidth;
254c2c66affSColin Finck info->bmiHeader.biHeight = bm.bmHeight;
255c2c66affSColin Finck info->bmiHeader.biPlanes = GetDeviceCaps( hdc_dst, PLANES );
256c2c66affSColin Finck info->bmiHeader.biBitCount = GetDeviceCaps( hdc_dst, BITSPIXEL );
257c2c66affSColin Finck info->bmiHeader.biCompression = BI_RGB;
258c2c66affSColin Finck info->bmiHeader.biSizeImage = get_dib_image_size( bm.bmWidth, bm.bmHeight, info->bmiHeader.biBitCount );
259c2c66affSColin Finck info->bmiHeader.biXPelsPerMeter = 0;
260c2c66affSColin Finck info->bmiHeader.biYPelsPerMeter = 0;
261c2c66affSColin Finck info->bmiHeader.biClrUsed = 0;
262c2c66affSColin Finck info->bmiHeader.biClrImportant = 0;
263c2c66affSColin Finck bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
264c2c66affSColin Finck if (bits && GetDIBits( hdc, src, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
265c2c66affSColin Finck StretchDIBits( hdc_dst, 0, 0, dst_width, dst_height,
266c2c66affSColin Finck 0, 0, bm.bmWidth, bm.bmHeight, bits, info, DIB_RGB_COLORS, SRCCOPY );
267c2c66affSColin Finck
268c2c66affSColin Finck HeapFree( GetProcessHeap(), 0, bits );
269c2c66affSColin Finck HeapFree( GetProcessHeap(), 0, info );
270c2c66affSColin Finck }
271c2c66affSColin Finck else
272c2c66affSColin Finck {
273c2c66affSColin Finck StretchBlt( hdc_dst, 0, 0, dst_width, dst_height, hdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );
274c2c66affSColin Finck SelectObject(hdc, hbmpPrev);
275c2c66affSColin Finck }
276c2c66affSColin Finck
277c2c66affSColin Finck DeleteDC( hdc );
278c2c66affSColin Finck }
279c2c66affSColin Finck
280c2c66affSColin Finck /***********************************************************************
281c2c66affSColin Finck * bmi_has_alpha
282c2c66affSColin Finck */
bmi_has_alpha(const BITMAPINFO * info,const void * bits)283c2c66affSColin Finck static BOOL bmi_has_alpha( const BITMAPINFO *info, const void *bits )
284c2c66affSColin Finck {
285c2c66affSColin Finck int i;
286c2c66affSColin Finck BOOL has_alpha = FALSE;
287c2c66affSColin Finck const unsigned char *ptr = bits;
288c2c66affSColin Finck
289c2c66affSColin Finck if (info->bmiHeader.biBitCount != 32) return FALSE;
290c2c66affSColin Finck for (i = 0; i < info->bmiHeader.biWidth * abs(info->bmiHeader.biHeight); i++, ptr += 4)
291c2c66affSColin Finck if ((has_alpha = (ptr[3] != 0))) break;
292c2c66affSColin Finck return has_alpha;
293c2c66affSColin Finck }
294c2c66affSColin Finck
295c2c66affSColin Finck /***********************************************************************
296c2c66affSColin Finck * create_alpha_bitmap
297c2c66affSColin Finck *
298c2c66affSColin Finck * Create the alpha bitmap for a 32-bpp icon that has an alpha channel.
299c2c66affSColin Finck */
300c2c66affSColin Finck static
301c2c66affSColin Finck HBITMAP
create_alpha_bitmap(_In_opt_ HBITMAP color,_In_opt_ BITMAPINFO * src_info,_In_opt_ const void * color_bits,_In_ LONG width,_In_ LONG height)302c2c66affSColin Finck create_alpha_bitmap(
303c2c66affSColin Finck _In_opt_ HBITMAP color,
304c2c66affSColin Finck _In_opt_ BITMAPINFO *src_info,
305c2c66affSColin Finck _In_opt_ const void *color_bits,
306c2c66affSColin Finck _In_ LONG width,
307c2c66affSColin Finck _In_ LONG height)
308c2c66affSColin Finck {
309c2c66affSColin Finck HBITMAP alpha = NULL, hbmpOld;
310c2c66affSColin Finck HDC hdc = NULL, hdcScreen;
311c2c66affSColin Finck unsigned char *ptr;
312c2c66affSColin Finck void *bits = NULL;
313e9ad66d5STimo Kreuzer ULONG size;
314c2c66affSColin Finck
315c2c66affSColin Finck hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
316c2c66affSColin Finck if (!hdcScreen)
317c2c66affSColin Finck return NULL;
318c2c66affSColin Finck hdc = CreateCompatibleDC(hdcScreen);
319c2c66affSColin Finck if (!hdc)
320c2c66affSColin Finck {
321c2c66affSColin Finck DeleteDC(hdcScreen);
322c2c66affSColin Finck return NULL;
323c2c66affSColin Finck }
324c2c66affSColin Finck
325c2c66affSColin Finck if (color)
326c2c66affSColin Finck {
327c2c66affSColin Finck BITMAP bm;
328c2c66affSColin Finck BITMAPINFO *info = NULL;
329c2c66affSColin Finck
330c2c66affSColin Finck TRACE("Creating alpha bitmap from existing bitmap.\n");
331c2c66affSColin Finck
332c2c66affSColin Finck if (!GetObjectW( color, sizeof(bm), &bm ))
333c2c66affSColin Finck goto done;
334c2c66affSColin Finck if (bm.bmBitsPixel != 32)
335c2c66affSColin Finck goto done;
336c2c66affSColin Finck
337c2c66affSColin Finck size = get_dib_image_size(bm.bmWidth, bm.bmHeight, 32);
338c2c66affSColin Finck
339c2c66affSColin Finck info = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(BITMAPINFO, bmiColors[256]));
340c2c66affSColin Finck if(!info)
341c2c66affSColin Finck goto done;
342c2c66affSColin Finck info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
343c2c66affSColin Finck info->bmiHeader.biWidth = bm.bmWidth;
344c2c66affSColin Finck info->bmiHeader.biHeight = -bm.bmHeight;
345c2c66affSColin Finck info->bmiHeader.biPlanes = 1;
346c2c66affSColin Finck info->bmiHeader.biBitCount = 32;
347c2c66affSColin Finck info->bmiHeader.biCompression = BI_RGB;
348c2c66affSColin Finck info->bmiHeader.biSizeImage = size;
349c2c66affSColin Finck info->bmiHeader.biXPelsPerMeter = 0;
350c2c66affSColin Finck info->bmiHeader.biYPelsPerMeter = 0;
351c2c66affSColin Finck info->bmiHeader.biClrUsed = 0;
352c2c66affSColin Finck info->bmiHeader.biClrImportant = 0;
353c2c66affSColin Finck
354c2c66affSColin Finck bits = HeapAlloc(GetProcessHeap(), 0, size);
355c2c66affSColin Finck if(!bits)
356c2c66affSColin Finck {
357c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, info);
358c2c66affSColin Finck goto done;
359c2c66affSColin Finck }
360c2c66affSColin Finck if(!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
361c2c66affSColin Finck {
362c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, info);
363c2c66affSColin Finck goto done;
364c2c66affSColin Finck }
365c2c66affSColin Finck if (!bmi_has_alpha( info, bits ))
366c2c66affSColin Finck {
367c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, info);
368c2c66affSColin Finck goto done;
369c2c66affSColin Finck }
370c2c66affSColin Finck
371c2c66affSColin Finck /* pre-multiply by alpha */
372c2c66affSColin Finck for (ptr = bits; ptr < ((BYTE*)bits + size); ptr += 4)
373c2c66affSColin Finck {
374c2c66affSColin Finck unsigned int alpha = ptr[3];
375c2c66affSColin Finck ptr[0] = (ptr[0] * alpha) / 255;
376c2c66affSColin Finck ptr[1] = (ptr[1] * alpha) / 255;
377c2c66affSColin Finck ptr[2] = (ptr[2] * alpha) / 255;
378c2c66affSColin Finck }
379c2c66affSColin Finck
380c2c66affSColin Finck /* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */
381c2c66affSColin Finck alpha = CreateDIBitmap(hdc, NULL, CBM_INIT | 2, bits, info, DIB_RGB_COLORS);
382c2c66affSColin Finck
383c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, info);
384c2c66affSColin Finck }
385c2c66affSColin Finck else
386c2c66affSColin Finck {
387c2c66affSColin Finck WORD bpp;
388c2c66affSColin Finck DWORD compr;
389c2c66affSColin Finck LONG orig_width, orig_height;
390c2c66affSColin Finck
391c2c66affSColin Finck TRACE("Creating alpha bitmap from bitmap info.\n");
392c2c66affSColin Finck
393c2c66affSColin Finck if(!bmi_has_alpha(src_info, color_bits))
394c2c66affSColin Finck goto done;
395c2c66affSColin Finck
396c2c66affSColin Finck if(!DIB_GetBitmapInfo(&src_info->bmiHeader, &orig_width, &orig_height, &bpp, &compr))
397c2c66affSColin Finck goto done;
398c2c66affSColin Finck if(bpp != 32)
399c2c66affSColin Finck goto done;
400c2c66affSColin Finck
401c2c66affSColin Finck size = get_dib_image_size(orig_width, orig_height, bpp);
402c2c66affSColin Finck bits = HeapAlloc(GetProcessHeap(), 0, size);
403c2c66affSColin Finck if(!bits)
404c2c66affSColin Finck goto done;
405c2c66affSColin Finck CopyMemory(bits, color_bits, size);
406c2c66affSColin Finck /* pre-multiply by alpha */
407c2c66affSColin Finck for (ptr = bits; ptr < ((BYTE*)bits + size); ptr += 4)
408c2c66affSColin Finck {
409c2c66affSColin Finck unsigned int alpha = ptr[3];
410c2c66affSColin Finck ptr[0] = (ptr[0] * alpha) / 255;
411c2c66affSColin Finck ptr[1] = (ptr[1] * alpha) / 255;
412c2c66affSColin Finck ptr[2] = (ptr[2] * alpha) / 255;
413c2c66affSColin Finck }
414c2c66affSColin Finck
415c2c66affSColin Finck /* Create the bitmap. Set the bitmap info to have the right width and height */
416c2c66affSColin Finck if(src_info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
417c2c66affSColin Finck {
418c2c66affSColin Finck ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcWidth = width;
419c2c66affSColin Finck ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = height;
420c2c66affSColin Finck }
421c2c66affSColin Finck else
422c2c66affSColin Finck {
423c2c66affSColin Finck src_info->bmiHeader.biWidth = width;
424c2c66affSColin Finck src_info->bmiHeader.biHeight = height;
425c2c66affSColin Finck }
426c2c66affSColin Finck /* Directly create a 32-bits DDB (thanks to undocumented CreateDIBitmap flag). */
427c2c66affSColin Finck alpha = CreateDIBitmap(hdcScreen, NULL, 2, NULL, src_info, DIB_RGB_COLORS);
428c2c66affSColin Finck /* Restore values */
429c2c66affSColin Finck if(src_info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
430c2c66affSColin Finck {
431c2c66affSColin Finck ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcWidth = orig_width;
432c2c66affSColin Finck ((BITMAPCOREHEADER*)&src_info->bmiHeader)->bcHeight = orig_height;
433c2c66affSColin Finck }
434c2c66affSColin Finck else
435c2c66affSColin Finck {
436c2c66affSColin Finck src_info->bmiHeader.biWidth = orig_width;
437c2c66affSColin Finck src_info->bmiHeader.biHeight = orig_height;
438c2c66affSColin Finck }
439c2c66affSColin Finck if(!alpha)
440c2c66affSColin Finck goto done;
441c2c66affSColin Finck hbmpOld = SelectObject(hdc, alpha);
442c2c66affSColin Finck if(!hbmpOld)
443c2c66affSColin Finck {
444c2c66affSColin Finck DeleteObject(alpha);
445c2c66affSColin Finck alpha = NULL;
446c2c66affSColin Finck goto done;
447c2c66affSColin Finck }
448c2c66affSColin Finck if(!StretchDIBits( hdc, 0, 0, width, height,
449c2c66affSColin Finck 0, 0, orig_width, orig_height,
450c2c66affSColin Finck bits, src_info, DIB_RGB_COLORS, SRCCOPY ))
451c2c66affSColin Finck {
452c2c66affSColin Finck SelectObject(hdc, hbmpOld);
453c2c66affSColin Finck hbmpOld = NULL;
454c2c66affSColin Finck DeleteObject(alpha);
455c2c66affSColin Finck alpha = NULL;
456c2c66affSColin Finck }
457c2c66affSColin Finck else
458c2c66affSColin Finck {
459c2c66affSColin Finck SelectObject(hdc, hbmpOld);
460c2c66affSColin Finck }
461c2c66affSColin Finck }
462c2c66affSColin Finck
463c2c66affSColin Finck done:
464c2c66affSColin Finck DeleteDC(hdcScreen);
465c2c66affSColin Finck DeleteDC( hdc );
466c2c66affSColin Finck if(bits) HeapFree(GetProcessHeap(), 0, bits);
467c2c66affSColin Finck
468c2c66affSColin Finck TRACE("Returning 0x%08x.\n", alpha);
469c2c66affSColin Finck return alpha;
470c2c66affSColin Finck }
471c2c66affSColin Finck
472c2c66affSColin Finck #include "pshpack1.h"
473c2c66affSColin Finck
474c2c66affSColin Finck typedef struct {
475c2c66affSColin Finck BYTE bWidth;
476c2c66affSColin Finck BYTE bHeight;
477c2c66affSColin Finck BYTE bColorCount;
478c2c66affSColin Finck BYTE bReserved;
479c2c66affSColin Finck WORD xHotspot;
480c2c66affSColin Finck WORD yHotspot;
481c2c66affSColin Finck DWORD dwDIBSize;
482c2c66affSColin Finck DWORD dwDIBOffset;
483c2c66affSColin Finck } CURSORICONFILEDIRENTRY;
484c2c66affSColin Finck
485c2c66affSColin Finck typedef struct
486c2c66affSColin Finck {
487c2c66affSColin Finck WORD idReserved;
488c2c66affSColin Finck WORD idType;
489c2c66affSColin Finck WORD idCount;
490c2c66affSColin Finck CURSORICONFILEDIRENTRY idEntries[1];
491c2c66affSColin Finck } CURSORICONFILEDIR;
492c2c66affSColin Finck
493c2c66affSColin Finck #include "poppack.h"
494c2c66affSColin Finck
495c2c66affSColin Finck const CURSORICONFILEDIRENTRY*
get_best_icon_file_entry(_In_ const CURSORICONFILEDIR * dir,_In_ DWORD dwFileSize,_In_ int cxDesired,_In_ int cyDesired,_In_ BOOL bIcon,_In_ DWORD fuLoad)496c2c66affSColin Finck get_best_icon_file_entry(
497c2c66affSColin Finck _In_ const CURSORICONFILEDIR* dir,
498c2c66affSColin Finck _In_ DWORD dwFileSize,
499c2c66affSColin Finck _In_ int cxDesired,
500c2c66affSColin Finck _In_ int cyDesired,
501c2c66affSColin Finck _In_ BOOL bIcon,
502c2c66affSColin Finck _In_ DWORD fuLoad
503c2c66affSColin Finck )
504c2c66affSColin Finck {
505c2c66affSColin Finck CURSORICONDIR* fakeDir;
506c2c66affSColin Finck CURSORICONDIRENTRY* fakeEntry;
507c2c66affSColin Finck WORD i;
508c2c66affSColin Finck const CURSORICONFILEDIRENTRY* entry;
509c2c66affSColin Finck
510c2c66affSColin Finck /* Check our file is what it claims to be */
511c2c66affSColin Finck if ( dwFileSize < sizeof(*dir) )
512c2c66affSColin Finck return NULL;
513c2c66affSColin Finck
514c2c66affSColin Finck if (dwFileSize < FIELD_OFFSET(CURSORICONFILEDIR, idEntries[dir->idCount]))
515c2c66affSColin Finck return NULL;
516c2c66affSColin Finck
517c2c66affSColin Finck /*
518c2c66affSColin Finck * Cute little hack:
519c2c66affSColin Finck * We allocate a buffer, fake it as if it was a pointer to a resource in a module,
520c2c66affSColin Finck * pass it to LookupIconIdFromDirectoryEx and get back the index we have to use
521c2c66affSColin Finck */
522c2c66affSColin Finck fakeDir = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(CURSORICONDIR, idEntries[dir->idCount]));
523c2c66affSColin Finck if(!fakeDir)
524c2c66affSColin Finck {
525c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY);
526c2c66affSColin Finck return NULL;
527c2c66affSColin Finck }
528c2c66affSColin Finck fakeDir->idReserved = 0;
529c2c66affSColin Finck fakeDir->idType = dir->idType;
530c2c66affSColin Finck fakeDir->idCount = dir->idCount;
531c2c66affSColin Finck for(i = 0; i<dir->idCount; i++)
532c2c66affSColin Finck {
533c2c66affSColin Finck fakeEntry = &fakeDir->idEntries[i];
534c2c66affSColin Finck entry = &dir->idEntries[i];
535c2c66affSColin Finck /* Take this as an occasion to perform a size check */
536c2c66affSColin Finck if ((entry->dwDIBOffset > dwFileSize)
537c2c66affSColin Finck || ((entry->dwDIBOffset + entry->dwDIBSize) > dwFileSize))
538c2c66affSColin Finck {
539c2c66affSColin Finck ERR("Corrupted icon file?.\n");
540c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, fakeDir);
541c2c66affSColin Finck return NULL;
542c2c66affSColin Finck }
543c2c66affSColin Finck /* File icon/cursors are not like resource ones */
544c2c66affSColin Finck if(bIcon)
545c2c66affSColin Finck {
546c2c66affSColin Finck fakeEntry->ResInfo.icon.bWidth = entry->bWidth;
547c2c66affSColin Finck fakeEntry->ResInfo.icon.bHeight = entry->bHeight;
548c2c66affSColin Finck fakeEntry->ResInfo.icon.bColorCount = 0;
549c2c66affSColin Finck fakeEntry->ResInfo.icon.bReserved = 0;
550c2c66affSColin Finck }
551c2c66affSColin Finck else
552c2c66affSColin Finck {
553c2c66affSColin Finck fakeEntry->ResInfo.cursor.wWidth = entry->bWidth;
554c2c66affSColin Finck fakeEntry->ResInfo.cursor.wHeight = entry->bHeight;
555c2c66affSColin Finck }
556c2c66affSColin Finck /* Let's assume there's always one plane */
557c2c66affSColin Finck fakeEntry->wPlanes = 1;
558c2c66affSColin Finck /* We must get the bitcount from the BITMAPINFOHEADER itself */
559c2c66affSColin Finck if (((BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset))->biSize == sizeof(BITMAPCOREHEADER))
560c2c66affSColin Finck fakeEntry->wBitCount = ((BITMAPCOREHEADER *)((char *)dir + entry->dwDIBOffset))->bcBitCount;
561c2c66affSColin Finck else
562c2c66affSColin Finck fakeEntry->wBitCount = ((BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset))->biBitCount;
563c2c66affSColin Finck fakeEntry->dwBytesInRes = entry->dwDIBSize;
564c2c66affSColin Finck fakeEntry->wResId = i + 1;
565c2c66affSColin Finck }
566c2c66affSColin Finck
567c2c66affSColin Finck /* Now call LookupIconIdFromResourceEx */
568c2c66affSColin Finck i = LookupIconIdFromDirectoryEx((PBYTE)fakeDir, bIcon, cxDesired, cyDesired, fuLoad & LR_MONOCHROME);
569c2c66affSColin Finck /* We don't need this anymore */
570c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, fakeDir);
571c2c66affSColin Finck if(i == 0)
572c2c66affSColin Finck {
573c2c66affSColin Finck WARN("Unable to get a fit entry index.\n");
574c2c66affSColin Finck return NULL;
575c2c66affSColin Finck }
576c2c66affSColin Finck
577c2c66affSColin Finck /* We found it */
578c2c66affSColin Finck return &dir->idEntries[i-1];
579c2c66affSColin Finck }
580c2c66affSColin Finck
581c2c66affSColin Finck DWORD
get_best_icon_file_offset(_In_ const LPBYTE dir,_In_ DWORD dwFileSize,_In_ int cxDesired,_In_ int cyDesired,_In_ BOOL bIcon,_In_ DWORD fuLoad,_Out_ POINT * ptHotSpot)582c2c66affSColin Finck get_best_icon_file_offset(
583c2c66affSColin Finck _In_ const LPBYTE dir,
584c2c66affSColin Finck _In_ DWORD dwFileSize,
585c2c66affSColin Finck _In_ int cxDesired,
586c2c66affSColin Finck _In_ int cyDesired,
587c2c66affSColin Finck _In_ BOOL bIcon,
588c2c66affSColin Finck _In_ DWORD fuLoad,
589c2c66affSColin Finck _Out_ POINT *ptHotSpot
590c2c66affSColin Finck )
591c2c66affSColin Finck {
592c2c66affSColin Finck const CURSORICONFILEDIRENTRY *entry;
593c2c66affSColin Finck
594c2c66affSColin Finck entry = get_best_icon_file_entry((CURSORICONFILEDIR *) dir, dwFileSize, cxDesired, cyDesired, bIcon, fuLoad);
595c2c66affSColin Finck
596c2c66affSColin Finck if(ptHotSpot)
597c2c66affSColin Finck {
598c2c66affSColin Finck ptHotSpot->x = entry->xHotspot;
599c2c66affSColin Finck ptHotSpot->y = entry->yHotspot;
600c2c66affSColin Finck }
601c2c66affSColin Finck
602c2c66affSColin Finck if(entry)
603c2c66affSColin Finck return entry->dwDIBOffset;
604c2c66affSColin Finck
605c2c66affSColin Finck return 0;
606c2c66affSColin Finck }
607c2c66affSColin Finck
608c2c66affSColin Finck
609c2c66affSColin Finck
610c2c66affSColin Finck /************* IMPLEMENTATION CORE ****************/
611c2c66affSColin Finck
CURSORICON_GetCursorDataFromBMI(_Inout_ CURSORDATA * pdata,_In_ const BITMAPINFO * pbmi)612c2c66affSColin Finck static BOOL CURSORICON_GetCursorDataFromBMI(
613c2c66affSColin Finck _Inout_ CURSORDATA* pdata,
614c2c66affSColin Finck _In_ const BITMAPINFO *pbmi
615c2c66affSColin Finck )
616c2c66affSColin Finck {
617c2c66affSColin Finck UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
618c2c66affSColin Finck BOOL monochrome = is_dib_monochrome(pbmi);
619c2c66affSColin Finck LONG width, height;
620c2c66affSColin Finck WORD bpp;
621c2c66affSColin Finck DWORD compr;
622c2c66affSColin Finck int ibmpType;
623c2c66affSColin Finck HDC hdc, hdcScreen;
624c2c66affSColin Finck BITMAPINFO* pbmiCopy;
625c2c66affSColin Finck HBITMAP hbmpOld = NULL;
626c2c66affSColin Finck BOOL bResult = FALSE;
627c2c66affSColin Finck const VOID *pvColor, *pvMask;
628c2c66affSColin Finck
629c2c66affSColin Finck ibmpType = DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height, &bpp, &compr);
630c2c66affSColin Finck /* Invalid data */
631c2c66affSColin Finck if(ibmpType < 0)
632c2c66affSColin Finck return FALSE;
633c2c66affSColin Finck
634c2c66affSColin Finck /* No compression for icons */
635c2c66affSColin Finck if(compr != BI_RGB)
636c2c66affSColin Finck return FALSE;
637c2c66affSColin Finck
638c2c66affSColin Finck /* If no dimensions were set, use the one from the icon */
639c2c66affSColin Finck if(!pdata->cx) pdata->cx = width;
640c2c66affSColin Finck if(!pdata->cy) pdata->cy = height < 0 ? -height/2 : height/2;
641c2c66affSColin Finck
642c2c66affSColin Finck /* Fix the hotspot coords */
643c2c66affSColin Finck if(pdata->rt == (USHORT)((ULONG_PTR)RT_CURSOR))
644c2c66affSColin Finck {
645c2c66affSColin Finck if(pdata->cx != width)
646c2c66affSColin Finck pdata->xHotspot = (pdata->xHotspot * pdata->cx) / width;
647c2c66affSColin Finck if(pdata->cy != height/2)
648c2c66affSColin Finck pdata->yHotspot = (pdata->yHotspot * pdata->cy * 2) / height;
649c2c66affSColin Finck }
650c2c66affSColin Finck else
651c2c66affSColin Finck {
652c2c66affSColin Finck pdata->xHotspot = pdata->cx/2;
653c2c66affSColin Finck pdata->yHotspot = pdata->cy/2;
654c2c66affSColin Finck }
655c2c66affSColin Finck
656c2c66affSColin Finck hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
657c2c66affSColin Finck if(!hdcScreen)
658c2c66affSColin Finck return FALSE;
659c2c66affSColin Finck hdc = CreateCompatibleDC(hdcScreen);
660c2c66affSColin Finck if(!hdc)
661c2c66affSColin Finck {
662c2c66affSColin Finck DeleteDC(hdcScreen);
663c2c66affSColin Finck return FALSE;
664c2c66affSColin Finck }
665c2c66affSColin Finck
666c2c66affSColin Finck pbmiCopy = HeapAlloc(GetProcessHeap(), 0, max(ubmiSize, FIELD_OFFSET(BITMAPINFO, bmiColors[3])));
667c2c66affSColin Finck if(!pbmiCopy)
668c2c66affSColin Finck goto done;
669c2c66affSColin Finck RtlCopyMemory(pbmiCopy, pbmi, ubmiSize);
670c2c66affSColin Finck
671c2c66affSColin Finck /* In an icon/cursor, the BITMAPINFO holds twice the height */
672c2c66affSColin Finck if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
673c2c66affSColin Finck ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcHeight /= 2;
674c2c66affSColin Finck else
675c2c66affSColin Finck pbmiCopy->bmiHeader.biHeight /= 2;
676c2c66affSColin Finck height /= 2;
677c2c66affSColin Finck
678c2c66affSColin Finck pvColor = (const char*)pbmi + ubmiSize;
679c2c66affSColin Finck pvMask = (const char*)pvColor +
680c2c66affSColin Finck get_dib_image_size(width, height, bpp );
681c2c66affSColin Finck
682c2c66affSColin Finck /* Set XOR bits */
683c2c66affSColin Finck if(monochrome)
684c2c66affSColin Finck {
685c2c66affSColin Finck /* Create the 1bpp bitmap which will contain everything */
686c2c66affSColin Finck pdata->hbmColor = NULL;
687c2c66affSColin Finck pdata->hbmMask = CreateBitmap(pdata->cx, pdata->cy * 2, 1, 1, NULL);
688c2c66affSColin Finck if(!pdata->hbmMask)
689c2c66affSColin Finck goto done;
690c2c66affSColin Finck hbmpOld = SelectObject(hdc, pdata->hbmMask);
691c2c66affSColin Finck if(!hbmpOld)
692c2c66affSColin Finck goto done;
693c2c66affSColin Finck
694c2c66affSColin Finck if(!StretchDIBits(hdc, 0, pdata->cy, pdata->cx, pdata->cy,
695c2c66affSColin Finck 0, 0, width, height,
696c2c66affSColin Finck pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
697c2c66affSColin Finck goto done;
698c2c66affSColin Finck pdata->bpp = 1;
699c2c66affSColin Finck }
700c2c66affSColin Finck else
701c2c66affSColin Finck {
702c2c66affSColin Finck /* Create the bitmap. It has to be compatible with the screen surface */
703c2c66affSColin Finck pdata->hbmColor = CreateCompatibleBitmap(hdcScreen, pdata->cx, pdata->cy);
704c2c66affSColin Finck if(!pdata->hbmColor)
705c2c66affSColin Finck goto done;
706c2c66affSColin Finck /* Create the 1bpp mask bitmap */
707c2c66affSColin Finck pdata->hbmMask = CreateBitmap(pdata->cx, pdata->cy, 1, 1, NULL);
708c2c66affSColin Finck if(!pdata->hbmMask)
709c2c66affSColin Finck goto done;
710c2c66affSColin Finck hbmpOld = SelectObject(hdc, pdata->hbmColor);
711c2c66affSColin Finck if(!hbmpOld)
712c2c66affSColin Finck goto done;
713c2c66affSColin Finck if(!StretchDIBits(hdc, 0, 0, pdata->cx, pdata->cy,
714c2c66affSColin Finck 0, 0, width, height,
715c2c66affSColin Finck pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
716c2c66affSColin Finck goto done;
717c2c66affSColin Finck pdata->bpp = GetDeviceCaps(hdcScreen, BITSPIXEL);
718c2c66affSColin Finck pdata->hbmAlpha = create_alpha_bitmap(NULL, pbmiCopy, pvColor, pdata->cx, pdata->cy);
719c2c66affSColin Finck
720c2c66affSColin Finck /* Now convert the info to monochrome for the mask bits */
721c2c66affSColin Finck if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
722c2c66affSColin Finck {
723c2c66affSColin Finck RGBQUAD *rgb = pbmiCopy->bmiColors;
724c2c66affSColin Finck
725c2c66affSColin Finck pbmiCopy->bmiHeader.biClrUsed = pbmiCopy->bmiHeader.biClrImportant = 2;
726c2c66affSColin Finck rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
727c2c66affSColin Finck rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
728c2c66affSColin Finck rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
729c2c66affSColin Finck pbmiCopy->bmiHeader.biBitCount = 1;
730c2c66affSColin Finck }
731c2c66affSColin Finck else
732c2c66affSColin Finck {
733c2c66affSColin Finck RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pbmiCopy) + 1);
734c2c66affSColin Finck
735c2c66affSColin Finck rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
736c2c66affSColin Finck rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
737c2c66affSColin Finck ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcBitCount = 1;
738c2c66affSColin Finck }
739c2c66affSColin Finck }
740c2c66affSColin Finck /* Set the mask bits */
741c2c66affSColin Finck if(!SelectObject(hdc, pdata->hbmMask))
742c2c66affSColin Finck goto done;
743c2c66affSColin Finck bResult = StretchDIBits(hdc, 0, 0, pdata->cx, pdata->cy,
744c2c66affSColin Finck 0, 0, width, height,
745c2c66affSColin Finck pvMask, pbmiCopy, DIB_RGB_COLORS, SRCCOPY) != 0;
746c2c66affSColin Finck
747c2c66affSColin Finck done:
748c2c66affSColin Finck DeleteDC(hdcScreen);
749c2c66affSColin Finck if(hbmpOld) SelectObject(hdc, hbmpOld);
750c2c66affSColin Finck DeleteDC(hdc);
751c2c66affSColin Finck if(pbmiCopy) HeapFree(GetProcessHeap(), 0, pbmiCopy);
752c2c66affSColin Finck /* Clean up in case of failure */
753c2c66affSColin Finck if(!bResult)
754c2c66affSColin Finck {
755c2c66affSColin Finck if(pdata->hbmMask) DeleteObject(pdata->hbmMask);
756c2c66affSColin Finck if(pdata->hbmColor) DeleteObject(pdata->hbmColor);
757c2c66affSColin Finck if(pdata->hbmAlpha) DeleteObject(pdata->hbmAlpha);
758c2c66affSColin Finck }
759c2c66affSColin Finck return bResult;
760c2c66affSColin Finck }
761c2c66affSColin Finck
CURSORICON_GetCursorDataFromIconInfo(_Out_ CURSORDATA * pCursorData,_In_ ICONINFO * pIconInfo)762c2c66affSColin Finck static BOOL CURSORICON_GetCursorDataFromIconInfo(
763c2c66affSColin Finck _Out_ CURSORDATA* pCursorData,
764c2c66affSColin Finck _In_ ICONINFO* pIconInfo
765c2c66affSColin Finck )
766c2c66affSColin Finck {
767c2c66affSColin Finck BITMAP bm;
768c2c66affSColin Finck
769c2c66affSColin Finck ZeroMemory(pCursorData, sizeof(*pCursorData));
770c2c66affSColin Finck if(pIconInfo->hbmColor)
771c2c66affSColin Finck {
772c2c66affSColin Finck /* We must convert the color bitmap to screen format */
773c2c66affSColin Finck HDC hdcScreen, hdcMem;
774c2c66affSColin Finck HBITMAP hbmpPrev;
775c2c66affSColin Finck
776c2c66affSColin Finck /* The mask dictates its dimensions */
777c2c66affSColin Finck if (!GetObject(pIconInfo->hbmMask, sizeof(bm), &bm))
778c2c66affSColin Finck return FALSE;
779c2c66affSColin Finck hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
780c2c66affSColin Finck if(!hdcScreen)
781c2c66affSColin Finck return FALSE;
782c2c66affSColin Finck hdcMem = CreateCompatibleDC(hdcScreen);
783c2c66affSColin Finck if(!hdcMem)
784c2c66affSColin Finck {
785c2c66affSColin Finck DeleteDC(hdcScreen);
786c2c66affSColin Finck return FALSE;
787c2c66affSColin Finck }
788c2c66affSColin Finck pCursorData->hbmColor = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
789c2c66affSColin Finck DeleteDC(hdcScreen);
790c2c66affSColin Finck if (!pCursorData->hbmColor)
791c2c66affSColin Finck {
792c2c66affSColin Finck DeleteDC(hdcMem);
793c2c66affSColin Finck return FALSE;
794c2c66affSColin Finck }
795c2c66affSColin Finck hbmpPrev = SelectObject(hdcMem, pCursorData->hbmColor);
796c2c66affSColin Finck if (!hbmpPrev)
797c2c66affSColin Finck {
798c2c66affSColin Finck DeleteDC(hdcMem);
799c2c66affSColin Finck DeleteObject(pCursorData->hbmColor);
800c2c66affSColin Finck return FALSE;
801c2c66affSColin Finck }
802c2c66affSColin Finck stretch_blt_icon( hdcMem, bm.bmWidth, bm.bmHeight, pIconInfo->hbmColor);
803c2c66affSColin Finck SelectObject(hdcMem, hbmpPrev);
804c2c66affSColin Finck DeleteDC(hdcMem);
805c2c66affSColin Finck }
806c2c66affSColin Finck pCursorData->hbmMask = CopyImage(pIconInfo->hbmMask, IMAGE_BITMAP, 0, 0, LR_MONOCHROME);
807c2c66affSColin Finck if(!pCursorData->hbmMask)
808c2c66affSColin Finck return FALSE;
809c2c66affSColin Finck
810c2c66affSColin Finck /* Now, fill some information */
811c2c66affSColin Finck pCursorData->rt = (USHORT)((ULONG_PTR)(pIconInfo->fIcon ? RT_ICON : RT_CURSOR));
812c2c66affSColin Finck if(pCursorData->hbmColor)
813c2c66affSColin Finck {
814c2c66affSColin Finck GetObject(pCursorData->hbmColor, sizeof(bm), &bm);
815c2c66affSColin Finck pCursorData->bpp = bm.bmBitsPixel;
816c2c66affSColin Finck pCursorData->cx = bm.bmWidth;
817c2c66affSColin Finck pCursorData->cy = bm.bmHeight;
818c2c66affSColin Finck if(pCursorData->bpp == 32)
819c2c66affSColin Finck pCursorData->hbmAlpha = create_alpha_bitmap(pCursorData->hbmColor, NULL, NULL, 0, 0);
820c2c66affSColin Finck }
821c2c66affSColin Finck else
822c2c66affSColin Finck {
823c2c66affSColin Finck GetObject(pCursorData->hbmMask, sizeof(bm), &bm);
824c2c66affSColin Finck pCursorData->bpp = 1;
825c2c66affSColin Finck pCursorData->cx = bm.bmWidth;
826c2c66affSColin Finck pCursorData->cy = bm.bmHeight/2;
827c2c66affSColin Finck }
828c2c66affSColin Finck
829c2c66affSColin Finck if(pIconInfo->fIcon)
830c2c66affSColin Finck {
831c2c66affSColin Finck pCursorData->xHotspot = pCursorData->cx/2;
832c2c66affSColin Finck pCursorData->yHotspot = pCursorData->cy/2;
833c2c66affSColin Finck }
834c2c66affSColin Finck else
835c2c66affSColin Finck {
836c2c66affSColin Finck pCursorData->xHotspot = pIconInfo->xHotspot;
837c2c66affSColin Finck pCursorData->yHotspot = pIconInfo->yHotspot;
838c2c66affSColin Finck }
839c2c66affSColin Finck
840c2c66affSColin Finck return TRUE;
841c2c66affSColin Finck }
842c2c66affSColin Finck
843c2c66affSColin Finck
844c2c66affSColin Finck #define RIFF_FOURCC( c0, c1, c2, c3 ) \
845c2c66affSColin Finck ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \
846c2c66affSColin Finck ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) )
847c2c66affSColin Finck
848c2c66affSColin Finck #define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F')
849c2c66affSColin Finck #define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T')
850c2c66affSColin Finck #define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N')
851c2c66affSColin Finck #define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h')
852c2c66affSColin Finck #define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ')
853c2c66affSColin Finck #define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm')
854c2c66affSColin Finck #define ANI_rate_ID RIFF_FOURCC('r', 'a', 't', 'e')
855c2c66affSColin Finck
856c2c66affSColin Finck #define ANI_FLAG_ICON 0x1
857c2c66affSColin Finck #define ANI_FLAG_SEQUENCE 0x2
858c2c66affSColin Finck
859c2c66affSColin Finck #include <pshpack1.h>
860c2c66affSColin Finck typedef struct {
861c2c66affSColin Finck DWORD header_size;
862c2c66affSColin Finck DWORD num_frames;
863c2c66affSColin Finck DWORD num_steps;
864c2c66affSColin Finck DWORD width;
865c2c66affSColin Finck DWORD height;
866c2c66affSColin Finck DWORD bpp;
867c2c66affSColin Finck DWORD num_planes;
868c2c66affSColin Finck DWORD display_rate;
869c2c66affSColin Finck DWORD flags;
870c2c66affSColin Finck } ani_header;
871c2c66affSColin Finck
872c2c66affSColin Finck typedef struct {
873c2c66affSColin Finck DWORD data_size;
874c2c66affSColin Finck const unsigned char *data;
875c2c66affSColin Finck } riff_chunk_t;
876c2c66affSColin Finck #include <poppack.h>
877c2c66affSColin Finck
dump_ani_header(const ani_header * header)878c2c66affSColin Finck static void dump_ani_header( const ani_header *header )
879c2c66affSColin Finck {
880c2c66affSColin Finck TRACE(" header size: %d\n", header->header_size);
881c2c66affSColin Finck TRACE(" frames: %d\n", header->num_frames);
882c2c66affSColin Finck TRACE(" steps: %d\n", header->num_steps);
883c2c66affSColin Finck TRACE(" width: %d\n", header->width);
884c2c66affSColin Finck TRACE(" height: %d\n", header->height);
885c2c66affSColin Finck TRACE(" bpp: %d\n", header->bpp);
886c2c66affSColin Finck TRACE(" planes: %d\n", header->num_planes);
887c2c66affSColin Finck TRACE(" display rate: %d\n", header->display_rate);
888c2c66affSColin Finck TRACE(" flags: 0x%08x\n", header->flags);
889c2c66affSColin Finck }
890c2c66affSColin Finck
891c2c66affSColin Finck /* Find an animated cursor chunk, given its type and ID */
riff_find_chunk(DWORD chunk_id,DWORD chunk_type,const riff_chunk_t * parent_chunk,riff_chunk_t * chunk)892c2c66affSColin Finck static void riff_find_chunk( DWORD chunk_id, DWORD chunk_type, const riff_chunk_t *parent_chunk, riff_chunk_t *chunk )
893c2c66affSColin Finck {
894c2c66affSColin Finck const unsigned char *ptr = parent_chunk->data;
895c2c66affSColin Finck const unsigned char *end = parent_chunk->data + (parent_chunk->data_size - (2 * sizeof(DWORD)));
896c2c66affSColin Finck
897c2c66affSColin Finck if (chunk_type == ANI_LIST_ID || chunk_type == ANI_RIFF_ID) end -= sizeof(DWORD);
898c2c66affSColin Finck
899c2c66affSColin Finck while (ptr < end)
900c2c66affSColin Finck {
901c2c66affSColin Finck if ((!chunk_type && *(const DWORD *)ptr == chunk_id )
902c2c66affSColin Finck || (chunk_type && *(const DWORD *)ptr == chunk_type && *((const DWORD *)ptr + 2) == chunk_id ))
903c2c66affSColin Finck {
904c2c66affSColin Finck ptr += sizeof(DWORD);
905c2c66affSColin Finck chunk->data_size = (*(const DWORD *)ptr + 1) & ~1;
906c2c66affSColin Finck ptr += sizeof(DWORD);
907c2c66affSColin Finck if (chunk_type == ANI_LIST_ID || chunk_type == ANI_RIFF_ID) ptr += sizeof(DWORD);
908c2c66affSColin Finck chunk->data = ptr;
909c2c66affSColin Finck
910c2c66affSColin Finck return;
911c2c66affSColin Finck }
912c2c66affSColin Finck
913c2c66affSColin Finck ptr += sizeof(DWORD);
914c2c66affSColin Finck ptr += (*(const DWORD *)ptr + 1) & ~1;
915c2c66affSColin Finck ptr += sizeof(DWORD);
916c2c66affSColin Finck }
917c2c66affSColin Finck }
918c2c66affSColin Finck
CURSORICON_GetCursorDataFromANI(_Inout_ CURSORDATA * pCurData,_In_ const BYTE * pData,_In_ DWORD dwDataSize,_In_ DWORD fuLoad)919c2c66affSColin Finck static BOOL CURSORICON_GetCursorDataFromANI(
920c2c66affSColin Finck _Inout_ CURSORDATA* pCurData,
921c2c66affSColin Finck _In_ const BYTE *pData,
922c2c66affSColin Finck _In_ DWORD dwDataSize,
923c2c66affSColin Finck _In_ DWORD fuLoad
924c2c66affSColin Finck )
925c2c66affSColin Finck {
926c2c66affSColin Finck UINT i;
927c2c66affSColin Finck const ani_header *pHeader;
928c2c66affSColin Finck riff_chunk_t root_chunk = { dwDataSize, pData };
929c2c66affSColin Finck riff_chunk_t ACON_chunk = {0};
930c2c66affSColin Finck riff_chunk_t anih_chunk = {0};
931c2c66affSColin Finck riff_chunk_t fram_chunk = {0};
932c2c66affSColin Finck riff_chunk_t rate_chunk = {0};
933c2c66affSColin Finck riff_chunk_t seq_chunk = {0};
934c2c66affSColin Finck const unsigned char *icon_chunk;
935c2c66affSColin Finck const unsigned char *icon_data;
936c2c66affSColin Finck
937c2c66affSColin Finck /* Find the root chunk */
938c2c66affSColin Finck riff_find_chunk( ANI_ACON_ID, ANI_RIFF_ID, &root_chunk, &ACON_chunk );
939c2c66affSColin Finck if (!ACON_chunk.data)
940c2c66affSColin Finck {
941c2c66affSColin Finck ERR("Failed to get root chunk.\n");
942c2c66affSColin Finck return FALSE;
943c2c66affSColin Finck }
944c2c66affSColin Finck
945c2c66affSColin Finck /* Find the header chunk */
946c2c66affSColin Finck riff_find_chunk( ANI_anih_ID, 0, &ACON_chunk, &anih_chunk );
947c2c66affSColin Finck if (!ACON_chunk.data)
948c2c66affSColin Finck {
949c2c66affSColin Finck ERR("Failed to get header chunk.\n");
950c2c66affSColin Finck return FALSE;
951c2c66affSColin Finck }
952c2c66affSColin Finck pHeader = (ani_header*)anih_chunk.data;
953c2c66affSColin Finck dump_ani_header(pHeader);
954c2c66affSColin Finck
955c2c66affSColin Finck /* Set up the master data */
956c2c66affSColin Finck pCurData->CURSORF_flags |= CURSORF_ACON;
957c2c66affSColin Finck pCurData->cpcur = pHeader->num_frames;
958c2c66affSColin Finck pCurData->cicur = pHeader->num_steps;
959c2c66affSColin Finck pCurData->iicur = pHeader->display_rate;
960c2c66affSColin Finck
961c2c66affSColin Finck /* Get the sequences */
962c2c66affSColin Finck if (pHeader->flags & ANI_FLAG_SEQUENCE)
963c2c66affSColin Finck {
964c2c66affSColin Finck riff_find_chunk( ANI_seq__ID, 0, &ACON_chunk, &seq_chunk );
965c2c66affSColin Finck if (!seq_chunk.data)
966c2c66affSColin Finck {
967c2c66affSColin Finck ERR("No sequence data although the flag is set!\n");
968c2c66affSColin Finck return FALSE;
969c2c66affSColin Finck }
970c2c66affSColin Finck }
971c2c66affSColin Finck
972c2c66affSColin Finck /* Get the frame rates */
973c2c66affSColin Finck riff_find_chunk( ANI_rate_ID, 0, &ACON_chunk, &rate_chunk );
974c2c66affSColin Finck if (rate_chunk.data)
975c2c66affSColin Finck pCurData->ajifRate = (INT*)rate_chunk.data;
976c2c66affSColin Finck
977c2c66affSColin Finck /* Get the frames chunk */
978c2c66affSColin Finck riff_find_chunk( ANI_fram_ID, ANI_LIST_ID, &ACON_chunk, &fram_chunk );
979c2c66affSColin Finck if (!fram_chunk.data)
980c2c66affSColin Finck {
981c2c66affSColin Finck ERR("Failed to get icon list.\n");
982c2c66affSColin Finck return 0;
983c2c66affSColin Finck }
984c2c66affSColin Finck icon_chunk = fram_chunk.data;
985c2c66affSColin Finck icon_data = fram_chunk.data + (2 * sizeof(DWORD));
986c2c66affSColin Finck
987c2c66affSColin Finck if(pHeader->num_frames > 1)
988c2c66affSColin Finck {
989c2c66affSColin Finck /* Allocate frame descriptors, step indices and rates */
990c2c66affSColin Finck pCurData->aspcur = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
991c2c66affSColin Finck pHeader->num_frames * sizeof(CURSORDATA) + pHeader->num_steps * (sizeof(DWORD) + sizeof(INT)));
992c2c66affSColin Finck if(!pCurData->aspcur)
993c2c66affSColin Finck {
994c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY);
995c2c66affSColin Finck return FALSE;
996c2c66affSColin Finck }
997c2c66affSColin Finck pCurData->aicur = (DWORD*)(pCurData->aspcur + pHeader->num_frames);
998c2c66affSColin Finck pCurData->ajifRate = (INT*)(pCurData->aicur + pHeader->num_steps);
999c2c66affSColin Finck }
1000c2c66affSColin Finck
1001c2c66affSColin Finck for(i=0; i < pHeader->num_frames; i++)
1002c2c66affSColin Finck {
1003c2c66affSColin Finck CURSORDATA* pFrameData;
1004c2c66affSColin Finck const DWORD chunk_size = *(const DWORD *)(icon_chunk + sizeof(DWORD));
1005c2c66affSColin Finck const BITMAPINFO* pbmi;
1006c2c66affSColin Finck
1007c2c66affSColin Finck if(pHeader->num_frames > 1)
1008c2c66affSColin Finck pFrameData = &pCurData->aspcur[i];
1009c2c66affSColin Finck else
1010c2c66affSColin Finck pFrameData = pCurData;
1011c2c66affSColin Finck
1012c2c66affSColin Finck pFrameData->rt = pCurData->rt;
1013c2c66affSColin Finck
1014c2c66affSColin Finck if (pHeader->flags & ANI_FLAG_ICON)
1015c2c66affSColin Finck {
1016c2c66affSColin Finck /* The chunks describe an icon file */
1017c2c66affSColin Finck const CURSORICONFILEDIRENTRY* pDirEntry = get_best_icon_file_entry(
1018c2c66affSColin Finck (const CURSORICONFILEDIR *) icon_data,
1019c2c66affSColin Finck chunk_size,
1020c2c66affSColin Finck pCurData->cx,
1021c2c66affSColin Finck pCurData->cy,
1022c2c66affSColin Finck TRUE,
1023c2c66affSColin Finck fuLoad);
1024c2c66affSColin Finck if(!pDirEntry)
1025c2c66affSColin Finck {
1026c2c66affSColin Finck ERR("Unable to find the right file entry for frame %d.\n", i);
1027c2c66affSColin Finck goto error;
1028c2c66affSColin Finck }
1029c2c66affSColin Finck pFrameData->xHotspot = pDirEntry->xHotspot;
1030c2c66affSColin Finck pFrameData->yHotspot = pDirEntry->yHotspot;
1031c2c66affSColin Finck if(!pHeader->width || !pHeader->height)
1032c2c66affSColin Finck {
1033c2c66affSColin Finck pFrameData->cx = pDirEntry->bWidth;
1034c2c66affSColin Finck pFrameData->cy = pDirEntry->bHeight;
1035c2c66affSColin Finck }
1036c2c66affSColin Finck else
1037c2c66affSColin Finck {
1038c2c66affSColin Finck pFrameData->cx = pHeader->width;
1039c2c66affSColin Finck pFrameData->cy = pHeader->height;
1040c2c66affSColin Finck }
1041c2c66affSColin Finck pbmi = (const BITMAPINFO *) (icon_data + pDirEntry->dwDIBOffset);
1042c2c66affSColin Finck }
1043c2c66affSColin Finck else
1044c2c66affSColin Finck {
1045c2c66affSColin Finck /* The chunks just describe bitmaps */
1046c2c66affSColin Finck pbmi = (const BITMAPINFO *)icon_data;
1047c2c66affSColin Finck pFrameData->xHotspot = pFrameData->yHotspot = 0;
1048c2c66affSColin Finck }
1049c2c66affSColin Finck
1050c2c66affSColin Finck /* Do the real work */
1051c2c66affSColin Finck CURSORICON_GetCursorDataFromBMI(pFrameData, pbmi);
1052c2c66affSColin Finck
1053c2c66affSColin Finck if(pHeader->num_frames > 1)
1054c2c66affSColin Finck pFrameData->CURSORF_flags |= CURSORF_ACONFRAME;
1055c2c66affSColin Finck else
1056c2c66affSColin Finck pFrameData->CURSORF_flags &= ~CURSORF_ACON;
1057c2c66affSColin Finck
1058c2c66affSColin Finck
1059c2c66affSColin Finck /* Next frame */
1060c2c66affSColin Finck icon_chunk += chunk_size + (2 * sizeof(DWORD));
1061c2c66affSColin Finck icon_data = icon_chunk + (2 * sizeof(DWORD));
1062c2c66affSColin Finck }
1063c2c66affSColin Finck
1064c2c66affSColin Finck if(pHeader->num_frames <= 1)
1065c2c66affSColin Finck return TRUE;
1066c2c66affSColin Finck
1067c2c66affSColin Finck if(rate_chunk.data)
1068c2c66affSColin Finck CopyMemory(pCurData->ajifRate, rate_chunk.data, pHeader->num_steps * sizeof(INT));
1069c2c66affSColin Finck else
1070c2c66affSColin Finck {
1071c2c66affSColin Finck for(i=0; i < pHeader->num_steps; i++)
1072c2c66affSColin Finck pCurData->ajifRate[i] = pHeader->display_rate;
1073c2c66affSColin Finck }
1074c2c66affSColin Finck
1075c2c66affSColin Finck if (pHeader->flags & ANI_FLAG_SEQUENCE)
1076c2c66affSColin Finck {
1077c2c66affSColin Finck CopyMemory(pCurData->aicur, seq_chunk.data, pHeader->num_steps * sizeof(DWORD));
1078c2c66affSColin Finck }
1079c2c66affSColin Finck else
1080c2c66affSColin Finck {
1081c2c66affSColin Finck for(i=0; i < pHeader->num_steps; i++)
1082c2c66affSColin Finck pCurData->aicur[i] = i;
1083c2c66affSColin Finck }
1084c2c66affSColin Finck
1085c2c66affSColin Finck return TRUE;
1086c2c66affSColin Finck
1087c2c66affSColin Finck error:
1088c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pCurData->aspcur);
1089c2c66affSColin Finck ZeroMemory(pCurData, sizeof(CURSORDATA));
1090c2c66affSColin Finck return FALSE;
1091c2c66affSColin Finck }
1092c2c66affSColin Finck
1093c2c66affSColin Finck
1094c2c66affSColin Finck static
1095c2c66affSColin Finck HBITMAP
BITMAP_LoadImageW(_In_opt_ HINSTANCE hinst,_In_ LPCWSTR lpszName,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuLoad)1096c2c66affSColin Finck BITMAP_LoadImageW(
1097c2c66affSColin Finck _In_opt_ HINSTANCE hinst,
1098c2c66affSColin Finck _In_ LPCWSTR lpszName,
1099c2c66affSColin Finck _In_ int cxDesired,
1100c2c66affSColin Finck _In_ int cyDesired,
1101c2c66affSColin Finck _In_ UINT fuLoad
1102c2c66affSColin Finck )
1103c2c66affSColin Finck {
1104c2c66affSColin Finck const BITMAPINFO* pbmi;
1105c2c66affSColin Finck BITMAPINFO* pbmiScaled = NULL;
1106c2c66affSColin Finck BITMAPINFO* pbmiCopy = NULL;
1107c2c66affSColin Finck const VOID* pvMapping = NULL;
1108c2c66affSColin Finck DWORD dwOffset = 0;
1109c2c66affSColin Finck HGLOBAL hgRsrc = NULL;
1110c2c66affSColin Finck int iBMISize;
1111c2c66affSColin Finck PVOID pvBits;
1112c2c66affSColin Finck HDC hdcScreen = NULL;
1113c2c66affSColin Finck HDC hdc = NULL;
1114c2c66affSColin Finck HBITMAP hbmpOld, hbmpRet = NULL;
1115c2c66affSColin Finck LONG width, height;
1116c2c66affSColin Finck WORD bpp;
1117116c0cd9SDoug Lyons DWORD compr, ResSize = 0;
1118c2c66affSColin Finck
1119c2c66affSColin Finck /* Map the bitmap info */
1120c2c66affSColin Finck if(fuLoad & LR_LOADFROMFILE)
1121c2c66affSColin Finck {
1122c2c66affSColin Finck const BITMAPFILEHEADER* pbmfh;
1123c2c66affSColin Finck
1124c2c66affSColin Finck pvMapping = map_fileW(lpszName, NULL);
1125c2c66affSColin Finck if(!pvMapping)
1126c2c66affSColin Finck return NULL;
1127c2c66affSColin Finck pbmfh = pvMapping;
1128c2c66affSColin Finck if (pbmfh->bfType != 0x4d42 /* 'BM' */)
1129c2c66affSColin Finck {
1130c2c66affSColin Finck WARN("Invalid/unsupported bitmap format!\n");
1131c2c66affSColin Finck goto end;
1132c2c66affSColin Finck }
1133c2c66affSColin Finck pbmi = (const BITMAPINFO*)(pbmfh + 1);
1134c2c66affSColin Finck
1135c2c66affSColin Finck /* Get the image bits */
1136c2c66affSColin Finck if(pbmfh->bfOffBits)
1137c2c66affSColin Finck dwOffset = pbmfh->bfOffBits - sizeof(BITMAPFILEHEADER);
1138c2c66affSColin Finck }
1139c2c66affSColin Finck else
1140c2c66affSColin Finck {
1141c2c66affSColin Finck HRSRC hrsrc;
1142c2c66affSColin Finck
1143c2c66affSColin Finck /* Caller wants an OEM bitmap */
1144c2c66affSColin Finck if(!hinst)
1145c2c66affSColin Finck hinst = User32Instance;
1146c2c66affSColin Finck hrsrc = FindResourceW(hinst, lpszName, RT_BITMAP);
1147c2c66affSColin Finck if(!hrsrc)
1148c2c66affSColin Finck return NULL;
1149c2c66affSColin Finck hgRsrc = LoadResource(hinst, hrsrc);
1150c2c66affSColin Finck if(!hgRsrc)
1151c2c66affSColin Finck return NULL;
1152c2c66affSColin Finck pbmi = LockResource(hgRsrc);
1153c2c66affSColin Finck if(!pbmi)
1154c2c66affSColin Finck return NULL;
1155116c0cd9SDoug Lyons ResSize = SizeofResource(hinst, hrsrc);
1156c2c66affSColin Finck }
1157c2c66affSColin Finck
1158c2c66affSColin Finck /* Fix up values */
1159c2c66affSColin Finck if(DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height, &bpp, &compr) == -1)
1160c2c66affSColin Finck goto end;
1161c2c66affSColin Finck if((width > 65535) || (height > 65535))
1162c2c66affSColin Finck goto end;
1163c2c66affSColin Finck if(cxDesired == 0)
1164c2c66affSColin Finck cxDesired = width;
1165c2c66affSColin Finck if(cyDesired == 0)
1166c2c66affSColin Finck cyDesired = height;
1167c2c66affSColin Finck else if(height < 0)
1168c2c66affSColin Finck cyDesired = -cyDesired;
1169c2c66affSColin Finck
1170c2c66affSColin Finck iBMISize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
1171c2c66affSColin Finck
1172c2c66affSColin Finck /* Get a pointer to the image data */
1173c2c66affSColin Finck pvBits = (char*)pbmi + (dwOffset ? dwOffset : iBMISize);
1174c2c66affSColin Finck
1175c2c66affSColin Finck /* Create a copy of the info describing the bitmap in the file */
1176c2c66affSColin Finck pbmiCopy = HeapAlloc(GetProcessHeap(), 0, iBMISize);
1177c2c66affSColin Finck if(!pbmiCopy)
1178c2c66affSColin Finck goto end;
1179c2c66affSColin Finck CopyMemory(pbmiCopy, pbmi, iBMISize);
1180c2c66affSColin Finck
1181116c0cd9SDoug Lyons TRACE("Size Image %d, Size Header %d, ResSize %d\n",
1182116c0cd9SDoug Lyons pbmiCopy->bmiHeader.biSizeImage, pbmiCopy->bmiHeader.biSize, ResSize);
1183116c0cd9SDoug Lyons
1184116c0cd9SDoug Lyons /* HACK: If this is a binutils' windres.exe compiled 16 or 32 bpp bitmap
1185116c0cd9SDoug Lyons * using BI_BITFIELDS, then a bug causes it to fail to include
1186116c0cd9SDoug Lyons * the bytes for the bitfields. So, we have to substract out the
1187116c0cd9SDoug Lyons * size of the bitfields previously included from bitmap_info_size. */
1188116c0cd9SDoug Lyons if (compr == BI_BITFIELDS && (bpp == 16 || bpp == 32) &&
1189116c0cd9SDoug Lyons pbmiCopy->bmiHeader.biSizeImage + pbmiCopy->bmiHeader.biSize == ResSize)
1190116c0cd9SDoug Lyons {
1191116c0cd9SDoug Lyons /* GCC pointer to the image data has 12 less bytes than MSVC */
1192116c0cd9SDoug Lyons pvBits = (char*)pvBits - 12;
1193116c0cd9SDoug Lyons WARN("Found GCC Resource Compiled 16-bpp or 32-bpp error\n");
1194116c0cd9SDoug Lyons }
1195116c0cd9SDoug Lyons
1196c2c66affSColin Finck /* Fix it up, if needed */
1197c2c66affSColin Finck if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS))
1198c2c66affSColin Finck {
1199c2c66affSColin Finck WORD bpp, incr, numColors;
1200c2c66affSColin Finck char* pbmiColors;
1201c2c66affSColin Finck RGBTRIPLE* ptr;
1202c2c66affSColin Finck COLORREF crWindow, cr3DShadow, cr3DFace, cr3DLight;
1203c2c66affSColin Finck BYTE pixel = *((BYTE*)pvBits);
1204c2c66affSColin Finck UINT i;
1205c2c66affSColin Finck
1206c2c66affSColin Finck if(pbmiCopy->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1207c2c66affSColin Finck {
1208c2c66affSColin Finck bpp = ((BITMAPCOREHEADER*)&pbmiCopy->bmiHeader)->bcBitCount;
1209c2c66affSColin Finck numColors = 1 << bpp;
1210c2c66affSColin Finck /* BITMAPCOREINFO holds RGBTRIPLEs */
1211c2c66affSColin Finck incr = 3;
1212c2c66affSColin Finck }
1213c2c66affSColin Finck else
1214c2c66affSColin Finck {
1215c2c66affSColin Finck bpp = pbmiCopy->bmiHeader.biBitCount;
1216c2c66affSColin Finck /* BITMAPINFOHEADER holds RGBQUADs */
1217c2c66affSColin Finck incr = 4;
1218c2c66affSColin Finck numColors = pbmiCopy->bmiHeader.biClrUsed;
1219c2c66affSColin Finck if(numColors > 256) numColors = 256;
1220c2c66affSColin Finck if (!numColors && (bpp <= 8)) numColors = 1 << bpp;
1221c2c66affSColin Finck }
1222c2c66affSColin Finck
1223c2c66affSColin Finck if(bpp > 8)
1224c2c66affSColin Finck goto create_bitmap;
1225c2c66affSColin Finck
1226c2c66affSColin Finck pbmiColors = (char*)pbmiCopy + pbmiCopy->bmiHeader.biSize;
1227c2c66affSColin Finck
1228c2c66affSColin Finck /* Get the relevant colors */
1229c2c66affSColin Finck crWindow = GetSysColor(COLOR_WINDOW);
1230c2c66affSColin Finck cr3DShadow = GetSysColor(COLOR_3DSHADOW);
1231c2c66affSColin Finck cr3DFace = GetSysColor(COLOR_3DFACE);
1232c2c66affSColin Finck cr3DLight = GetSysColor(COLOR_3DLIGHT);
1233c2c66affSColin Finck
1234c2c66affSColin Finck /* Fix the transparent palette entry */
1235c2c66affSColin Finck if(fuLoad & LR_LOADTRANSPARENT)
1236c2c66affSColin Finck {
1237c2c66affSColin Finck switch(bpp)
1238c2c66affSColin Finck {
1239c2c66affSColin Finck case 1: pixel >>= 7; break;
1240c2c66affSColin Finck case 4: pixel >>= 4; break;
1241c2c66affSColin Finck case 8: break;
1242c2c66affSColin Finck default:
1243c2c66affSColin Finck FIXME("Unhandled bit depth %d.\n", bpp);
1244c2c66affSColin Finck goto create_bitmap;
1245c2c66affSColin Finck }
1246c2c66affSColin Finck
1247c2c66affSColin Finck if(pixel >= numColors)
1248c2c66affSColin Finck {
1249c2c66affSColin Finck ERR("Wrong pixel passed in.\n");
1250c2c66affSColin Finck goto create_bitmap;
1251c2c66affSColin Finck }
1252c2c66affSColin Finck
1253c2c66affSColin Finck /* If both flags are set, we must use COLOR_3DFACE */
1254c2c66affSColin Finck if(fuLoad & LR_LOADMAP3DCOLORS) crWindow = cr3DFace;
1255c2c66affSColin Finck
1256c2c66affSColin Finck /* Define the color */
1257c2c66affSColin Finck ptr = (RGBTRIPLE*)(pbmiColors + pixel*incr);
1258c2c66affSColin Finck ptr->rgbtBlue = GetBValue(crWindow);
1259c2c66affSColin Finck ptr->rgbtGreen = GetGValue(crWindow);
1260c2c66affSColin Finck ptr->rgbtRed = GetRValue(crWindow);
1261c2c66affSColin Finck goto create_bitmap;
1262c2c66affSColin Finck }
1263c2c66affSColin Finck
1264c2c66affSColin Finck /* If we are here, then LR_LOADMAP3DCOLORS is set without LR_TRANSPARENT */
1265c2c66affSColin Finck for(i = 0; i<numColors; i++)
1266c2c66affSColin Finck {
1267c2c66affSColin Finck ptr = (RGBTRIPLE*)(pbmiColors + i*incr);
1268c2c66affSColin Finck if((ptr->rgbtBlue == ptr->rgbtRed) && (ptr->rgbtBlue == ptr->rgbtGreen))
1269c2c66affSColin Finck {
1270c2c66affSColin Finck if(ptr->rgbtBlue == 128)
1271c2c66affSColin Finck {
1272c2c66affSColin Finck ptr->rgbtBlue = GetBValue(cr3DShadow);
1273c2c66affSColin Finck ptr->rgbtGreen = GetGValue(cr3DShadow);
1274c2c66affSColin Finck ptr->rgbtRed = GetRValue(cr3DShadow);
1275c2c66affSColin Finck }
1276c2c66affSColin Finck if(ptr->rgbtBlue == 192)
1277c2c66affSColin Finck {
1278c2c66affSColin Finck ptr->rgbtBlue = GetBValue(cr3DFace);
1279c2c66affSColin Finck ptr->rgbtGreen = GetGValue(cr3DFace);
1280c2c66affSColin Finck ptr->rgbtRed = GetRValue(cr3DFace);
1281c2c66affSColin Finck }
1282c2c66affSColin Finck if(ptr->rgbtBlue == 223)
1283c2c66affSColin Finck {
1284c2c66affSColin Finck ptr->rgbtBlue = GetBValue(cr3DLight);
1285c2c66affSColin Finck ptr->rgbtGreen = GetGValue(cr3DLight);
1286c2c66affSColin Finck ptr->rgbtRed = GetRValue(cr3DLight);
1287c2c66affSColin Finck }
1288c2c66affSColin Finck }
1289c2c66affSColin Finck }
1290c2c66affSColin Finck }
1291c2c66affSColin Finck
1292c2c66affSColin Finck create_bitmap:
1293c2c66affSColin Finck if(fuLoad & LR_CREATEDIBSECTION)
1294c2c66affSColin Finck {
1295c2c66affSColin Finck /* Allocate the BMI describing the new bitmap */
1296c2c66affSColin Finck pbmiScaled = HeapAlloc(GetProcessHeap(), 0, iBMISize);
1297c2c66affSColin Finck if(!pbmiScaled)
1298c2c66affSColin Finck goto end;
1299c2c66affSColin Finck CopyMemory(pbmiScaled, pbmiCopy, iBMISize);
1300c2c66affSColin Finck
1301c2c66affSColin Finck /* Fix it up */
1302c2c66affSColin Finck if(pbmiScaled->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1303c2c66affSColin Finck {
1304c2c66affSColin Finck BITMAPCOREHEADER* pbmch = (BITMAPCOREHEADER*)&pbmiScaled->bmiHeader;
1305c2c66affSColin Finck pbmch->bcWidth = cxDesired;
1306c2c66affSColin Finck pbmch->bcHeight = cyDesired;
1307c2c66affSColin Finck }
1308c2c66affSColin Finck else
1309c2c66affSColin Finck {
1310c2c66affSColin Finck pbmiScaled->bmiHeader.biWidth = cxDesired;
1311c2c66affSColin Finck pbmiScaled->bmiHeader.biHeight = cyDesired;
1312c2c66affSColin Finck /* No compression for DIB sections */
1313c2c66affSColin Finck pbmiScaled->bmiHeader.biCompression = BI_RGB;
1314c2c66affSColin Finck }
1315c2c66affSColin Finck }
1316c2c66affSColin Finck
1317c2c66affSColin Finck /* Top-down image */
1318c2c66affSColin Finck if(cyDesired < 0) cyDesired = -cyDesired;
1319c2c66affSColin Finck
1320c2c66affSColin Finck /* We need a device context */
1321c2c66affSColin Finck hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
1322c2c66affSColin Finck if(!hdcScreen)
1323c2c66affSColin Finck goto end;
1324c2c66affSColin Finck hdc = CreateCompatibleDC(hdcScreen);
1325c2c66affSColin Finck if(!hdc)
1326c2c66affSColin Finck goto end;
1327c2c66affSColin Finck
1328c2c66affSColin Finck /* Now create the bitmap */
1329c2c66affSColin Finck if(fuLoad & LR_CREATEDIBSECTION)
1330c2c66affSColin Finck hbmpRet = CreateDIBSection(hdc, pbmiScaled, DIB_RGB_COLORS, NULL, 0, 0);
1331c2c66affSColin Finck else
1332c2c66affSColin Finck {
1333c2c66affSColin Finck if(is_dib_monochrome(pbmiCopy) || (fuLoad & LR_MONOCHROME))
1334c2c66affSColin Finck hbmpRet = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL);
1335c2c66affSColin Finck else
1336c2c66affSColin Finck hbmpRet = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired);
1337c2c66affSColin Finck }
1338c2c66affSColin Finck
1339c2c66affSColin Finck if(!hbmpRet)
1340c2c66affSColin Finck goto end;
1341c2c66affSColin Finck
1342c2c66affSColin Finck hbmpOld = SelectObject(hdc, hbmpRet);
1343c2c66affSColin Finck if(!hbmpOld)
1344c2c66affSColin Finck goto end;
1345c2c66affSColin Finck if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
1346c2c66affSColin Finck 0, 0, width, height,
1347c2c66affSColin Finck pvBits, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
1348c2c66affSColin Finck {
1349c2c66affSColin Finck ERR("StretchDIBits failed!.\n");
1350c2c66affSColin Finck SelectObject(hdc, hbmpOld);
1351c2c66affSColin Finck DeleteObject(hbmpRet);
1352c2c66affSColin Finck hbmpRet = NULL;
1353c2c66affSColin Finck goto end;
1354c2c66affSColin Finck }
1355c2c66affSColin Finck
1356c2c66affSColin Finck SelectObject(hdc, hbmpOld);
1357c2c66affSColin Finck
1358c2c66affSColin Finck end:
1359c2c66affSColin Finck if(hdcScreen)
1360c2c66affSColin Finck DeleteDC(hdcScreen);
1361c2c66affSColin Finck if(hdc)
1362c2c66affSColin Finck DeleteDC(hdc);
1363c2c66affSColin Finck if(pbmiScaled)
1364c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pbmiScaled);
1365c2c66affSColin Finck if(pbmiCopy)
1366c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pbmiCopy);
1367c2c66affSColin Finck if (pvMapping)
1368c2c66affSColin Finck UnmapViewOfFile( pvMapping );
1369c2c66affSColin Finck if(hgRsrc)
1370c2c66affSColin Finck FreeResource(hgRsrc);
1371c2c66affSColin Finck
1372c2c66affSColin Finck return hbmpRet;
1373c2c66affSColin Finck }
1374c2c66affSColin Finck
1375c2c66affSColin Finck
1376c2c66affSColin Finck static
1377c2c66affSColin Finck HANDLE
CURSORICON_LoadFromFileW(_In_ LPCWSTR lpszName,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuLoad,_In_ BOOL bIcon)1378c2c66affSColin Finck CURSORICON_LoadFromFileW(
1379c2c66affSColin Finck _In_ LPCWSTR lpszName,
1380c2c66affSColin Finck _In_ int cxDesired,
1381c2c66affSColin Finck _In_ int cyDesired,
1382c2c66affSColin Finck _In_ UINT fuLoad,
1383c2c66affSColin Finck _In_ BOOL bIcon
1384c2c66affSColin Finck )
1385c2c66affSColin Finck {
1386c2c66affSColin Finck const CURSORICONFILEDIRENTRY *entry;
1387c2c66affSColin Finck const CURSORICONFILEDIR *dir;
1388c2c66affSColin Finck DWORD filesize = 0;
1389c2c66affSColin Finck LPBYTE bits;
1390c2c66affSColin Finck HANDLE hCurIcon = NULL;
1391c2c66affSColin Finck CURSORDATA cursorData;
1392c2c66affSColin Finck
1393c2c66affSColin Finck TRACE("loading %s\n", debugstr_w( lpszName ));
1394c2c66affSColin Finck
1395c2c66affSColin Finck bits = map_fileW( lpszName, &filesize );
1396c2c66affSColin Finck if (!bits)
1397c2c66affSColin Finck return NULL;
1398c2c66affSColin Finck
1399c2c66affSColin Finck /* Check for .ani. */
1400c2c66affSColin Finck if (memcmp( bits, "RIFF", 4 ) == 0)
1401c2c66affSColin Finck {
1402c2c66affSColin Finck UNIMPLEMENTED;
1403c2c66affSColin Finck goto end;
1404c2c66affSColin Finck }
1405c2c66affSColin Finck
1406c2c66affSColin Finck dir = (CURSORICONFILEDIR*) bits;
1407c2c66affSColin Finck entry = get_best_icon_file_entry(dir, filesize, cxDesired, cyDesired, bIcon, fuLoad);
1408c2c66affSColin Finck if(!entry)
1409c2c66affSColin Finck goto end;
1410c2c66affSColin Finck
1411c2c66affSColin Finck /* Fix dimensions */
1412c2c66affSColin Finck if(!cxDesired) cxDesired = entry->bWidth;
1413c2c66affSColin Finck if(!cyDesired) cyDesired = entry->bHeight;
1414c2c66affSColin Finck /* A bit of preparation */
1415c2c66affSColin Finck ZeroMemory(&cursorData, sizeof(cursorData));
1416c2c66affSColin Finck if(!bIcon)
1417c2c66affSColin Finck {
1418c2c66affSColin Finck cursorData.xHotspot = entry->xHotspot;
1419c2c66affSColin Finck cursorData.yHotspot = entry->yHotspot;
1420c2c66affSColin Finck }
1421c2c66affSColin Finck cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR));
1422c2c66affSColin Finck
1423c2c66affSColin Finck /* Do the dance */
1424c2c66affSColin Finck if(!CURSORICON_GetCursorDataFromBMI(&cursorData, (BITMAPINFO*)(&bits[entry->dwDIBOffset])))
1425afd39cbcSDoug Lyons {
1426afd39cbcSDoug Lyons ERR("Failing File is \n '%S'.\n", lpszName);
1427c2c66affSColin Finck goto end;
1428afd39cbcSDoug Lyons }
1429c2c66affSColin Finck
1430c2c66affSColin Finck hCurIcon = NtUserxCreateEmptyCurObject(FALSE);
1431c2c66affSColin Finck if(!hCurIcon)
1432c2c66affSColin Finck goto end;
1433c2c66affSColin Finck
1434c2c66affSColin Finck /* Tell win32k */
1435c2c66affSColin Finck if(!NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData))
1436c2c66affSColin Finck {
1437c2c66affSColin Finck NtUserDestroyCursor(hCurIcon, TRUE);
1438c2c66affSColin Finck goto end_error;
1439c2c66affSColin Finck }
1440c2c66affSColin Finck
1441c2c66affSColin Finck end:
1442c2c66affSColin Finck UnmapViewOfFile(bits);
1443c2c66affSColin Finck return hCurIcon;
1444c2c66affSColin Finck
1445c2c66affSColin Finck /* Clean up */
1446c2c66affSColin Finck end_error:
1447c2c66affSColin Finck DeleteObject(cursorData.hbmMask);
1448c2c66affSColin Finck if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
1449c2c66affSColin Finck if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
1450c2c66affSColin Finck UnmapViewOfFile(bits);
1451c2c66affSColin Finck
1452c2c66affSColin Finck return NULL;
1453c2c66affSColin Finck }
1454c2c66affSColin Finck
1455c2c66affSColin Finck static
1456c2c66affSColin Finck HANDLE
CURSORICON_LoadImageW(_In_opt_ HINSTANCE hinst,_In_ LPCWSTR lpszName,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuLoad,_In_ BOOL bIcon)1457c2c66affSColin Finck CURSORICON_LoadImageW(
1458c2c66affSColin Finck _In_opt_ HINSTANCE hinst,
1459c2c66affSColin Finck _In_ LPCWSTR lpszName,
1460c2c66affSColin Finck _In_ int cxDesired,
1461c2c66affSColin Finck _In_ int cyDesired,
1462c2c66affSColin Finck _In_ UINT fuLoad,
1463c2c66affSColin Finck _In_ BOOL bIcon
1464c2c66affSColin Finck )
1465c2c66affSColin Finck {
1466c2c66affSColin Finck HRSRC hrsrc;
1467c2c66affSColin Finck HANDLE handle, hCurIcon = NULL;
1468c2c66affSColin Finck CURSORICONDIR* dir;
1469c2c66affSColin Finck WORD wResId;
1470c2c66affSColin Finck LPBYTE bits;
1471c2c66affSColin Finck CURSORDATA cursorData;
1472c2c66affSColin Finck BOOL bStatus;
1473c2c66affSColin Finck UNICODE_STRING ustrRsrc;
1474c2c66affSColin Finck UNICODE_STRING ustrModule = {0, 0, NULL};
1475c2c66affSColin Finck
1476c2c66affSColin Finck /* Fix width/height */
1477c2c66affSColin Finck if(fuLoad & LR_DEFAULTSIZE)
1478c2c66affSColin Finck {
1479c2c66affSColin Finck if(!cxDesired) cxDesired = GetSystemMetrics(bIcon ? SM_CXICON : SM_CXCURSOR);
1480c2c66affSColin Finck if(!cyDesired) cyDesired = GetSystemMetrics(bIcon ? SM_CYICON : SM_CYCURSOR);
1481c2c66affSColin Finck }
1482c2c66affSColin Finck
1483c2c66affSColin Finck if(fuLoad & LR_LOADFROMFILE)
1484c2c66affSColin Finck {
1485c2c66affSColin Finck return CURSORICON_LoadFromFileW(lpszName, cxDesired, cyDesired, fuLoad, bIcon);
1486c2c66affSColin Finck }
1487c2c66affSColin Finck
1488c2c66affSColin Finck /* Check if caller wants OEM icons */
1489c2c66affSColin Finck if(!hinst)
1490c2c66affSColin Finck hinst = User32Instance;
1491c2c66affSColin Finck
1492c2c66affSColin Finck if(lpszName)
1493c2c66affSColin Finck {
1494c2c66affSColin Finck /* Prepare the resource name string */
1495c2c66affSColin Finck if(IS_INTRESOURCE(lpszName))
1496c2c66affSColin Finck {
1497c2c66affSColin Finck ustrRsrc.Buffer = (LPWSTR)lpszName;
1498c2c66affSColin Finck ustrRsrc.Length = 0;
1499c2c66affSColin Finck ustrRsrc.MaximumLength = 0;
1500c2c66affSColin Finck }
1501c2c66affSColin Finck else
1502c2c66affSColin Finck RtlInitUnicodeString(&ustrRsrc, lpszName);
1503c2c66affSColin Finck }
1504c2c66affSColin Finck
150582c07abfSWhindmar Saksit if(LDR_IS_RESOURCE(hinst))
150682c07abfSWhindmar Saksit {
150782c07abfSWhindmar Saksit /* We don't have a real module for GetModuleFileName, construct a fake name instead.
150882c07abfSWhindmar Saksit * GetIconInfoEx reveals the name used by Windows. */
150982c07abfSWhindmar Saksit LPCWSTR fakeNameFmt = sizeof(void*) > 4 ? L"\x01%016IX" : L"\x01%08IX";
151082c07abfSWhindmar Saksit ustrModule.MaximumLength = 18 * sizeof(WCHAR);
151182c07abfSWhindmar Saksit ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength);
151282c07abfSWhindmar Saksit if (!ustrModule.Buffer)
151382c07abfSWhindmar Saksit {
151482c07abfSWhindmar Saksit SetLastError(ERROR_NOT_ENOUGH_MEMORY);
151582c07abfSWhindmar Saksit return NULL;
151682c07abfSWhindmar Saksit }
151782c07abfSWhindmar Saksit ustrModule.Length = wsprintfW(ustrModule.Buffer, fakeNameFmt, hinst) * sizeof(WCHAR);
151882c07abfSWhindmar Saksit }
151982c07abfSWhindmar Saksit else if(hinst)
1520c2c66affSColin Finck {
1521c2c66affSColin Finck DWORD size = MAX_PATH;
1522c2c66affSColin Finck /* Get the module name string */
1523c2c66affSColin Finck while (TRUE)
1524c2c66affSColin Finck {
1525c2c66affSColin Finck DWORD ret;
1526c2c66affSColin Finck ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
1527c2c66affSColin Finck if (!ustrModule.Buffer)
1528c2c66affSColin Finck {
1529c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1530c2c66affSColin Finck return NULL;
1531c2c66affSColin Finck }
1532c2c66affSColin Finck ret = GetModuleFileNameW(hinst, ustrModule.Buffer, size);
1533c2c66affSColin Finck if(ret == 0)
1534c2c66affSColin Finck {
1535c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1536c2c66affSColin Finck return NULL;
1537c2c66affSColin Finck }
1538c2c66affSColin Finck
1539c2c66affSColin Finck /* This API is completely broken... */
1540c2c66affSColin Finck if (ret == size)
1541c2c66affSColin Finck {
1542c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1543c2c66affSColin Finck size *= 2;
1544c2c66affSColin Finck continue;
1545c2c66affSColin Finck }
1546c2c66affSColin Finck
1547c2c66affSColin Finck ustrModule.Buffer[ret] = UNICODE_NULL;
1548c2c66affSColin Finck ustrModule.Length = ret * sizeof(WCHAR);
1549c2c66affSColin Finck ustrModule.MaximumLength = size * sizeof(WCHAR);
1550c2c66affSColin Finck break;
1551c2c66affSColin Finck }
1552c2c66affSColin Finck }
1553c2c66affSColin Finck
1554c2c66affSColin Finck if(fuLoad & LR_SHARED)
1555c2c66affSColin Finck {
1556c2c66affSColin Finck FINDEXISTINGCURICONPARAM param;
1557c2c66affSColin Finck
1558c2c66affSColin Finck TRACE("Checking for an LR_SHARED cursor/icon.\n");
1559c2c66affSColin Finck /* Ask win32k */
1560c2c66affSColin Finck param.bIcon = bIcon;
1561c2c66affSColin Finck param.cx = cxDesired;
1562c2c66affSColin Finck param.cy = cyDesired;
1563c2c66affSColin Finck hCurIcon = NtUserFindExistingCursorIcon(&ustrModule, &ustrRsrc, ¶m);
1564c2c66affSColin Finck if(hCurIcon)
1565c2c66affSColin Finck {
1566c2c66affSColin Finck /* Woohoo, got it! */
1567c2c66affSColin Finck TRACE("MATCH! %p\n",hCurIcon);
1568c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1569c2c66affSColin Finck return hCurIcon;
1570c2c66affSColin Finck }
1571c2c66affSColin Finck }
1572c2c66affSColin Finck
1573c2c66affSColin Finck /* Find resource ID */
1574c2c66affSColin Finck hrsrc = FindResourceW(
1575c2c66affSColin Finck hinst,
1576c2c66affSColin Finck lpszName,
1577c2c66affSColin Finck bIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR);
1578c2c66affSColin Finck
1579c2c66affSColin Finck /* We let FindResource, LoadResource, etc. call SetLastError */
1580c2c66affSColin Finck if(!hrsrc)
1581c2c66affSColin Finck goto done;
1582c2c66affSColin Finck
1583c2c66affSColin Finck handle = LoadResource(hinst, hrsrc);
1584c2c66affSColin Finck if(!handle)
1585c2c66affSColin Finck goto done;
1586c2c66affSColin Finck
1587c2c66affSColin Finck dir = LockResource(handle);
1588c2c66affSColin Finck if(!dir)
1589c2c66affSColin Finck goto done;
1590c2c66affSColin Finck
1591c2c66affSColin Finck wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad);
1592c2c66affSColin Finck FreeResource(handle);
1593c2c66affSColin Finck
1594c2c66affSColin Finck /* Get the relevant resource pointer */
1595c2c66affSColin Finck hrsrc = FindResourceW(
1596c2c66affSColin Finck hinst,
1597c2c66affSColin Finck MAKEINTRESOURCEW(wResId),
1598c2c66affSColin Finck bIcon ? RT_ICON : RT_CURSOR);
1599c2c66affSColin Finck if(!hrsrc)
1600c2c66affSColin Finck goto done;
1601c2c66affSColin Finck
1602c2c66affSColin Finck handle = LoadResource(hinst, hrsrc);
1603c2c66affSColin Finck if(!handle)
1604c2c66affSColin Finck goto done;
1605c2c66affSColin Finck
1606c2c66affSColin Finck bits = LockResource(handle);
1607c2c66affSColin Finck if(!bits)
1608c2c66affSColin Finck {
1609c2c66affSColin Finck FreeResource(handle);
1610c2c66affSColin Finck goto done;
1611c2c66affSColin Finck }
1612c2c66affSColin Finck
1613c2c66affSColin Finck ZeroMemory(&cursorData, sizeof(cursorData));
1614c2c66affSColin Finck
1615c2c66affSColin Finck /* This is from resource */
1616c2c66affSColin Finck cursorData.CURSORF_flags = CURSORF_FROMRESOURCE;
1617c2c66affSColin Finck
1618c2c66affSColin Finck if(dir->idType == 2)
1619c2c66affSColin Finck {
1620c2c66affSColin Finck /* idType == 2 for cursor resources */
1621c2c66affSColin Finck SHORT* ptr = (SHORT*)bits;
1622c2c66affSColin Finck cursorData.xHotspot = ptr[0];
1623c2c66affSColin Finck cursorData.yHotspot = ptr[1];
1624c2c66affSColin Finck bits += 2*sizeof(SHORT);
1625c2c66affSColin Finck }
1626c2c66affSColin Finck cursorData.cx = cxDesired;
1627c2c66affSColin Finck cursorData.cy = cyDesired;
1628c2c66affSColin Finck cursorData.rt = (USHORT)((ULONG_PTR)(bIcon ? RT_ICON : RT_CURSOR));
1629c2c66affSColin Finck
1630c2c66affSColin Finck /* Get the bitmaps */
1631c2c66affSColin Finck bStatus = CURSORICON_GetCursorDataFromBMI(
1632c2c66affSColin Finck &cursorData,
1633c2c66affSColin Finck (BITMAPINFO*)bits);
1634c2c66affSColin Finck
1635c2c66affSColin Finck FreeResource( handle );
1636c2c66affSColin Finck
1637c2c66affSColin Finck if(!bStatus)
1638c2c66affSColin Finck goto done;
1639c2c66affSColin Finck
1640c2c66affSColin Finck /* Create the handle */
1641c2c66affSColin Finck hCurIcon = NtUserxCreateEmptyCurObject(FALSE);
1642c2c66affSColin Finck if(!hCurIcon)
1643c2c66affSColin Finck {
1644c2c66affSColin Finck goto end_error;
1645c2c66affSColin Finck }
1646c2c66affSColin Finck
1647c2c66affSColin Finck if(fuLoad & LR_SHARED)
1648c2c66affSColin Finck {
1649c2c66affSColin Finck cursorData.CURSORF_flags |= CURSORF_LRSHARED;
1650c2c66affSColin Finck }
1651c2c66affSColin Finck
1652c2c66affSColin Finck /* Tell win32k */
1653c2c66affSColin Finck bStatus = NtUserSetCursorIconData(hCurIcon, hinst ? &ustrModule : NULL, lpszName ? &ustrRsrc : NULL, &cursorData);
1654c2c66affSColin Finck
1655c2c66affSColin Finck if(!bStatus)
1656c2c66affSColin Finck {
1657c2c66affSColin Finck NtUserDestroyCursor(hCurIcon, TRUE);
1658c2c66affSColin Finck goto end_error;
1659c2c66affSColin Finck }
1660c2c66affSColin Finck
1661c2c66affSColin Finck done:
1662c2c66affSColin Finck if(ustrModule.Buffer)
1663c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1664c2c66affSColin Finck return hCurIcon;
1665c2c66affSColin Finck
1666c2c66affSColin Finck end_error:
1667c2c66affSColin Finck if(ustrModule.Buffer)
1668c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1669c2c66affSColin Finck DeleteObject(cursorData.hbmMask);
1670c2c66affSColin Finck if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
1671c2c66affSColin Finck if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
1672c2c66affSColin Finck
1673c2c66affSColin Finck return NULL;
1674c2c66affSColin Finck }
1675c2c66affSColin Finck
1676c2c66affSColin Finck static
1677c2c66affSColin Finck HBITMAP
BITMAP_CopyImage(_In_ HBITMAP hnd,_In_ int desiredx,_In_ int desiredy,_In_ UINT flags)1678c2c66affSColin Finck BITMAP_CopyImage(
1679c2c66affSColin Finck _In_ HBITMAP hnd,
1680c2c66affSColin Finck _In_ int desiredx,
1681c2c66affSColin Finck _In_ int desiredy,
1682c2c66affSColin Finck _In_ UINT flags
1683c2c66affSColin Finck )
1684c2c66affSColin Finck {
1685c2c66affSColin Finck HBITMAP res = NULL;
1686c2c66affSColin Finck DIBSECTION ds;
1687c2c66affSColin Finck int objSize;
1688c2c66affSColin Finck BITMAPINFO * bi;
1689c2c66affSColin Finck
1690c2c66affSColin Finck objSize = GetObjectW( hnd, sizeof(ds), &ds );
1691c2c66affSColin Finck if (!objSize) return 0;
1692c2c66affSColin Finck if ((desiredx < 0) || (desiredy < 0)) return 0;
1693c2c66affSColin Finck
1694c2c66affSColin Finck if (flags & LR_COPYFROMRESOURCE)
1695c2c66affSColin Finck {
1696c2c66affSColin Finck FIXME("The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n");
1697c2c66affSColin Finck }
1698c2c66affSColin Finck
1699c2c66affSColin Finck if (flags & LR_COPYRETURNORG)
1700c2c66affSColin Finck {
1701c2c66affSColin Finck FIXME("The flag LR_COPYRETURNORG is not implemented for bitmaps\n");
1702c2c66affSColin Finck }
1703c2c66affSColin Finck
1704c2c66affSColin Finck if (desiredx == 0) desiredx = ds.dsBm.bmWidth;
1705c2c66affSColin Finck if (desiredy == 0) desiredy = ds.dsBm.bmHeight;
1706c2c66affSColin Finck
1707c2c66affSColin Finck /* Allocate memory for a BITMAPINFOHEADER structure and a
1708c2c66affSColin Finck color table. The maximum number of colors in a color table
1709c2c66affSColin Finck is 256 which corresponds to a bitmap with depth 8.
1710c2c66affSColin Finck Bitmaps with higher depths don't have color tables. */
1711c2c66affSColin Finck bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1712c2c66affSColin Finck if (!bi) return 0;
1713c2c66affSColin Finck
1714c2c66affSColin Finck bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
1715c2c66affSColin Finck bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes;
1716c2c66affSColin Finck bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
1717c2c66affSColin Finck bi->bmiHeader.biCompression = BI_RGB;
1718c2c66affSColin Finck
1719c2c66affSColin Finck if (flags & LR_CREATEDIBSECTION)
1720c2c66affSColin Finck {
1721c2c66affSColin Finck /* Create a DIB section. LR_MONOCHROME is ignored */
1722c2c66affSColin Finck void * bits;
1723c2c66affSColin Finck HDC dc = CreateCompatibleDC(NULL);
1724c2c66affSColin Finck
1725c2c66affSColin Finck if (objSize == sizeof(DIBSECTION))
1726c2c66affSColin Finck {
1727c2c66affSColin Finck /* The source bitmap is a DIB.
1728c2c66affSColin Finck Get its attributes to create an exact copy */
1729c2c66affSColin Finck memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
1730c2c66affSColin Finck }
1731c2c66affSColin Finck
1732c2c66affSColin Finck bi->bmiHeader.biWidth = desiredx;
1733c2c66affSColin Finck bi->bmiHeader.biHeight = desiredy;
1734c2c66affSColin Finck
1735c2c66affSColin Finck /* Get the color table or the color masks */
1736c2c66affSColin Finck GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
1737c2c66affSColin Finck
1738c2c66affSColin Finck res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
1739c2c66affSColin Finck DeleteDC(dc);
1740c2c66affSColin Finck }
1741c2c66affSColin Finck else
1742c2c66affSColin Finck {
1743c2c66affSColin Finck /* Create a device-dependent bitmap */
1744c2c66affSColin Finck
1745c2c66affSColin Finck BOOL monochrome = (flags & LR_MONOCHROME);
1746c2c66affSColin Finck
1747c2c66affSColin Finck if (objSize == sizeof(DIBSECTION))
1748c2c66affSColin Finck {
1749c2c66affSColin Finck /* The source bitmap is a DIB section.
1750c2c66affSColin Finck Get its attributes */
1751c2c66affSColin Finck HDC dc = CreateCompatibleDC(NULL);
1752c2c66affSColin Finck bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
1753c2c66affSColin Finck bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
1754c2c66affSColin Finck GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
1755c2c66affSColin Finck DeleteDC(dc);
1756c2c66affSColin Finck
1757c2c66affSColin Finck if (!monochrome && ds.dsBm.bmBitsPixel == 1)
1758c2c66affSColin Finck {
1759c2c66affSColin Finck /* Look if the colors of the DIB are black and white */
1760c2c66affSColin Finck
1761c2c66affSColin Finck monochrome =
1762c2c66affSColin Finck (bi->bmiColors[0].rgbRed == 0xff
1763c2c66affSColin Finck && bi->bmiColors[0].rgbGreen == 0xff
1764c2c66affSColin Finck && bi->bmiColors[0].rgbBlue == 0xff
1765c2c66affSColin Finck && bi->bmiColors[0].rgbReserved == 0
1766c2c66affSColin Finck && bi->bmiColors[1].rgbRed == 0
1767c2c66affSColin Finck && bi->bmiColors[1].rgbGreen == 0
1768c2c66affSColin Finck && bi->bmiColors[1].rgbBlue == 0
1769c2c66affSColin Finck && bi->bmiColors[1].rgbReserved == 0)
1770c2c66affSColin Finck ||
1771c2c66affSColin Finck (bi->bmiColors[0].rgbRed == 0
1772c2c66affSColin Finck && bi->bmiColors[0].rgbGreen == 0
1773c2c66affSColin Finck && bi->bmiColors[0].rgbBlue == 0
1774c2c66affSColin Finck && bi->bmiColors[0].rgbReserved == 0
1775c2c66affSColin Finck && bi->bmiColors[1].rgbRed == 0xff
1776c2c66affSColin Finck && bi->bmiColors[1].rgbGreen == 0xff
1777c2c66affSColin Finck && bi->bmiColors[1].rgbBlue == 0xff
1778c2c66affSColin Finck && bi->bmiColors[1].rgbReserved == 0);
1779c2c66affSColin Finck }
1780c2c66affSColin Finck }
1781c2c66affSColin Finck else if (!monochrome)
1782c2c66affSColin Finck {
1783c2c66affSColin Finck monochrome = ds.dsBm.bmBitsPixel == 1;
1784c2c66affSColin Finck }
1785c2c66affSColin Finck
1786c2c66affSColin Finck if (monochrome)
1787c2c66affSColin Finck {
1788c2c66affSColin Finck res = CreateBitmap(desiredx, desiredy, 1, 1, NULL);
1789c2c66affSColin Finck }
1790c2c66affSColin Finck else
1791c2c66affSColin Finck {
1792c2c66affSColin Finck HDC screenDC = GetDC(NULL);
1793c2c66affSColin Finck res = CreateCompatibleBitmap(screenDC, desiredx, desiredy);
1794c2c66affSColin Finck ReleaseDC(NULL, screenDC);
1795c2c66affSColin Finck }
1796c2c66affSColin Finck }
1797c2c66affSColin Finck
1798c2c66affSColin Finck if (res)
1799c2c66affSColin Finck {
1800c2c66affSColin Finck /* Only copy the bitmap if it's a DIB section or if it's
1801c2c66affSColin Finck compatible to the screen */
1802c2c66affSColin Finck BOOL copyContents;
1803c2c66affSColin Finck
1804c2c66affSColin Finck if (objSize == sizeof(DIBSECTION))
1805c2c66affSColin Finck {
1806c2c66affSColin Finck copyContents = TRUE;
1807c2c66affSColin Finck }
1808c2c66affSColin Finck else
1809c2c66affSColin Finck {
1810c2c66affSColin Finck HDC screenDC = GetDC(NULL);
1811c2c66affSColin Finck int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
1812c2c66affSColin Finck ReleaseDC(NULL, screenDC);
1813c2c66affSColin Finck
1814c2c66affSColin Finck copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth);
1815c2c66affSColin Finck }
1816c2c66affSColin Finck
1817c2c66affSColin Finck if (copyContents)
1818c2c66affSColin Finck {
1819c2c66affSColin Finck /* The source bitmap may already be selected in a device context,
1820c2c66affSColin Finck use GetDIBits/StretchDIBits and not StretchBlt */
1821c2c66affSColin Finck
1822c2c66affSColin Finck HDC dc;
1823c2c66affSColin Finck void * bits;
1824c2c66affSColin Finck
1825c2c66affSColin Finck dc = CreateCompatibleDC(NULL);
1826c2c66affSColin Finck
1827c2c66affSColin Finck bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
1828c2c66affSColin Finck bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
1829c2c66affSColin Finck bi->bmiHeader.biSizeImage = 0;
1830c2c66affSColin Finck bi->bmiHeader.biClrUsed = 0;
1831c2c66affSColin Finck bi->bmiHeader.biClrImportant = 0;
1832c2c66affSColin Finck
1833c2c66affSColin Finck /* Fill in biSizeImage */
1834c2c66affSColin Finck GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
1835c2c66affSColin Finck bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage);
1836c2c66affSColin Finck
1837c2c66affSColin Finck if (bits)
1838c2c66affSColin Finck {
1839c2c66affSColin Finck HBITMAP oldBmp;
1840c2c66affSColin Finck
1841c2c66affSColin Finck /* Get the image bits of the source bitmap */
1842c2c66affSColin Finck GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
1843c2c66affSColin Finck
1844c2c66affSColin Finck /* Copy it to the destination bitmap */
1845c2c66affSColin Finck oldBmp = SelectObject(dc, res);
1846c2c66affSColin Finck StretchDIBits(dc, 0, 0, desiredx, desiredy,
1847c2c66affSColin Finck 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight,
1848c2c66affSColin Finck bits, bi, DIB_RGB_COLORS, SRCCOPY);
1849c2c66affSColin Finck SelectObject(dc, oldBmp);
1850c2c66affSColin Finck
1851c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, bits);
1852c2c66affSColin Finck }
1853c2c66affSColin Finck
1854c2c66affSColin Finck DeleteDC(dc);
1855c2c66affSColin Finck }
1856c2c66affSColin Finck
1857c2c66affSColin Finck if (flags & LR_COPYDELETEORG)
1858c2c66affSColin Finck {
1859c2c66affSColin Finck DeleteObject(hnd);
1860c2c66affSColin Finck }
1861c2c66affSColin Finck }
1862c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, bi);
1863c2c66affSColin Finck return res;
1864c2c66affSColin Finck }
1865c2c66affSColin Finck
1866c2c66affSColin Finck static
1867c2c66affSColin Finck HICON
CURSORICON_CopyImage(_In_ HICON hicon,_In_ BOOL bIcon,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuFlags)1868c2c66affSColin Finck CURSORICON_CopyImage(
1869c2c66affSColin Finck _In_ HICON hicon,
1870c2c66affSColin Finck _In_ BOOL bIcon,
1871c2c66affSColin Finck _In_ int cxDesired,
1872c2c66affSColin Finck _In_ int cyDesired,
1873c2c66affSColin Finck _In_ UINT fuFlags
1874c2c66affSColin Finck )
1875c2c66affSColin Finck {
1876c2c66affSColin Finck HICON ret = NULL;
1877c2c66affSColin Finck ICONINFO ii;
1878c2c66affSColin Finck CURSORDATA CursorData;
1879c2c66affSColin Finck
1880c2c66affSColin Finck if (fuFlags & LR_COPYFROMRESOURCE)
1881c2c66affSColin Finck {
1882c2c66affSColin Finck /* Get the icon module/resource names */
1883c2c66affSColin Finck UNICODE_STRING ustrModule;
1884c2c66affSColin Finck UNICODE_STRING ustrRsrc;
1885c2c66affSColin Finck HMODULE hModule;
1886c2c66affSColin Finck
1887c2c66affSColin Finck ustrModule.MaximumLength = 0;
1888c2c66affSColin Finck ustrRsrc.MaximumLength = 0;
1889c2c66affSColin Finck
1890c2c66affSColin Finck /* Get the buffer size */
1891c2c66affSColin Finck if (!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE))
1892c2c66affSColin Finck {
1893c2c66affSColin Finck return NULL;
1894c2c66affSColin Finck }
1895c2c66affSColin Finck
1896c2c66affSColin Finck ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength);
1897c2c66affSColin Finck if (!ustrModule.Buffer)
1898c2c66affSColin Finck {
1899c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1900c2c66affSColin Finck return NULL;
1901c2c66affSColin Finck }
1902c2c66affSColin Finck
1903c2c66affSColin Finck if (ustrRsrc.MaximumLength)
1904c2c66affSColin Finck {
1905c2c66affSColin Finck ustrRsrc.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrRsrc.MaximumLength);
1906c2c66affSColin Finck if (!ustrRsrc.Buffer)
1907c2c66affSColin Finck {
1908c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1909c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1910c2c66affSColin Finck return NULL;
1911c2c66affSColin Finck }
1912c2c66affSColin Finck }
1913c2c66affSColin Finck
1914c2c66affSColin Finck if (!NtUserGetIconInfo(hicon, NULL, &ustrModule, &ustrRsrc, NULL, FALSE))
1915c2c66affSColin Finck {
1916c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1917c2c66affSColin Finck if (!IS_INTRESOURCE(ustrRsrc.Buffer))
1918c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrRsrc.Buffer);
1919c2c66affSColin Finck return NULL;
1920c2c66affSColin Finck }
1921c2c66affSColin Finck
1922c2c66affSColin Finck /* NULL-terminate our strings */
1923c2c66affSColin Finck ustrModule.Buffer[ustrModule.Length/sizeof(WCHAR)] = UNICODE_NULL;
1924c2c66affSColin Finck if (!IS_INTRESOURCE(ustrRsrc.Buffer))
1925c2c66affSColin Finck ustrRsrc.Buffer[ustrRsrc.Length/sizeof(WCHAR)] = UNICODE_NULL;
1926c2c66affSColin Finck
1927c2c66affSColin Finck TRACE("Got module %wZ, resource %p (%S).\n", &ustrModule,
1928c2c66affSColin Finck ustrRsrc.Buffer, IS_INTRESOURCE(ustrRsrc.Buffer) ? L"" : ustrRsrc.Buffer);
1929c2c66affSColin Finck
1930c2c66affSColin Finck /* Get the module handle or load the module */
1931a0483167SSerge Gautherie hModule = LoadLibraryExW(ustrModule.Buffer, NULL, /* NT6+: LOAD_LIBRARY_AS_IMAGE_RESOURCE | */ LOAD_LIBRARY_AS_DATAFILE);
1932c2c66affSColin Finck if (!hModule)
1933c2c66affSColin Finck {
1934c2c66affSColin Finck DWORD err = GetLastError();
1935c2c66affSColin Finck ERR("Unable to load/use module '%wZ' in process %lu, error %lu.\n", &ustrModule, GetCurrentProcessId(), err);
1936c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
1937c2c66affSColin Finck goto leave;
1938c2c66affSColin Finck }
1939c2c66affSColin Finck
1940c2c66affSColin Finck /* Call the relevant function */
1941c2c66affSColin Finck ret = CURSORICON_LoadImageW(
1942c2c66affSColin Finck hModule,
1943c2c66affSColin Finck ustrRsrc.Buffer,
1944c2c66affSColin Finck cxDesired,
1945c2c66affSColin Finck cyDesired,
1946c2c66affSColin Finck fuFlags & (LR_DEFAULTSIZE | LR_SHARED),
1947c2c66affSColin Finck bIcon);
1948c2c66affSColin Finck
1949c2c66affSColin Finck FreeLibrary(hModule);
1950c2c66affSColin Finck
1951c2c66affSColin Finck /* If we're here, that means that the passed icon is shared. Don't destroy it, even if LR_COPYDELETEORG is specified */
1952c2c66affSColin Finck leave:
1953c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
1954c2c66affSColin Finck if (!IS_INTRESOURCE(ustrRsrc.Buffer))
1955c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ustrRsrc.Buffer);
1956c2c66affSColin Finck
1957c2c66affSColin Finck TRACE("Returning 0x%08x.\n", ret);
1958c2c66affSColin Finck
1959c2c66affSColin Finck return ret;
1960c2c66affSColin Finck }
1961c2c66affSColin Finck
1962c2c66affSColin Finck /* This is a regular copy */
1963c2c66affSColin Finck if (fuFlags & ~(LR_COPYDELETEORG | LR_SHARED))
1964c2c66affSColin Finck FIXME("Unimplemented flags: 0x%08x\n", fuFlags);
1965c2c66affSColin Finck
1966c2c66affSColin Finck if (!GetIconInfo(hicon, &ii))
1967c2c66affSColin Finck {
1968c2c66affSColin Finck ERR("GetIconInfo failed.\n");
1969c2c66affSColin Finck return NULL;
1970c2c66affSColin Finck }
1971c2c66affSColin Finck
1972c2c66affSColin Finck /* This is CreateIconIndirect with the LR_SHARED coat added */
1973c2c66affSColin Finck if (!CURSORICON_GetCursorDataFromIconInfo(&CursorData, &ii))
1974c2c66affSColin Finck goto Leave;
1975c2c66affSColin Finck
1976c2c66affSColin Finck if (fuFlags & LR_SHARED)
1977c2c66affSColin Finck CursorData.CURSORF_flags |= CURSORF_LRSHARED;
1978c2c66affSColin Finck
1979c2c66affSColin Finck ret = NtUserxCreateEmptyCurObject(FALSE);
1980c2c66affSColin Finck if (!ret)
1981c2c66affSColin Finck goto Leave;
1982c2c66affSColin Finck
1983c2c66affSColin Finck if (!NtUserSetCursorIconData(ret, NULL, NULL, &CursorData))
1984c2c66affSColin Finck {
1985c2c66affSColin Finck NtUserDestroyCursor(ret, TRUE);
1986c2c66affSColin Finck goto Leave;
1987c2c66affSColin Finck }
1988c2c66affSColin Finck
1989c2c66affSColin Finck Leave:
1990c2c66affSColin Finck DeleteObject(ii.hbmMask);
1991c2c66affSColin Finck if (ii.hbmColor) DeleteObject(ii.hbmColor);
1992c2c66affSColin Finck
1993c2c66affSColin Finck if (ret && (fuFlags & LR_COPYDELETEORG))
1994c2c66affSColin Finck DestroyIcon(hicon);
1995c2c66affSColin Finck
1996c2c66affSColin Finck return ret;
1997c2c66affSColin Finck }
1998c2c66affSColin Finck
1999c2c66affSColin Finck NTSTATUS WINAPI
User32CallCopyImageFromKernel(PVOID Arguments,ULONG ArgumentLength)2000c2c66affSColin Finck User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength)
2001c2c66affSColin Finck {
2002c2c66affSColin Finck PCOPYIMAGE_CALLBACK_ARGUMENTS Common;
2003c2c66affSColin Finck HANDLE Result;
2004c2c66affSColin Finck Common = (PCOPYIMAGE_CALLBACK_ARGUMENTS) Arguments;
2005c2c66affSColin Finck
2006c2c66affSColin Finck Result = CopyImage(Common->hImage,
2007c2c66affSColin Finck Common->uType,
2008c2c66affSColin Finck Common->cxDesired,
2009c2c66affSColin Finck Common->cyDesired,
2010c2c66affSColin Finck Common->fuFlags);
2011c2c66affSColin Finck
2012c2c66affSColin Finck return ZwCallbackReturn(&Result, sizeof(HANDLE), STATUS_SUCCESS);
2013c2c66affSColin Finck }
2014c2c66affSColin Finck
2015c2c66affSColin Finck
2016c2c66affSColin Finck /************* PUBLIC FUNCTIONS *******************/
2017c2c66affSColin Finck
2018efe42074SKatayama Hirofumi MZ #define COPYIMAGE_VALID_FLAGS ( \
2019efe42074SKatayama Hirofumi MZ LR_SHARED | LR_COPYFROMRESOURCE | LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS | 0x800 | \
2020efe42074SKatayama Hirofumi MZ LR_VGACOLOR | LR_LOADREALSIZE | LR_DEFAULTSIZE | LR_LOADTRANSPARENT | LR_LOADFROMFILE | \
2021efe42074SKatayama Hirofumi MZ LR_COPYDELETEORG | LR_COPYRETURNORG | LR_COLOR | LR_MONOCHROME \
2022efe42074SKatayama Hirofumi MZ )
2023efe42074SKatayama Hirofumi MZ
CopyImage(_In_ HANDLE hImage,_In_ UINT uType,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuFlags)2024c2c66affSColin Finck HANDLE WINAPI CopyImage(
2025c2c66affSColin Finck _In_ HANDLE hImage,
2026c2c66affSColin Finck _In_ UINT uType,
2027c2c66affSColin Finck _In_ int cxDesired,
2028c2c66affSColin Finck _In_ int cyDesired,
2029c2c66affSColin Finck _In_ UINT fuFlags
2030c2c66affSColin Finck )
2031c2c66affSColin Finck {
2032c2c66affSColin Finck TRACE("hImage=%p, uType=%u, cxDesired=%d, cyDesired=%d, fuFlags=%x\n",
2033c2c66affSColin Finck hImage, uType, cxDesired, cyDesired, fuFlags);
2034efe42074SKatayama Hirofumi MZ
2035efe42074SKatayama Hirofumi MZ if (fuFlags & ~COPYIMAGE_VALID_FLAGS)
2036efe42074SKatayama Hirofumi MZ {
2037efe42074SKatayama Hirofumi MZ SetLastError(ERROR_INVALID_PARAMETER);
2038efe42074SKatayama Hirofumi MZ return NULL;
2039efe42074SKatayama Hirofumi MZ }
2040efe42074SKatayama Hirofumi MZ
2041c2c66affSColin Finck switch(uType)
2042c2c66affSColin Finck {
2043c2c66affSColin Finck case IMAGE_BITMAP:
2044c2c66affSColin Finck return BITMAP_CopyImage(hImage, cxDesired, cyDesired, fuFlags);
2045c2c66affSColin Finck case IMAGE_CURSOR:
2046c2c66affSColin Finck case IMAGE_ICON:
2047*d3ec7cddSJulen Urizar Compains /* HACK: Copying bitmaps with LR_COPYFROMRESOURCE flag fails. CORE-17902.
2048*d3ec7cddSJulen Urizar Compains * This is a way to return the original bit map if we need
2049*d3ec7cddSJulen Urizar Compains * the icons to show up. We need a simpler test. */
2050*d3ec7cddSJulen Urizar Compains {
2051*d3ec7cddSJulen Urizar Compains HANDLE handle = CURSORICON_CopyImage(hImage, uType == IMAGE_ICON, cxDesired, cyDesired, fuFlags);
2052*d3ec7cddSJulen Urizar Compains if (!handle && (fuFlags & (LR_COPYFROMRESOURCE|LR_COPYRETURNORG)))
2053*d3ec7cddSJulen Urizar Compains handle = CURSORICON_CopyImage(hImage, uType == IMAGE_ICON, cxDesired, cyDesired, (fuFlags & ~LR_COPYFROMRESOURCE));
2054*d3ec7cddSJulen Urizar Compains return handle;
2055*d3ec7cddSJulen Urizar Compains }
2056c2c66affSColin Finck default:
2057c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2058c2c66affSColin Finck break;
2059c2c66affSColin Finck }
2060c2c66affSColin Finck return NULL;
2061c2c66affSColin Finck }
2062c2c66affSColin Finck
CopyIcon(_In_ HICON hIcon)2063c2c66affSColin Finck HICON WINAPI CopyIcon(
2064c2c66affSColin Finck _In_ HICON hIcon
2065c2c66affSColin Finck )
2066c2c66affSColin Finck {
2067c2c66affSColin Finck return CURSORICON_CopyImage(hIcon, FALSE, 0, 0, 0);
2068c2c66affSColin Finck }
2069c2c66affSColin Finck
DrawIcon(_In_ HDC hDC,_In_ int X,_In_ int Y,_In_ HICON hIcon)2070c2c66affSColin Finck BOOL WINAPI DrawIcon(
2071c2c66affSColin Finck _In_ HDC hDC,
2072c2c66affSColin Finck _In_ int X,
2073c2c66affSColin Finck _In_ int Y,
2074c2c66affSColin Finck _In_ HICON hIcon
2075c2c66affSColin Finck )
2076c2c66affSColin Finck {
2077c2c66affSColin Finck return DrawIconEx(hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
2078c2c66affSColin Finck }
2079c2c66affSColin Finck
DrawIconEx(_In_ HDC hdc,_In_ int xLeft,_In_ int yTop,_In_ HICON hIcon,_In_ int cxWidth,_In_ int cyWidth,_In_ UINT istepIfAniCur,_In_opt_ HBRUSH hbrFlickerFreeDraw,_In_ UINT diFlags)2080c2c66affSColin Finck BOOL WINAPI DrawIconEx(
2081c2c66affSColin Finck _In_ HDC hdc,
2082c2c66affSColin Finck _In_ int xLeft,
2083c2c66affSColin Finck _In_ int yTop,
2084c2c66affSColin Finck _In_ HICON hIcon,
2085c2c66affSColin Finck _In_ int cxWidth,
2086c2c66affSColin Finck _In_ int cyWidth,
2087c2c66affSColin Finck _In_ UINT istepIfAniCur,
2088c2c66affSColin Finck _In_opt_ HBRUSH hbrFlickerFreeDraw,
2089c2c66affSColin Finck _In_ UINT diFlags
2090c2c66affSColin Finck )
2091c2c66affSColin Finck {
2092c2c66affSColin Finck return NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
2093c2c66affSColin Finck istepIfAniCur, hbrFlickerFreeDraw, diFlags,
2094c2c66affSColin Finck 0, 0);
2095c2c66affSColin Finck }
2096c2c66affSColin Finck
GetIconInfo(_In_ HICON hIcon,_Out_ PICONINFO piconinfo)2097c2c66affSColin Finck BOOL WINAPI GetIconInfo(
2098c2c66affSColin Finck _In_ HICON hIcon,
2099c2c66affSColin Finck _Out_ PICONINFO piconinfo
2100c2c66affSColin Finck )
2101c2c66affSColin Finck {
2102c2c66affSColin Finck return NtUserGetIconInfo(hIcon, piconinfo, NULL, NULL, NULL, FALSE);
2103c2c66affSColin Finck }
2104c2c66affSColin Finck
DestroyIcon(_In_ HICON hIcon)2105c2c66affSColin Finck BOOL WINAPI DestroyIcon(
2106c2c66affSColin Finck _In_ HICON hIcon
2107c2c66affSColin Finck )
2108c2c66affSColin Finck {
2109c2c66affSColin Finck return NtUserDestroyCursor(hIcon, FALSE);
2110c2c66affSColin Finck }
2111c2c66affSColin Finck
LoadIconA(_In_opt_ HINSTANCE hInstance,_In_ LPCSTR lpIconName)2112c2c66affSColin Finck HICON WINAPI LoadIconA(
2113c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2114c2c66affSColin Finck _In_ LPCSTR lpIconName
2115c2c66affSColin Finck )
2116c2c66affSColin Finck {
2117c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_a(lpIconName));
2118c2c66affSColin Finck
2119c2c66affSColin Finck return LoadImageA(hInstance,
2120c2c66affSColin Finck lpIconName,
2121c2c66affSColin Finck IMAGE_ICON,
2122c2c66affSColin Finck 0,
2123c2c66affSColin Finck 0,
2124c2c66affSColin Finck LR_SHARED | LR_DEFAULTSIZE );
2125c2c66affSColin Finck }
2126c2c66affSColin Finck
LoadIconW(_In_opt_ HINSTANCE hInstance,_In_ LPCWSTR lpIconName)2127c2c66affSColin Finck HICON WINAPI LoadIconW(
2128c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2129c2c66affSColin Finck _In_ LPCWSTR lpIconName
2130c2c66affSColin Finck )
2131c2c66affSColin Finck {
2132c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_w(lpIconName));
2133c2c66affSColin Finck
2134c2c66affSColin Finck return LoadImageW(hInstance,
2135c2c66affSColin Finck lpIconName,
2136c2c66affSColin Finck IMAGE_ICON,
2137c2c66affSColin Finck 0,
2138c2c66affSColin Finck 0,
2139c2c66affSColin Finck LR_SHARED | LR_DEFAULTSIZE );
2140c2c66affSColin Finck }
2141c2c66affSColin Finck
LoadCursorA(_In_opt_ HINSTANCE hInstance,_In_ LPCSTR lpCursorName)2142c2c66affSColin Finck HCURSOR WINAPI LoadCursorA(
2143c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2144c2c66affSColin Finck _In_ LPCSTR lpCursorName
2145c2c66affSColin Finck )
2146c2c66affSColin Finck {
2147c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_a(lpCursorName));
2148c2c66affSColin Finck
2149c2c66affSColin Finck return LoadImageA(hInstance,
2150c2c66affSColin Finck lpCursorName,
2151c2c66affSColin Finck IMAGE_CURSOR,
2152c2c66affSColin Finck 0,
2153c2c66affSColin Finck 0,
2154c2c66affSColin Finck LR_SHARED | LR_DEFAULTSIZE );
2155c2c66affSColin Finck }
2156c2c66affSColin Finck
LoadCursorW(_In_opt_ HINSTANCE hInstance,_In_ LPCWSTR lpCursorName)2157c2c66affSColin Finck HCURSOR WINAPI LoadCursorW(
2158c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2159c2c66affSColin Finck _In_ LPCWSTR lpCursorName
2160c2c66affSColin Finck )
2161c2c66affSColin Finck {
2162c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_w(lpCursorName));
2163c2c66affSColin Finck
2164c2c66affSColin Finck return LoadImageW(hInstance,
2165c2c66affSColin Finck lpCursorName,
2166c2c66affSColin Finck IMAGE_CURSOR,
2167c2c66affSColin Finck 0,
2168c2c66affSColin Finck 0,
2169c2c66affSColin Finck LR_SHARED | LR_DEFAULTSIZE );
2170c2c66affSColin Finck }
2171c2c66affSColin Finck
LoadCursorFromFileA(_In_ LPCSTR lpFileName)2172c2c66affSColin Finck HCURSOR WINAPI LoadCursorFromFileA(
2173c2c66affSColin Finck _In_ LPCSTR lpFileName
2174c2c66affSColin Finck )
2175c2c66affSColin Finck {
2176c2c66affSColin Finck TRACE("%s\n", debugstr_a(lpFileName));
2177c2c66affSColin Finck
2178c2c66affSColin Finck return LoadImageA(NULL,
2179c2c66affSColin Finck lpFileName,
2180c2c66affSColin Finck IMAGE_CURSOR,
2181c2c66affSColin Finck 0,
2182c2c66affSColin Finck 0,
2183c2c66affSColin Finck LR_LOADFROMFILE | LR_DEFAULTSIZE );
2184c2c66affSColin Finck }
2185c2c66affSColin Finck
LoadCursorFromFileW(_In_ LPCWSTR lpFileName)2186c2c66affSColin Finck HCURSOR WINAPI LoadCursorFromFileW(
2187c2c66affSColin Finck _In_ LPCWSTR lpFileName
2188c2c66affSColin Finck )
2189c2c66affSColin Finck {
2190c2c66affSColin Finck TRACE("%s\n", debugstr_w(lpFileName));
2191c2c66affSColin Finck
2192c2c66affSColin Finck return LoadImageW(NULL,
2193c2c66affSColin Finck lpFileName,
2194c2c66affSColin Finck IMAGE_CURSOR,
2195c2c66affSColin Finck 0,
2196c2c66affSColin Finck 0,
2197c2c66affSColin Finck LR_LOADFROMFILE | LR_DEFAULTSIZE );
2198c2c66affSColin Finck }
2199c2c66affSColin Finck
LoadBitmapA(_In_opt_ HINSTANCE hInstance,_In_ LPCSTR lpBitmapName)2200c2c66affSColin Finck HBITMAP WINAPI LoadBitmapA(
2201c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2202c2c66affSColin Finck _In_ LPCSTR lpBitmapName
2203c2c66affSColin Finck )
2204c2c66affSColin Finck {
2205c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_a(lpBitmapName));
2206c2c66affSColin Finck
2207c2c66affSColin Finck return LoadImageA(hInstance,
2208c2c66affSColin Finck lpBitmapName,
2209c2c66affSColin Finck IMAGE_BITMAP,
2210c2c66affSColin Finck 0,
2211c2c66affSColin Finck 0,
2212c2c66affSColin Finck 0);
2213c2c66affSColin Finck }
2214c2c66affSColin Finck
LoadBitmapW(_In_opt_ HINSTANCE hInstance,_In_ LPCWSTR lpBitmapName)2215c2c66affSColin Finck HBITMAP WINAPI LoadBitmapW(
2216c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2217c2c66affSColin Finck _In_ LPCWSTR lpBitmapName
2218c2c66affSColin Finck )
2219c2c66affSColin Finck {
2220c2c66affSColin Finck TRACE("%p, %s\n", hInstance, debugstr_w(lpBitmapName));
2221c2c66affSColin Finck
2222c2c66affSColin Finck return LoadImageW(hInstance,
2223c2c66affSColin Finck lpBitmapName,
2224c2c66affSColin Finck IMAGE_BITMAP,
2225c2c66affSColin Finck 0,
2226c2c66affSColin Finck 0,
2227c2c66affSColin Finck 0);
2228c2c66affSColin Finck }
2229c2c66affSColin Finck
LoadImageA(_In_opt_ HINSTANCE hinst,_In_ LPCSTR lpszName,_In_ UINT uType,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuLoad)2230c2c66affSColin Finck HANDLE WINAPI LoadImageA(
2231c2c66affSColin Finck _In_opt_ HINSTANCE hinst,
2232c2c66affSColin Finck _In_ LPCSTR lpszName,
2233c2c66affSColin Finck _In_ UINT uType,
2234c2c66affSColin Finck _In_ int cxDesired,
2235c2c66affSColin Finck _In_ int cyDesired,
2236c2c66affSColin Finck _In_ UINT fuLoad
2237c2c66affSColin Finck )
2238c2c66affSColin Finck {
2239c2c66affSColin Finck HANDLE res;
2240c2c66affSColin Finck LPWSTR u_name;
2241c2c66affSColin Finck DWORD len;
2242c2c66affSColin Finck
2243c2c66affSColin Finck if (IS_INTRESOURCE(lpszName))
2244c2c66affSColin Finck return LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired, cyDesired, fuLoad);
2245c2c66affSColin Finck
2246c2c66affSColin Finck len = MultiByteToWideChar( CP_ACP, 0, lpszName, -1, NULL, 0 );
2247c2c66affSColin Finck u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2248c2c66affSColin Finck MultiByteToWideChar( CP_ACP, 0, lpszName, -1, u_name, len );
2249c2c66affSColin Finck
2250c2c66affSColin Finck res = LoadImageW(hinst, u_name, uType, cxDesired, cyDesired, fuLoad);
2251c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, u_name);
2252c2c66affSColin Finck return res;
2253c2c66affSColin Finck }
2254c2c66affSColin Finck
LoadImageW(_In_opt_ HINSTANCE hinst,_In_ LPCWSTR lpszName,_In_ UINT uType,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT fuLoad)2255c2c66affSColin Finck HANDLE WINAPI LoadImageW(
2256c2c66affSColin Finck _In_opt_ HINSTANCE hinst,
2257c2c66affSColin Finck _In_ LPCWSTR lpszName,
2258c2c66affSColin Finck _In_ UINT uType,
2259c2c66affSColin Finck _In_ int cxDesired,
2260c2c66affSColin Finck _In_ int cyDesired,
2261c2c66affSColin Finck _In_ UINT fuLoad
2262c2c66affSColin Finck )
2263c2c66affSColin Finck {
2264c2c66affSColin Finck TRACE("hinst 0x%p, name %s, uType 0x%08x, cxDesired %d, cyDesired %d, fuLoad 0x%08x.\n",
2265c2c66affSColin Finck hinst, debugstr_w(lpszName), uType, cxDesired, cyDesired, fuLoad);
2266c2c66affSColin Finck /* Redirect to each implementation */
2267c2c66affSColin Finck switch(uType)
2268c2c66affSColin Finck {
2269c2c66affSColin Finck case IMAGE_BITMAP:
2270c2c66affSColin Finck return BITMAP_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad);
2271c2c66affSColin Finck case IMAGE_CURSOR:
2272c2c66affSColin Finck case IMAGE_ICON:
2273c2c66affSColin Finck return CURSORICON_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad, uType == IMAGE_ICON);
2274c2c66affSColin Finck default:
2275c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2276c2c66affSColin Finck break;
2277c2c66affSColin Finck }
2278c2c66affSColin Finck return NULL;
2279c2c66affSColin Finck }
2280c2c66affSColin Finck
LookupIconIdFromDirectory(_In_ PBYTE presbits,_In_ BOOL fIcon)2281c2c66affSColin Finck int WINAPI LookupIconIdFromDirectory(
2282c2c66affSColin Finck _In_ PBYTE presbits,
2283c2c66affSColin Finck _In_ BOOL fIcon
2284c2c66affSColin Finck )
2285c2c66affSColin Finck {
2286c2c66affSColin Finck return LookupIconIdFromDirectoryEx( presbits, fIcon,
2287c2c66affSColin Finck fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
2288c2c66affSColin Finck fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), fIcon ? 0 : LR_MONOCHROME );
2289c2c66affSColin Finck }
2290c2c66affSColin Finck
LookupIconIdFromDirectoryEx(_In_ PBYTE presbits,_In_ BOOL fIcon,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT Flags)2291c2c66affSColin Finck int WINAPI LookupIconIdFromDirectoryEx(
2292c2c66affSColin Finck _In_ PBYTE presbits,
2293c2c66affSColin Finck _In_ BOOL fIcon,
2294c2c66affSColin Finck _In_ int cxDesired,
2295c2c66affSColin Finck _In_ int cyDesired,
2296c2c66affSColin Finck _In_ UINT Flags
2297c2c66affSColin Finck )
2298c2c66affSColin Finck {
2299c2c66affSColin Finck WORD bppDesired;
2300c2c66affSColin Finck CURSORICONDIR* dir = (CURSORICONDIR*)presbits;
2301c2c66affSColin Finck CURSORICONDIRENTRY* entry;
2302c2c66affSColin Finck int i, numMatch = 0, iIndex = -1;
2303c2c66affSColin Finck WORD width, height, BitCount = 0;
2304c2c66affSColin Finck BOOL notPaletted = FALSE;
2305c2c66affSColin Finck ULONG bestScore = 0xFFFFFFFF, score;
2306c2c66affSColin Finck
2307c2c66affSColin Finck TRACE("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired, Flags);
2308c2c66affSColin Finck
2309c2c66affSColin Finck if(!(dir && !dir->idReserved && (dir->idType & 3)))
2310c2c66affSColin Finck {
2311c2c66affSColin Finck WARN("Invalid resource.\n");
2312c2c66affSColin Finck return 0;
2313c2c66affSColin Finck }
2314c2c66affSColin Finck
2315c2c66affSColin Finck if(Flags & LR_MONOCHROME)
2316c2c66affSColin Finck bppDesired = 1;
2317c2c66affSColin Finck else
2318c2c66affSColin Finck {
2319c2c66affSColin Finck HDC icScreen;
2320c2c66affSColin Finck icScreen = CreateICW(DISPLAYW, NULL, NULL, NULL);
2321c2c66affSColin Finck if(!icScreen)
2322c2c66affSColin Finck return FALSE;
2323c2c66affSColin Finck
2324c2c66affSColin Finck bppDesired = GetDeviceCaps(icScreen, BITSPIXEL);
2325c2c66affSColin Finck DeleteDC(icScreen);
2326c2c66affSColin Finck }
2327c2c66affSColin Finck
2328c2c66affSColin Finck if(!cxDesired)
2329c2c66affSColin Finck cxDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR) : 256;
2330c2c66affSColin Finck if(!cyDesired)
2331c2c66affSColin Finck cyDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR) : 256;
2332c2c66affSColin Finck
2333c2c66affSColin Finck /* Find the best match for the desired size */
2334c2c66affSColin Finck for(i = 0; i < dir->idCount; i++)
2335c2c66affSColin Finck {
2336c2c66affSColin Finck entry = &dir->idEntries[i];
2337c2c66affSColin Finck width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
2338c2c66affSColin Finck /* Height is twice as big in cursor resources */
2339c2c66affSColin Finck height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2;
2340c2c66affSColin Finck /* 0 represents 256 */
2341c2c66affSColin Finck if(!width) width = 256;
2342c2c66affSColin Finck if(!height) height = 256;
2343c2c66affSColin Finck /* Calculate the "score" (lower is better) */
2344c2c66affSColin Finck score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
2345c2c66affSColin Finck if( score > bestScore)
2346c2c66affSColin Finck continue;
2347c2c66affSColin Finck /* Bigger than requested lowers the score */
2348c2c66affSColin Finck if(width > cxDesired)
2349c2c66affSColin Finck score -= width - cxDesired;
2350c2c66affSColin Finck if(height > cyDesired)
2351c2c66affSColin Finck score -= height - cyDesired;
2352c2c66affSColin Finck if(score > bestScore)
2353c2c66affSColin Finck continue;
2354c2c66affSColin Finck if(score == bestScore)
2355c2c66affSColin Finck {
2356c2c66affSColin Finck if(entry->wBitCount > BitCount)
2357c2c66affSColin Finck BitCount = entry->wBitCount;
2358c2c66affSColin Finck numMatch++;
2359c2c66affSColin Finck continue;
2360c2c66affSColin Finck }
2361c2c66affSColin Finck iIndex = i;
2362c2c66affSColin Finck numMatch = 1;
2363c2c66affSColin Finck bestScore = score;
2364c2c66affSColin Finck BitCount = entry->wBitCount;
2365c2c66affSColin Finck }
2366c2c66affSColin Finck
2367c2c66affSColin Finck if(numMatch == 1)
2368c2c66affSColin Finck {
2369c2c66affSColin Finck /* Only one entry fits the asked dimensions */
2370c2c66affSColin Finck return dir->idEntries[iIndex].wResId;
2371c2c66affSColin Finck }
2372c2c66affSColin Finck
2373c2c66affSColin Finck /* Avoid paletted icons on non-paletted device */
2374c2c66affSColin Finck if (bppDesired > 8 && BitCount > 8)
2375c2c66affSColin Finck notPaletted = TRUE;
2376c2c66affSColin Finck
2377c2c66affSColin Finck BitCount = 0;
2378c2c66affSColin Finck iIndex = -1;
2379c2c66affSColin Finck /* Now find the entry with the best depth */
2380c2c66affSColin Finck for(i = 0; i < dir->idCount; i++)
2381c2c66affSColin Finck {
2382c2c66affSColin Finck entry = &dir->idEntries[i];
2383c2c66affSColin Finck width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
2384c2c66affSColin Finck height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2;
2385c2c66affSColin Finck /* 0 represents 256 */
2386c2c66affSColin Finck if(!width) width = 256;
2387c2c66affSColin Finck if(!height) height = 256;
2388c2c66affSColin Finck /* Check if this is the best match we had */
2389c2c66affSColin Finck score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
2390c2c66affSColin Finck if(width > cxDesired)
2391c2c66affSColin Finck score -= width - cxDesired;
2392c2c66affSColin Finck if(height > cyDesired)
2393c2c66affSColin Finck score -= height - cyDesired;
2394c2c66affSColin Finck if(score != bestScore)
2395c2c66affSColin Finck continue;
2396c2c66affSColin Finck /* Exact match? */
2397c2c66affSColin Finck if(entry->wBitCount == bppDesired)
2398c2c66affSColin Finck return entry->wResId;
2399c2c66affSColin Finck /* We take the highest possible but smaller than the display depth */
2400c2c66affSColin Finck if((entry->wBitCount > BitCount) && (entry->wBitCount < bppDesired))
2401c2c66affSColin Finck {
2402c2c66affSColin Finck /* Avoid paletted icons on non paletted devices */
2403c2c66affSColin Finck if ((entry->wBitCount <= 8) && notPaletted)
2404c2c66affSColin Finck continue;
2405c2c66affSColin Finck iIndex = i;
2406c2c66affSColin Finck BitCount = entry->wBitCount;
2407c2c66affSColin Finck }
2408c2c66affSColin Finck }
2409c2c66affSColin Finck
2410c2c66affSColin Finck if(iIndex >= 0)
2411c2c66affSColin Finck return dir->idEntries[iIndex].wResId;
2412c2c66affSColin Finck
2413c2c66affSColin Finck /* No inferior or equal depth available. Get the smallest bigger one */
2414c2c66affSColin Finck BitCount = 0xFFFF;
2415c2c66affSColin Finck iIndex = -1;
2416c2c66affSColin Finck for(i = 0; i < dir->idCount; i++)
2417c2c66affSColin Finck {
2418c2c66affSColin Finck entry = &dir->idEntries[i];
2419c2c66affSColin Finck width = fIcon ? entry->ResInfo.icon.bWidth : entry->ResInfo.cursor.wWidth;
2420c2c66affSColin Finck height = fIcon ? entry->ResInfo.icon.bHeight : entry->ResInfo.cursor.wHeight/2;
2421c2c66affSColin Finck /* 0 represents 256 */
2422c2c66affSColin Finck if(!width) width = 256;
2423c2c66affSColin Finck if(!height) height = 256;
2424c2c66affSColin Finck /* Check if this is the best match we had */
2425c2c66affSColin Finck score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
2426c2c66affSColin Finck if(width > cxDesired)
2427c2c66affSColin Finck score -= width - cxDesired;
2428c2c66affSColin Finck if(height > cyDesired)
2429c2c66affSColin Finck score -= height - cyDesired;
2430c2c66affSColin Finck if(score != bestScore)
2431c2c66affSColin Finck continue;
2432c2c66affSColin Finck /* Check the bit depth */
2433c2c66affSColin Finck if(entry->wBitCount < BitCount)
2434c2c66affSColin Finck {
2435c2c66affSColin Finck if((entry->wBitCount <= 8) && notPaletted)
2436c2c66affSColin Finck continue;
2437c2c66affSColin Finck iIndex = i;
2438c2c66affSColin Finck BitCount = entry->wBitCount;
2439c2c66affSColin Finck }
2440c2c66affSColin Finck }
2441c2c66affSColin Finck if (iIndex >= 0)
2442c2c66affSColin Finck return dir->idEntries[iIndex].wResId;
2443c2c66affSColin Finck
2444c2c66affSColin Finck return 0;
2445c2c66affSColin Finck }
2446c2c66affSColin Finck
CreateIcon(_In_opt_ HINSTANCE hInstance,_In_ int nWidth,_In_ int nHeight,_In_ BYTE cPlanes,_In_ BYTE cBitsPixel,_In_ const BYTE * lpbANDbits,_In_ const BYTE * lpbXORbits)2447c2c66affSColin Finck HICON WINAPI CreateIcon(
2448c2c66affSColin Finck _In_opt_ HINSTANCE hInstance,
2449c2c66affSColin Finck _In_ int nWidth,
2450c2c66affSColin Finck _In_ int nHeight,
2451c2c66affSColin Finck _In_ BYTE cPlanes,
2452c2c66affSColin Finck _In_ BYTE cBitsPixel,
2453c2c66affSColin Finck _In_ const BYTE *lpbANDbits,
2454c2c66affSColin Finck _In_ const BYTE *lpbXORbits
2455c2c66affSColin Finck )
2456c2c66affSColin Finck {
2457c2c66affSColin Finck ICONINFO iinfo;
2458c2c66affSColin Finck HICON hIcon;
2459c2c66affSColin Finck
2460c2c66affSColin Finck TRACE_(icon)("%dx%d, planes %d, bpp %d, xor %p, and %p\n",
2461c2c66affSColin Finck nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits, lpbANDbits);
2462c2c66affSColin Finck
2463c2c66affSColin Finck iinfo.fIcon = TRUE;
2464c2c66affSColin Finck iinfo.xHotspot = nWidth / 2;
2465c2c66affSColin Finck iinfo.yHotspot = nHeight / 2;
2466c2c66affSColin Finck if (cPlanes * cBitsPixel > 1)
2467c2c66affSColin Finck {
2468c2c66affSColin Finck iinfo.hbmColor = CreateBitmap( nWidth, nHeight, cPlanes, cBitsPixel, lpbXORbits );
2469c2c66affSColin Finck iinfo.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, lpbANDbits );
2470c2c66affSColin Finck }
2471c2c66affSColin Finck else
2472c2c66affSColin Finck {
2473c2c66affSColin Finck iinfo.hbmMask = CreateBitmap( nWidth, nHeight * 2, 1, 1, lpbANDbits );
2474c2c66affSColin Finck iinfo.hbmColor = NULL;
2475c2c66affSColin Finck }
2476c2c66affSColin Finck
2477c2c66affSColin Finck hIcon = CreateIconIndirect( &iinfo );
2478c2c66affSColin Finck
2479c2c66affSColin Finck DeleteObject( iinfo.hbmMask );
2480c2c66affSColin Finck if (iinfo.hbmColor) DeleteObject( iinfo.hbmColor );
2481c2c66affSColin Finck
2482c2c66affSColin Finck return hIcon;
2483c2c66affSColin Finck }
2484c2c66affSColin Finck
CreateIconFromResource(_In_ PBYTE presbits,_In_ DWORD dwResSize,_In_ BOOL fIcon,_In_ DWORD dwVer)2485c2c66affSColin Finck HICON WINAPI CreateIconFromResource(
2486c2c66affSColin Finck _In_ PBYTE presbits,
2487c2c66affSColin Finck _In_ DWORD dwResSize,
2488c2c66affSColin Finck _In_ BOOL fIcon,
2489c2c66affSColin Finck _In_ DWORD dwVer
2490c2c66affSColin Finck )
2491c2c66affSColin Finck {
2492c2c66affSColin Finck return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
2493c2c66affSColin Finck }
2494c2c66affSColin Finck
CreateIconFromResourceEx(_In_ PBYTE pbIconBits,_In_ DWORD cbIconBits,_In_ BOOL fIcon,_In_ DWORD dwVersion,_In_ int cxDesired,_In_ int cyDesired,_In_ UINT uFlags)2495c2c66affSColin Finck HICON WINAPI CreateIconFromResourceEx(
2496c2c66affSColin Finck _In_ PBYTE pbIconBits,
2497c2c66affSColin Finck _In_ DWORD cbIconBits,
2498c2c66affSColin Finck _In_ BOOL fIcon,
2499c2c66affSColin Finck _In_ DWORD dwVersion,
2500c2c66affSColin Finck _In_ int cxDesired,
2501c2c66affSColin Finck _In_ int cyDesired,
2502c2c66affSColin Finck _In_ UINT uFlags
2503c2c66affSColin Finck )
2504c2c66affSColin Finck {
2505c2c66affSColin Finck CURSORDATA cursorData;
2506c2c66affSColin Finck HICON hIcon;
2507c2c66affSColin Finck BOOL isAnimated;
2508c2c66affSColin Finck
2509c2c66affSColin Finck TRACE("%p, %lu, %lu, %lu, %i, %i, %lu.\n", pbIconBits, cbIconBits, fIcon, dwVersion, cxDesired, cyDesired, uFlags);
2510c2c66affSColin Finck
2511c2c66affSColin Finck if(uFlags & LR_DEFAULTSIZE)
2512c2c66affSColin Finck {
2513c2c66affSColin Finck if(!cxDesired) cxDesired = GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR);
2514c2c66affSColin Finck if(!cyDesired) cyDesired = GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR);
2515c2c66affSColin Finck }
2516c2c66affSColin Finck
2517c2c66affSColin Finck ZeroMemory(&cursorData, sizeof(cursorData));
2518c2c66affSColin Finck cursorData.cx = cxDesired;
2519c2c66affSColin Finck cursorData.cy = cyDesired;
2520c2c66affSColin Finck cursorData.rt = (USHORT)((ULONG_PTR)(fIcon ? RT_ICON : RT_CURSOR));
2521c2c66affSColin Finck
2522c2c66affSColin Finck /* Convert to win32k-ready data */
2523c2c66affSColin Finck if(!memcmp(pbIconBits, "RIFF", 4))
2524c2c66affSColin Finck {
2525c2c66affSColin Finck if(!CURSORICON_GetCursorDataFromANI(&cursorData, pbIconBits, cbIconBits, uFlags))
2526c2c66affSColin Finck {
2527c2c66affSColin Finck ERR("Could not get cursor data from .ani.\n");
2528c2c66affSColin Finck return NULL;
2529c2c66affSColin Finck }
2530c2c66affSColin Finck isAnimated = !!(cursorData.CURSORF_flags & CURSORF_ACON);
2531c2c66affSColin Finck }
2532c2c66affSColin Finck else
2533c2c66affSColin Finck {
2534c2c66affSColin Finck /* It is possible to pass Icon Directories to this API */
2535c2c66affSColin Finck int wResId = LookupIconIdFromDirectoryEx(pbIconBits, fIcon, cxDesired, cyDesired, uFlags);
2536c2c66affSColin Finck HANDLE ResHandle = NULL;
2537a47590c9SDoug Lyons #ifdef __REACTOS__
2538a47590c9SDoug Lyons if (wResId && (pbIconBits[4] != sizeof(BITMAPINFOHEADER)))
2539a47590c9SDoug Lyons #else
2540c2c66affSColin Finck if(wResId)
2541a47590c9SDoug Lyons #endif
2542c2c66affSColin Finck {
2543c2c66affSColin Finck HINSTANCE hinst;
2544c2c66affSColin Finck HRSRC hrsrc;
2545c2c66affSColin Finck CURSORICONDIR* pCurIconDir = (CURSORICONDIR*)pbIconBits;
2546c2c66affSColin Finck
2547c2c66affSColin Finck TRACE("Pointer points to a directory structure.\n");
2548c2c66affSColin Finck
2549c2c66affSColin Finck /* So this is a pointer to an icon directory structure. Find the module */
2550c2c66affSColin Finck if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
2551c2c66affSColin Finck (LPCWSTR)pbIconBits,
2552c2c66affSColin Finck &hinst))
2553c2c66affSColin Finck {
2554c2c66affSColin Finck return NULL;
2555c2c66affSColin Finck }
2556c2c66affSColin Finck
2557c2c66affSColin Finck /* Check we were given the right type of resource */
2558c2c66affSColin Finck if((fIcon && pCurIconDir->idType == 2) || (!fIcon && pCurIconDir->idType == 1))
2559c2c66affSColin Finck {
256003422451SSerge Gautherie WARN("Got a %s directory pointer, but called for a %s\n", fIcon ? "cursor" : "icon", fIcon ? "icon" : "cursor");
2561c2c66affSColin Finck return NULL;
2562c2c66affSColin Finck }
2563c2c66affSColin Finck
2564c2c66affSColin Finck /* Get the relevant resource pointer */
2565c2c66affSColin Finck hrsrc = FindResourceW(
2566c2c66affSColin Finck hinst,
2567c2c66affSColin Finck MAKEINTRESOURCEW(wResId),
2568c2c66affSColin Finck fIcon ? RT_ICON : RT_CURSOR);
2569c2c66affSColin Finck if (!hrsrc)
2570c2c66affSColin Finck return NULL;
2571c2c66affSColin Finck
2572c2c66affSColin Finck ResHandle = LoadResource(hinst, hrsrc);
2573c2c66affSColin Finck if (!ResHandle)
2574c2c66affSColin Finck return NULL;
2575c2c66affSColin Finck
2576c2c66affSColin Finck pbIconBits = LockResource(ResHandle);
2577c2c66affSColin Finck if (!pbIconBits)
2578c2c66affSColin Finck {
2579c2c66affSColin Finck FreeResource(ResHandle);
2580c2c66affSColin Finck return NULL;
2581c2c66affSColin Finck }
2582c2c66affSColin Finck }
2583c2c66affSColin Finck if(!fIcon)
2584c2c66affSColin Finck {
2585c2c66affSColin Finck WORD* pt = (WORD*)pbIconBits;
2586c2c66affSColin Finck cursorData.xHotspot = *pt++;
2587c2c66affSColin Finck cursorData.yHotspot = *pt++;
2588c2c66affSColin Finck pbIconBits = (PBYTE)pt;
2589c2c66affSColin Finck }
2590c2c66affSColin Finck
2591c2c66affSColin Finck if (!CURSORICON_GetCursorDataFromBMI(&cursorData, (BITMAPINFO*)pbIconBits))
2592c2c66affSColin Finck {
2593c2c66affSColin Finck ERR("Couldn't fill the CURSORDATA structure.\n");
2594c2c66affSColin Finck if (ResHandle)
2595c2c66affSColin Finck FreeResource(ResHandle);
2596c2c66affSColin Finck return NULL;
2597c2c66affSColin Finck }
2598c2c66affSColin Finck if (ResHandle)
2599c2c66affSColin Finck FreeResource(ResHandle);
2600c2c66affSColin Finck isAnimated = FALSE;
2601c2c66affSColin Finck }
2602c2c66affSColin Finck
2603c2c66affSColin Finck if (uFlags & LR_SHARED)
2604c2c66affSColin Finck cursorData.CURSORF_flags |= CURSORF_LRSHARED;
2605c2c66affSColin Finck
2606c2c66affSColin Finck hIcon = NtUserxCreateEmptyCurObject(isAnimated);
2607c2c66affSColin Finck if (!hIcon)
2608c2c66affSColin Finck goto end_error;
2609c2c66affSColin Finck
2610c2c66affSColin Finck if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData))
2611c2c66affSColin Finck {
2612c2c66affSColin Finck ERR("NtUserSetCursorIconData failed.\n");
2613c2c66affSColin Finck NtUserDestroyCursor(hIcon, TRUE);
2614c2c66affSColin Finck goto end_error;
2615c2c66affSColin Finck }
2616c2c66affSColin Finck
2617c2c66affSColin Finck if(isAnimated)
2618c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, cursorData.aspcur);
2619c2c66affSColin Finck
2620c2c66affSColin Finck return hIcon;
2621c2c66affSColin Finck
2622c2c66affSColin Finck /* Clean up */
2623c2c66affSColin Finck end_error:
2624c2c66affSColin Finck if(isAnimated)
2625c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, cursorData.aspcur);
2626c2c66affSColin Finck DeleteObject(cursorData.hbmMask);
2627c2c66affSColin Finck if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
2628c2c66affSColin Finck if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
2629c2c66affSColin Finck
2630c2c66affSColin Finck return NULL;
2631c2c66affSColin Finck }
2632c2c66affSColin Finck
CreateIconIndirect(_In_ PICONINFO piconinfo)2633c2c66affSColin Finck HICON WINAPI CreateIconIndirect(
2634c2c66affSColin Finck _In_ PICONINFO piconinfo
2635c2c66affSColin Finck )
2636c2c66affSColin Finck {
2637c2c66affSColin Finck /* As simple as creating a handle, and let win32k deal with the bitmaps */
2638c2c66affSColin Finck HICON hiconRet;
2639c2c66affSColin Finck CURSORDATA cursorData;
2640c2c66affSColin Finck
2641c2c66affSColin Finck TRACE("%p.\n", piconinfo);
2642c2c66affSColin Finck
2643c2c66affSColin Finck ZeroMemory(&cursorData, sizeof(cursorData));
2644c2c66affSColin Finck
2645c2c66affSColin Finck if(!CURSORICON_GetCursorDataFromIconInfo(&cursorData, piconinfo))
2646c2c66affSColin Finck return NULL;
2647c2c66affSColin Finck
2648c2c66affSColin Finck hiconRet = NtUserxCreateEmptyCurObject(FALSE);
2649c2c66affSColin Finck if(!hiconRet)
2650c2c66affSColin Finck goto end_error;
2651c2c66affSColin Finck
2652c2c66affSColin Finck if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, &cursorData))
2653c2c66affSColin Finck {
2654c2c66affSColin Finck NtUserDestroyCursor(hiconRet, FALSE);
2655c2c66affSColin Finck goto end_error;
2656c2c66affSColin Finck }
2657c2c66affSColin Finck
2658c2c66affSColin Finck TRACE("Returning 0x%08x.\n", hiconRet);
2659c2c66affSColin Finck
2660c2c66affSColin Finck return hiconRet;
2661c2c66affSColin Finck
2662c2c66affSColin Finck end_error:
2663c2c66affSColin Finck /* Clean up */
2664c2c66affSColin Finck DeleteObject(cursorData.hbmMask);
2665c2c66affSColin Finck if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
2666c2c66affSColin Finck if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
2667c2c66affSColin Finck
2668c2c66affSColin Finck return NULL;
2669c2c66affSColin Finck }
2670c2c66affSColin Finck
CreateCursor(_In_opt_ HINSTANCE hInst,_In_ int xHotSpot,_In_ int yHotSpot,_In_ int nWidth,_In_ int nHeight,_In_ const VOID * pvANDPlane,_In_ const VOID * pvXORPlane)2671c2c66affSColin Finck HCURSOR WINAPI CreateCursor(
2672c2c66affSColin Finck _In_opt_ HINSTANCE hInst,
2673c2c66affSColin Finck _In_ int xHotSpot,
2674c2c66affSColin Finck _In_ int yHotSpot,
2675c2c66affSColin Finck _In_ int nWidth,
2676c2c66affSColin Finck _In_ int nHeight,
2677c2c66affSColin Finck _In_ const VOID *pvANDPlane,
2678c2c66affSColin Finck _In_ const VOID *pvXORPlane
2679c2c66affSColin Finck )
2680c2c66affSColin Finck {
2681c2c66affSColin Finck ICONINFO info;
2682c2c66affSColin Finck HCURSOR hCursor;
2683c2c66affSColin Finck
2684c2c66affSColin Finck TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
2685c2c66affSColin Finck nWidth, nHeight, xHotSpot, yHotSpot, pvXORPlane, pvANDPlane);
2686c2c66affSColin Finck
2687c2c66affSColin Finck info.fIcon = FALSE;
2688c2c66affSColin Finck info.xHotspot = xHotSpot;
2689c2c66affSColin Finck info.yHotspot = yHotSpot;
2690c2c66affSColin Finck info.hbmMask = CreateBitmap( nWidth, nHeight, 1, 1, pvANDPlane );
2691c2c66affSColin Finck info.hbmColor = CreateBitmap( nWidth, nHeight, 1, 1, pvXORPlane );
2692c2c66affSColin Finck hCursor = CreateIconIndirect( &info );
2693c2c66affSColin Finck DeleteObject( info.hbmMask );
2694c2c66affSColin Finck DeleteObject( info.hbmColor );
2695c2c66affSColin Finck return hCursor;
2696c2c66affSColin Finck }
2697c2c66affSColin Finck
SetSystemCursor(_In_ HCURSOR hcur,_In_ DWORD id)2698c2c66affSColin Finck BOOL WINAPI SetSystemCursor(
2699c2c66affSColin Finck _In_ HCURSOR hcur,
2700c2c66affSColin Finck _In_ DWORD id
2701c2c66affSColin Finck )
2702c2c66affSColin Finck {
2703c2c66affSColin Finck if (hcur == NULL)
2704c2c66affSColin Finck {
2705345ad553SSerge Gautherie hcur = LoadImageW(NULL, MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
2706c2c66affSColin Finck if (hcur == NULL)
2707c2c66affSColin Finck {
2708c2c66affSColin Finck return FALSE;
2709c2c66affSColin Finck }
2710c2c66affSColin Finck }
2711c2c66affSColin Finck return NtUserSetSystemCursor(hcur,id);
2712c2c66affSColin Finck }
2713c2c66affSColin Finck
SetCursorPos(_In_ int X,_In_ int Y)2714c2c66affSColin Finck BOOL WINAPI SetCursorPos(
2715c2c66affSColin Finck _In_ int X,
2716c2c66affSColin Finck _In_ int Y
2717c2c66affSColin Finck )
2718c2c66affSColin Finck {
2719c2c66affSColin Finck return NtUserxSetCursorPos(X,Y);
2720c2c66affSColin Finck }
2721c2c66affSColin Finck
GetCursorPos(_Out_ LPPOINT lpPoint)2722c2c66affSColin Finck BOOL WINAPI GetCursorPos(
2723c2c66affSColin Finck _Out_ LPPOINT lpPoint
2724c2c66affSColin Finck )
2725c2c66affSColin Finck {
2726c2c66affSColin Finck return NtUserxGetCursorPos(lpPoint);
2727c2c66affSColin Finck }
2728c2c66affSColin Finck
ShowCursor(_In_ BOOL bShow)2729c2c66affSColin Finck int WINAPI ShowCursor(
2730c2c66affSColin Finck _In_ BOOL bShow
2731c2c66affSColin Finck )
2732c2c66affSColin Finck {
2733c2c66affSColin Finck return NtUserxShowCursor(bShow);
2734c2c66affSColin Finck }
2735c2c66affSColin Finck
GetCursor(void)2736c2c66affSColin Finck HCURSOR WINAPI GetCursor(void)
2737c2c66affSColin Finck {
2738c2c66affSColin Finck return (HCURSOR)NtUserGetThreadState(THREADSTATE_GETCURSOR);
2739c2c66affSColin Finck }
2740c2c66affSColin Finck
DestroyCursor(_In_ HCURSOR hCursor)2741c2c66affSColin Finck BOOL WINAPI DestroyCursor(
2742c2c66affSColin Finck _In_ HCURSOR hCursor
2743c2c66affSColin Finck )
2744c2c66affSColin Finck {
2745c2c66affSColin Finck return NtUserDestroyCursor(hCursor, FALSE);
2746c2c66affSColin Finck }
2747c2c66affSColin Finck
2748c2c66affSColin Finck HCURSOR
2749c2c66affSColin Finck WINAPI
GetCursorFrameInfo(HCURSOR hCursor,DWORD reserved,DWORD istep,PINT rate_jiffies,DWORD * num_steps)2750c2c66affSColin Finck GetCursorFrameInfo(HCURSOR hCursor, DWORD reserved, DWORD istep, PINT rate_jiffies, DWORD *num_steps)
2751c2c66affSColin Finck {
2752c2c66affSColin Finck return NtUserGetCursorFrameInfo(hCursor, istep, rate_jiffies, num_steps);
2753c2c66affSColin Finck }
2754