merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / lib / user32 / windows / bitmap.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/input.c
23 * PURPOSE: Input
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * UPDATE HISTORY:
26 * 09-05-2001 CSH Created
27 */
28
29 /* INCLUDES ******************************************************************/
30
31 #include "user32.h"
32 #include <string.h>
33 #include <debug.h>
34 #include <stdlib.h>
35
36 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
37 HICON ICON_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
38 HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
39 CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
40 CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
41
42 /* FUNCTIONS *****************************************************************/
43
44 /*
45 * @implemented
46 */
47 HANDLE STDCALL
48 LoadImageA(HINSTANCE hinst,
49 LPCSTR lpszName,
50 UINT uType,
51 int cxDesired,
52 int cyDesired,
53 UINT fuLoad)
54 {
55 LPWSTR lpszWName;
56 HANDLE Handle;
57 UNICODE_STRING NameString;
58
59 if (HIWORD(lpszName))
60 {
61 RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
62 lpszWName = NameString.Buffer;
63 Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
64 cyDesired, fuLoad);
65 RtlFreeUnicodeString(&NameString);
66 }
67 else
68 {
69 Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
70 cyDesired, fuLoad);
71 }
72 return(Handle);
73 }
74
75
76 HANDLE STATIC
77 LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)
78 {
79 HANDLE hResource;
80 HANDLE h2Resource;
81 HANDLE hfRes;
82 HANDLE hFile;
83 HANDLE hSection;
84 CURSORICONDIR *IconDIR;
85 HDC hScreenDc;
86 HANDLE hIcon;
87 ULONG HeaderSize;
88 ULONG ColorCount;
89 PVOID Data;
90 CURSORICONDIRENTRY* dirEntry;
91 ICONIMAGE* SafeIconImage;
92 GRPCURSORICONDIR* IconResDir;
93 INT id;
94 ICONIMAGE *ResIcon;
95 UINT ColorBits;
96
97 if (!(fuLoad & LR_LOADFROMFILE))
98 {
99 if (hinst == NULL)
100 {
101 hinst = GetModuleHandleW(L"USER32");
102 }
103 hResource = hfRes = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);
104 if (hResource == NULL)
105 {
106 return NULL;
107 }
108
109 if (fuLoad & LR_SHARED)
110 {
111 /* FIXME - pass size! */
112 hIcon = (HANDLE)NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes, 0, 0);
113 if (hIcon)
114 {
115 return hIcon;
116 }
117 }
118
119 hResource = LoadResource(hinst, hResource);
120 if (hResource == NULL)
121 {
122 return NULL;
123 }
124 IconResDir = LockResource(hResource);
125 if (IconResDir == NULL)
126 {
127 return NULL;
128 }
129
130 /* Find the best fitting in the IconResDir for this resolution. */
131 id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, TRUE,
132 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
133
134 h2Resource = FindResourceW(hinst, MAKEINTRESOURCEW(id),
135 MAKEINTRESOURCEW(RT_CURSOR));
136
137 hResource = LoadResource(hinst, h2Resource);
138 if (hResource == NULL)
139 {
140 return NULL;
141 }
142
143 ResIcon = LockResource(hResource);
144 if (ResIcon == NULL)
145 {
146 return NULL;
147 }
148
149 hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE)ResIcon,
150 SizeofResource(hinst, h2Resource), FALSE, 0x00030000,
151 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
152 if (hIcon && 0 != (fuLoad & LR_SHARED))
153 {
154 NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,
155 (HRSRC)NULL);
156 }
157
158 return hIcon;
159 }
160
161 if (fuLoad & LR_SHARED)
162 {
163 DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
164 }
165
166 hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
167 OPEN_EXISTING, 0, NULL);
168 if (hFile == NULL)
169 {
170 return NULL;
171 }
172
173 hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
174 CloseHandle(hFile);
175 if (hSection == NULL)
176 {
177 return NULL;
178 }
179
180 IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
181 CloseHandle(hSection);
182 if (IconDIR == NULL || 0 != IconDIR->idReserved
183 || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
184 {
185 return NULL;
186 }
187
188 /*
189 * Get a handle to the screen dc, the icon we create is going to be
190 * compatable with it.
191 */
192 hScreenDc = CreateCompatibleDC(0);
193 if (hScreenDc == NULL)
194 {
195 UnmapViewOfFile(IconDIR);
196 return NULL;
197 }
198
199 if (fuLoad & LR_MONOCHROME)
200 {
201 ColorBits = 1;
202 }
203 else
204 {
205 ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL);
206 /*
207 * FIXME:
208 * Remove this after proper support for alpha icons will be finished.
209 */
210 if (ColorBits > 8)
211 ColorBits = 8;
212 }
213
214 /* Pick the best size. */
215 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits);
216 if (!dirEntry)
217 {
218 UnmapViewOfFile(IconDIR);
219 return(NULL);
220 }
221
222 SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
223 memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
224
225 /* at this point we have a copy of the icon image to play with */
226
227 SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
228
229 if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
230 {
231 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
232 ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
233 HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
234 }
235 else
236 {
237 ColorCount = SafeIconImage->icHeader.biClrUsed;
238 if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
239 {
240 ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
241 }
242 HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
243 }
244
245 /* make data point to the start of the XOR image data */
246 Data = (PBYTE)SafeIconImage + HeaderSize;
247
248 hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
249 DeleteDC(hScreenDc);
250 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
251 return hIcon;
252 }
253
254
255 HANDLE STATIC
256 LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
257 {
258 HANDLE hResource;
259 HANDLE h2Resource;
260 HANDLE hfRes;
261 HANDLE hFile;
262 HANDLE hSection;
263 CURSORICONDIR* IconDIR;
264 HDC hScreenDc;
265 HANDLE hIcon;
266 ULONG HeaderSize;
267 ULONG ColorCount;
268 PVOID Data;
269 CURSORICONDIRENTRY* dirEntry;
270 ICONIMAGE* SafeIconImage;
271 GRPCURSORICONDIR* IconResDir;
272 INT id;
273 ICONIMAGE *ResIcon;
274
275 if (!(fuLoad & LR_LOADFROMFILE))
276 {
277 if (hinst == NULL)
278 {
279 hinst = GetModuleHandleW(L"USER32");
280 }
281 hResource = hfRes = FindResourceW(hinst, lpszName, RT_GROUP_ICON);
282 if (hResource == NULL)
283 {
284 return(NULL);
285 }
286
287 if (fuLoad & LR_SHARED)
288 {
289 hIcon = NtUserFindExistingCursorIcon(hinst, (HRSRC)hfRes, width, height);
290 if(hIcon)
291 return hIcon;
292 }
293
294 hResource = LoadResource(hinst, hResource);
295 if (hResource == NULL)
296 {
297 return(NULL);
298 }
299 IconResDir = LockResource(hResource);
300 if (IconResDir == NULL)
301 {
302 return(NULL);
303 }
304
305 //find the best fitting in the IconResDir for this resolution
306 id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,
307 width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
308
309 h2Resource = FindResourceW(hinst,
310 MAKEINTRESOURCEW(id),
311 MAKEINTRESOURCEW(RT_ICON));
312
313 hResource = LoadResource(hinst, h2Resource);
314 if (hResource == NULL)
315 {
316 return(NULL);
317 }
318
319 ResIcon = LockResource(hResource);
320 if (ResIcon == NULL)
321 {
322 return(NULL);
323 }
324 hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE) ResIcon,
325 SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
326 width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
327 if (hIcon && 0 != (fuLoad & LR_SHARED))
328 {
329 NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,
330 (HRSRC)NULL);
331 }
332 return hIcon;
333 }
334 else
335 {
336 /*
337 * FIXME: This code is incorrect and is likely to crash in many cases.
338 * In the file the cursor/icon directory records are stored like
339 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
340 * this is solved by creating a fake cursor/icon directory in memory
341 * and passing that to CURSORICON_FindBestIcon.
342 */
343
344 if (fuLoad & LR_SHARED)
345 {
346 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
347 }
348
349 hFile = CreateFileW(lpszName,
350 GENERIC_READ,
351 FILE_SHARE_READ,
352 NULL,
353 OPEN_EXISTING,
354 0,
355 NULL);
356 if (hFile == NULL)
357 {
358 return(NULL);
359 }
360
361 hSection = CreateFileMappingW(hFile,
362 NULL,
363 PAGE_READONLY,
364 0,
365 0,
366 NULL);
367
368 if (hSection == NULL)
369 {
370 CloseHandle(hFile);
371 return(NULL);
372 }
373 IconDIR = MapViewOfFile(hSection,
374 FILE_MAP_READ,
375 0,
376 0,
377 0);
378
379 if (IconDIR == NULL || 0 != IconDIR->idReserved
380 || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
381 {
382 CloseHandle(hFile);
383 CloseHandle(hSection);
384 return(NULL);
385 }
386
387 //pick the best size.
388 dirEntry = (CURSORICONDIRENTRY *) CURSORICON_FindBestIcon( IconDIR, width, height, 1);
389
390
391 if (!dirEntry)
392 {
393 CloseHandle(hFile);
394 CloseHandle(hSection);
395 UnmapViewOfFile(IconDIR);
396 return(NULL);
397 }
398
399 SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
400
401 memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
402
403 CloseHandle(hFile);
404 CloseHandle(hSection);
405 }
406
407 //at this point we have a copy of the icon image to play with
408
409 SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
410
411 if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
412 {
413 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
414 ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
415 HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
416 }
417 else
418 {
419 ColorCount = SafeIconImage->icHeader.biClrUsed;
420 if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
421 {
422 ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
423 }
424 HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
425 }
426
427 //make data point to the start of the XOR image data
428 Data = (PBYTE)SafeIconImage + HeaderSize;
429
430
431 //get a handle to the screen dc, the icon we create is going to be compatable with this
432 hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
433 if (hScreenDc == NULL)
434 {
435 if (fuLoad & LR_LOADFROMFILE)
436 {
437 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
438 UnmapViewOfFile(IconDIR);
439 }
440 return(NULL);
441 }
442
443 hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
444 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
445 return hIcon;
446 }
447
448
449 HANDLE STATIC
450 LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
451 {
452 HANDLE hResource;
453 HANDLE hFile;
454 HANDLE hSection;
455 BITMAPINFO* BitmapInfo;
456 BITMAPINFO* PrivateInfo;
457 HDC hScreenDc;
458 HANDLE hBitmap;
459 ULONG HeaderSize;
460 ULONG ColorCount;
461 PVOID Data;
462
463 if (!(fuLoad & LR_LOADFROMFILE))
464 {
465 if (hInstance == NULL)
466 {
467 hInstance = GetModuleHandleW(L"USER32");
468 }
469 hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
470 if (hResource == NULL)
471 {
472 return(NULL);
473 }
474 hResource = LoadResource(hInstance, hResource);
475 if (hResource == NULL)
476 {
477 return(NULL);
478 }
479 BitmapInfo = LockResource(hResource);
480 if (BitmapInfo == NULL)
481 {
482 return(NULL);
483 }
484 }
485 else
486 {
487 hFile = CreateFileW(lpszName,
488 GENERIC_READ,
489 FILE_SHARE_READ,
490 NULL,
491 OPEN_EXISTING,
492 0,
493 NULL);
494 if (hFile == NULL)
495 {
496 return(NULL);
497 }
498 hSection = CreateFileMappingW(hFile,
499 NULL,
500 PAGE_READONLY,
501 0,
502 0,
503 NULL);
504 CloseHandle(hFile);
505 if (hSection == NULL)
506 {
507 return(NULL);
508 }
509 BitmapInfo = MapViewOfFile(hSection,
510 FILE_MAP_READ,
511 0,
512 0,
513 0);
514 CloseHandle(hSection);
515 if (BitmapInfo == NULL)
516 {
517 return(NULL);
518 }
519 /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
520 unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
521 */
522 BitmapInfo = (BITMAPINFO*)(((PBYTE)BitmapInfo) + 14);
523 }
524
525 if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
526 {
527 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
528 ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
529 HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
530 }
531 else
532 {
533 ColorCount = BitmapInfo->bmiHeader.biClrUsed;
534 if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
535 {
536 ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount;
537 }
538 HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
539 }
540 Data = (PVOID)BitmapInfo + HeaderSize;
541
542 PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize);
543 if (PrivateInfo == NULL)
544 {
545 if (fuLoad & LR_LOADFROMFILE)
546 {
547 UnmapViewOfFile(BitmapInfo);
548 }
549 return(NULL);
550 }
551 memcpy(PrivateInfo, BitmapInfo, HeaderSize);
552
553 /* FIXME: Handle color conversion and transparency. */
554
555 hScreenDc = CreateCompatibleDC(NULL);
556 if (hScreenDc == NULL)
557 {
558 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
559 if (fuLoad & LR_LOADFROMFILE)
560 {
561 UnmapViewOfFile(BitmapInfo);
562 }
563 return(NULL);
564 }
565
566 if (fuLoad & LR_CREATEDIBSECTION)
567 {
568 DIBSECTION Dib;
569
570 hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
571 0, 0);
572 GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
573 SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
574 DIB_RGB_COLORS);
575 }
576 else
577 {
578 hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
579 Data, PrivateInfo, DIB_RGB_COLORS);
580 }
581
582 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
583 DeleteDC(hScreenDc);
584 if (fuLoad & LR_LOADFROMFILE)
585 {
586 UnmapViewOfFile(BitmapInfo);
587 }
588 return(hBitmap);
589 }
590
591 HANDLE STDCALL
592 LoadImageW(HINSTANCE hinst,
593 LPCWSTR lpszName,
594 UINT uType,
595 int cxDesired,
596 int cyDesired,
597 UINT fuLoad)
598 {
599 if (fuLoad & LR_DEFAULTSIZE)
600 {
601 if (uType == IMAGE_ICON)
602 {
603 if (cxDesired == 0)
604 {
605 cxDesired = GetSystemMetrics(SM_CXICON);
606 }
607 if (cyDesired == 0)
608 {
609 cyDesired = GetSystemMetrics(SM_CYICON);
610 }
611 }
612 else if (uType == IMAGE_CURSOR)
613 {
614 if (cxDesired == 0)
615 {
616 cxDesired = GetSystemMetrics(SM_CXCURSOR);
617 }
618 if (cyDesired == 0)
619 {
620 cyDesired = GetSystemMetrics(SM_CYCURSOR);
621 }
622 }
623 }
624
625 switch (uType)
626 {
627 case IMAGE_BITMAP:
628 {
629 return(LoadBitmapImage(hinst, lpszName, fuLoad));
630 }
631 case IMAGE_CURSOR:
632 {
633 return(LoadCursorImage(hinst, lpszName, fuLoad));
634 }
635 case IMAGE_ICON:
636 {
637 return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));
638 }
639 default:
640 DbgBreakPoint();
641 break;
642 }
643 return(NULL);
644 }
645
646
647 /*
648 * @implemented
649 */
650 HBITMAP STDCALL
651 LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
652 {
653 return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
654 }
655
656
657 /*
658 * @implemented
659 */
660 HBITMAP STDCALL
661 LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
662 {
663 return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
664 }
665
666
667 /*
668 * @unimplemented
669 */
670 HANDLE WINAPI
671 CopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
672 {
673 switch (type)
674 {
675 case IMAGE_BITMAP:
676 {
677 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
678 /* FIXME: support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
679 LR_COPYRETURNORG, LR_CREATEDIBSECTION,
680 and LR_MONOCHROME; */
681 HBITMAP res;
682 BITMAP bm;
683
684 if (!GetObjectW(hnd, sizeof(bm), &bm)) return 0;
685 bm.bmBits = NULL;
686 if ((res = CreateBitmapIndirect(&bm)))
687 {
688 char *buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight);
689 GetBitmapBits(hnd, bm.bmWidthBytes * bm.bmHeight, buf);
690 SetBitmapBits(res, bm.bmWidthBytes * bm.bmHeight, buf);
691 HeapFree(GetProcessHeap(), 0, buf);
692 }
693 return res;
694 }
695 case IMAGE_ICON:
696 {
697 static BOOL IconMsgDisplayed = FALSE;
698 /* FIXME: support loading the image as shared from an instance */
699 if (!IconMsgDisplayed) {
700 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
701 IconMsgDisplayed = TRUE;
702 }
703 return CopyIcon(hnd);
704 }
705 case IMAGE_CURSOR:
706 {
707 static BOOL IconMsgDisplayed = FALSE;
708 /* FIXME: support loading the image as shared from an instance */
709 if (!IconMsgDisplayed) {
710 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
711 IconMsgDisplayed = TRUE;
712 }
713 return CopyCursor(hnd);
714 }
715 }
716 return 0;
717 }