- Move NCI generated files to arch-specific directories
[reactos.git] / reactos / dll / win32 / 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
33 #include <wine/debug.h>
34
35 #include "pshpack1.h"
36
37 typedef struct {
38 BYTE bWidth;
39 BYTE bHeight;
40 BYTE bColorCount;
41 BYTE bReserved;
42 WORD xHotspot;
43 WORD yHotspot;
44 DWORD dwDIBSize;
45 DWORD dwDIBOffset;
46 } CURSORICONFILEDIRENTRY;
47
48 typedef struct
49 {
50 WORD idReserved;
51 WORD idType;
52 WORD idCount;
53 CURSORICONFILEDIRENTRY idEntries[1];
54 } CURSORICONFILEDIR;
55
56 #include "poppack.h"
57
58 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
59 HICON ICON_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
60 HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
61 CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
62 CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
63
64 /* FUNCTIONS *****************************************************************/
65
66 /*
67 * @implemented
68 */
69 HANDLE STDCALL
70 LoadImageA(HINSTANCE hinst,
71 LPCSTR lpszName,
72 UINT uType,
73 int cxDesired,
74 int cyDesired,
75 UINT fuLoad)
76 {
77 LPWSTR lpszWName;
78 HANDLE Handle;
79 UNICODE_STRING NameString;
80
81 if (HIWORD(lpszName))
82 {
83 RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
84 lpszWName = NameString.Buffer;
85 Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
86 cyDesired, fuLoad);
87 RtlFreeUnicodeString(&NameString);
88 }
89 else
90 {
91 Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
92 cyDesired, fuLoad);
93 }
94
95 return Handle;
96 }
97
98
99 /*
100 * The following macro functions account for the irregularities of
101 * accessing cursor and icon resources in files and resource entries.
102 */
103 typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n,
104 int *width, int *height, int *bits );
105
106 /**********************************************************************
107 * CURSORICON_FindBestCursor2
108 *
109 * Find the cursor closest to the requested size.
110 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
111 * ignored too
112 */
113 static int CURSORICON_FindBestCursor2( LPVOID dir, fnGetCIEntry get_entry,
114 int width, int height, int color )
115 {
116 int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
117
118 /* Double height to account for AND and XOR masks */
119
120 height *= 2;
121
122 /* First find the largest one smaller than or equal to the requested size*/
123
124 maxwidth = maxheight = 0;
125 for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
126 {
127 if ((cx <= width) && (cy <= height) &&
128 (cx > maxwidth) && (cy > maxheight) &&
129 (bits == 1))
130 {
131 bestEntry = i;
132 maxwidth = cx;
133 maxheight = cy;
134 }
135 }
136 if (bestEntry != -1) return bestEntry;
137
138 /* Now find the smallest one larger than the requested size */
139
140 maxwidth = maxheight = 255;
141 for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
142 {
143 if (((cx < maxwidth) && (cy < maxheight) && (bits == 1)) ||
144 (bestEntry==-1))
145 {
146 bestEntry = i;
147 maxwidth = cx;
148 maxheight = cy;
149 }
150 }
151
152 return bestEntry;
153 }
154
155 static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n,
156 int *width, int *height, int *bits )
157 {
158 CURSORICONFILEDIR *filedir = dir;
159 CURSORICONFILEDIRENTRY *entry;
160
161 if ( filedir->idCount <= n )
162 return FALSE;
163 entry = &filedir->idEntries[n];
164 *width = entry->bWidth;
165 *height = entry->bHeight;
166 *bits = entry->bColorCount;
167 return TRUE;
168 }
169
170 static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir,
171 int width, int height, int color )
172 {
173 int n = CURSORICON_FindBestCursor2( dir, CURSORICON_GetFileEntry,
174 width, height, color );
175 if ( n < 0 )
176 return NULL;
177 return &dir->idEntries[n];
178 }
179
180 static HANDLE
181 LoadCursorIconImage(
182 HINSTANCE hinst,
183 LPCWSTR lpszName,
184 INT width,
185 INT height,
186 UINT fuLoad,
187 ULONG uType)
188 {
189 HRSRC hResInfo;
190 HANDLE hResource;
191 HANDLE hFile;
192 HANDLE hSection;
193 CURSORICONFILEDIR *IconDIR;
194 HDC hScreenDc;
195 HICON hIcon;
196 ULONG HeaderSize;
197 ULONG ColorCount;
198 ULONG ColorBits;
199 PVOID Data;
200 CURSORICONFILEDIRENTRY* dirEntry;
201 ICONIMAGE* SafeIconImage = NULL;
202 GRPCURSORICONDIR* IconResDir;
203 INT id;
204 ICONIMAGE *ResIcon;
205 BOOL Icon = (uType == IMAGE_ICON);
206 DWORD filesize = 0;
207
208 if (!(fuLoad & LR_LOADFROMFILE))
209 {
210 if (hinst == NULL)
211 hinst = User32Instance;
212
213 hResInfo = FindResourceW(hinst, lpszName,
214 Icon ? RT_GROUP_ICON : RT_GROUP_CURSOR);
215 if (hResInfo == NULL)
216 return NULL;
217
218 hResource = LoadResource(hinst, hResInfo);
219 if (hResource == NULL)
220 return NULL;
221
222 IconResDir = LockResource(hResource);
223 if (IconResDir == NULL)
224 {
225 return NULL;
226 }
227
228 /* Find the best fitting in the IconResDir for this resolution */
229 id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, Icon, width, height,
230 fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
231
232 hResInfo = FindResourceW(hinst, MAKEINTRESOURCEW(id),
233 Icon ? (LPCWSTR) RT_ICON :
234 (LPCWSTR) RT_CURSOR);
235 if (hResInfo == NULL)
236 {
237 return NULL;
238 }
239
240 /* Now we have found the icon we want to load.
241 * Let's see if we already loaded it */
242 if (fuLoad & LR_SHARED)
243 {
244 hIcon = NtUserFindExistingCursorIcon(hinst, hResInfo, 0, 0);
245 if (hIcon)
246 {
247 return hIcon;
248 }
249 }
250
251 hResource = LoadResource(hinst, hResInfo);
252 if (hResource == NULL)
253 {
254 return NULL;
255 }
256
257 ResIcon = LockResource(hResource);
258 if (ResIcon == NULL)
259 {
260 return NULL;
261 }
262
263 hIcon = CreateIconFromResourceEx((PBYTE)ResIcon,
264 SizeofResource(hinst, hResInfo),
265 Icon, 0x00030000, width, height,
266 fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
267
268 if (hIcon && 0 != (fuLoad & LR_SHARED))
269 {
270 NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, hResInfo,
271 (HRSRC)NULL);
272 }
273
274 return hIcon;
275 }
276
277 if (fuLoad & LR_SHARED)
278 {
279 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
280 }
281
282 hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
283 OPEN_EXISTING, 0, NULL);
284 if (hFile == INVALID_HANDLE_VALUE)
285 return NULL;
286
287 hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
288 filesize = GetFileSize( hFile, NULL );
289 CloseHandle(hFile);
290 if (hSection == NULL)
291 return NULL;
292
293 IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
294 CloseHandle(hSection);
295 if (IconDIR == NULL)
296 return NULL;
297
298 if (0 != IconDIR->idReserved ||
299 (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
300 {
301 UnmapViewOfFile(IconDIR);
302 return NULL;
303 }
304
305 /* Get a handle to the screen dc, the icon we create is going to be
306 * compatable with this. */
307 hScreenDc = CreateDCW(NULL, NULL, NULL, NULL);
308 if (hScreenDc == NULL)
309 {
310 UnmapViewOfFile(IconDIR);
311 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
312 return NULL;
313 }
314
315 if (fuLoad & LR_MONOCHROME)
316 {
317 ColorBits = 1;
318 }
319 else
320 {
321 ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL);
322 /*
323 * FIXME:
324 * Remove this after proper support for alpha icons will be finished.
325 */
326 if (ColorBits > 8)
327 ColorBits = 8;
328 }
329
330 /* Pick the best size. */
331 dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits );
332 if (!dirEntry)
333 {
334 DeleteDC(hScreenDc);
335 UnmapViewOfFile(IconDIR);
336 return NULL;
337 }
338
339 if ( dirEntry->dwDIBOffset > filesize )
340 {
341 DeleteDC(hScreenDc);
342 UnmapViewOfFile(IconDIR);
343 return NULL;
344 }
345
346 if ( dirEntry->dwDIBOffset + dirEntry->dwDIBSize > filesize ){
347 DeleteDC(hScreenDc);
348 UnmapViewOfFile(IconDIR);
349 return NULL;
350 }
351
352 SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize);
353 if (SafeIconImage == NULL)
354 {
355 DeleteDC(hScreenDc);
356 UnmapViewOfFile(IconDIR);
357 return NULL;
358 }
359
360 memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwDIBOffset, dirEntry->dwDIBSize);
361 UnmapViewOfFile(IconDIR);
362
363 /* At this point we have a copy of the icon image to play with. */
364
365 SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
366
367 if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
368 {
369 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
370 ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
371 HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
372 }
373 else
374 {
375 ColorCount = SafeIconImage->icHeader.biClrUsed;
376 if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
377 ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
378 HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
379 }
380
381 /* Make data point to the start of the XOR image data. */
382 Data = (PBYTE)SafeIconImage + HeaderSize;
383
384 hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
385 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
386 DeleteDC(hScreenDc);
387
388 return hIcon;
389 }
390
391
392 static HANDLE
393 LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
394 {
395 HANDLE hResource;
396 HANDLE hFile;
397 HANDLE hSection;
398 LPBITMAPINFO BitmapInfo;
399 LPBITMAPINFO PrivateInfo;
400 HDC hScreenDc;
401 HANDLE hBitmap;
402 ULONG HeaderSize;
403 ULONG ColorCount;
404 PVOID Data;
405
406 if (!(fuLoad & LR_LOADFROMFILE))
407 {
408 if (hInstance == NULL)
409 hInstance = User32Instance;
410
411 hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
412 if (hResource == NULL)
413 return NULL;
414 hResource = LoadResource(hInstance, hResource);
415 if (hResource == NULL)
416 return NULL;
417 BitmapInfo = LockResource(hResource);
418 if (BitmapInfo == NULL)
419 return NULL;
420 }
421 else
422 {
423 hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
424 OPEN_EXISTING, 0, NULL);
425 if (hFile == INVALID_HANDLE_VALUE)
426 return NULL;
427
428 hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
429 CloseHandle(hFile);
430 if (hSection == NULL)
431 return NULL;
432
433 BitmapInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
434 CloseHandle(hSection);
435 if (BitmapInfo == NULL)
436 return NULL;
437
438 BitmapInfo = (LPBITMAPINFO)((ULONG_PTR)BitmapInfo + sizeof(BITMAPFILEHEADER));
439 }
440
441 if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
442 {
443 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
444 ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
445 HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
446 }
447 else
448 {
449 ColorCount = BitmapInfo->bmiHeader.biClrUsed;
450 if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
451 ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount;
452 HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
453 }
454 Data = (PVOID)((ULONG_PTR)BitmapInfo + HeaderSize);
455
456 PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize);
457 if (PrivateInfo == NULL)
458 {
459 if (fuLoad & LR_LOADFROMFILE)
460 UnmapViewOfFile(BitmapInfo);
461 return NULL;
462 }
463 memcpy(PrivateInfo, BitmapInfo, HeaderSize);
464
465 /* FIXME: Handle color conversion and transparency. */
466
467 hScreenDc = CreateCompatibleDC(NULL);
468 if (hScreenDc == NULL)
469 {
470 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
471 if (fuLoad & LR_LOADFROMFILE)
472 UnmapViewOfFile(BitmapInfo);
473 return NULL;
474 }
475
476 if (fuLoad & LR_CREATEDIBSECTION)
477 {
478 DIBSECTION Dib;
479
480 hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
481 0, 0);
482 GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
483 SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
484 DIB_RGB_COLORS);
485 }
486 else
487 {
488 hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
489 Data, PrivateInfo, DIB_RGB_COLORS);
490 }
491
492 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
493 DeleteDC(hScreenDc);
494 if (fuLoad & LR_LOADFROMFILE)
495 UnmapViewOfFile(BitmapInfo);
496
497 return hBitmap;
498 }
499
500 HANDLE STDCALL
501 LoadImageW(
502 IN HINSTANCE hinst,
503 IN LPCWSTR lpszName,
504 IN UINT uType,
505 IN INT cxDesired,
506 IN INT cyDesired,
507 IN UINT fuLoad)
508 {
509 if (fuLoad & LR_DEFAULTSIZE)
510 {
511 if (uType == IMAGE_ICON)
512 {
513 if (cxDesired == 0)
514 cxDesired = GetSystemMetrics(SM_CXICON);
515 if (cyDesired == 0)
516 cyDesired = GetSystemMetrics(SM_CYICON);
517 }
518 else if (uType == IMAGE_CURSOR)
519 {
520 if (cxDesired == 0)
521 cxDesired = GetSystemMetrics(SM_CXCURSOR);
522 if (cyDesired == 0)
523 cyDesired = GetSystemMetrics(SM_CYCURSOR);
524 }
525 }
526
527 switch (uType)
528 {
529 case IMAGE_BITMAP:
530 return LoadBitmapImage(hinst, lpszName, fuLoad);
531 case IMAGE_CURSOR:
532 case IMAGE_ICON:
533 return LoadCursorIconImage(hinst, lpszName, cxDesired, cyDesired,
534 fuLoad, uType);
535 default:
536 break;
537 }
538
539 return NULL;
540 }
541
542
543 /*
544 * @implemented
545 */
546 HBITMAP STDCALL
547 LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
548 {
549 return LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
550 }
551
552
553 /*
554 * @implemented
555 */
556 HBITMAP STDCALL
557 LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
558 {
559 return LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
560 }
561
562
563 /*
564 * @unimplemented
565 */
566 HANDLE WINAPI
567 CopyImage(
568 IN HANDLE hnd,
569 IN UINT type,
570 IN INT desiredx,
571 IN INT desiredy,
572 IN UINT flags)
573 {
574 /*
575 * BUGS
576 * Only Windows NT 4.0 supports the LR_COPYRETURNORG flag for bitmaps,
577 * all other versions (95/2000/XP have been tested) ignore it.
578 *
579 * NOTES
580 * If LR_CREATEDIBSECTION is absent, the copy will be monochrome for
581 * a monochrome source bitmap or if LR_MONOCHROME is present, otherwise
582 * the copy will have the same depth as the screen.
583 * The content of the image will only be copied if the bit depth of the
584 * original image is compatible with the bit depth of the screen, or
585 * if the source is a DIB section.
586 * The LR_MONOCHROME flag is ignored if LR_CREATEDIBSECTION is present.
587 */
588 switch (type)
589 {
590 case IMAGE_BITMAP:
591 {
592 HBITMAP res = NULL;
593 DIBSECTION ds;
594 int objSize;
595 BITMAPINFO * bi;
596
597 objSize = GetObjectW( hnd, sizeof(ds), &ds );
598 if (!objSize) return 0;
599 if ((desiredx < 0) || (desiredy < 0)) return 0;
600
601 if (flags & LR_COPYFROMRESOURCE)
602 {
603 DPRINT1("FIXME: The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n");
604 }
605
606 if (desiredx == 0) desiredx = ds.dsBm.bmWidth;
607 if (desiredy == 0) desiredy = ds.dsBm.bmHeight;
608
609 /* Allocate memory for a BITMAPINFOHEADER structure and a
610 color table. The maximum number of colors in a color table
611 is 256 which corresponds to a bitmap with depth 8.
612 Bitmaps with higher depths don't have color tables. */
613 bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
614 if (!bi) return 0;
615
616 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
617 bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes;
618 bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
619 bi->bmiHeader.biCompression = BI_RGB;
620
621 if (flags & LR_CREATEDIBSECTION)
622 {
623 /* Create a DIB section. LR_MONOCHROME is ignored */
624 void * bits;
625 HDC dc = CreateCompatibleDC(NULL);
626
627 if (objSize == sizeof(DIBSECTION))
628 {
629 /* The source bitmap is a DIB.
630 Get its attributes to create an exact copy */
631 memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
632 }
633
634 /* Get the color table or the color masks */
635 GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
636
637 bi->bmiHeader.biWidth = desiredx;
638 bi->bmiHeader.biHeight = desiredy;
639 bi->bmiHeader.biSizeImage = 0;
640
641 res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
642 DeleteDC(dc);
643 }
644 else
645 {
646 /* Create a device-dependent bitmap */
647
648 BOOL monochrome = (flags & LR_MONOCHROME);
649
650 if (objSize == sizeof(DIBSECTION))
651 {
652 /* The source bitmap is a DIB section.
653 Get its attributes */
654 HDC dc = CreateCompatibleDC(NULL);
655 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
656 bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
657 GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
658 DeleteDC(dc);
659
660 if (!monochrome && ds.dsBm.bmBitsPixel == 1)
661 {
662 /* Look if the colors of the DIB are black and white */
663
664 monochrome =
665 (bi->bmiColors[0].rgbRed == 0xff
666 && bi->bmiColors[0].rgbGreen == 0xff
667 && bi->bmiColors[0].rgbBlue == 0xff
668 && bi->bmiColors[0].rgbReserved == 0
669 && bi->bmiColors[1].rgbRed == 0
670 && bi->bmiColors[1].rgbGreen == 0
671 && bi->bmiColors[1].rgbBlue == 0
672 && bi->bmiColors[1].rgbReserved == 0)
673 ||
674 (bi->bmiColors[0].rgbRed == 0
675 && bi->bmiColors[0].rgbGreen == 0
676 && bi->bmiColors[0].rgbBlue == 0
677 && bi->bmiColors[0].rgbReserved == 0
678 && bi->bmiColors[1].rgbRed == 0xff
679 && bi->bmiColors[1].rgbGreen == 0xff
680 && bi->bmiColors[1].rgbBlue == 0xff
681 && bi->bmiColors[1].rgbReserved == 0);
682 }
683 }
684 else if (!monochrome)
685 {
686 monochrome = ds.dsBm.bmBitsPixel == 1;
687 }
688
689 if (monochrome)
690 {
691 res = CreateBitmap(desiredx, desiredy, 1, 1, NULL);
692 }
693 else
694 {
695 HDC screenDC = GetDC(NULL);
696 res = CreateCompatibleBitmap(screenDC, desiredx, desiredy);
697 ReleaseDC(NULL, screenDC);
698 }
699 }
700
701 if (res)
702 {
703 /* Only copy the bitmap if it's a DIB section or if it's
704 compatible to the screen */
705 BOOL copyContents;
706
707 if (objSize == sizeof(DIBSECTION))
708 {
709 copyContents = TRUE;
710 }
711 else
712 {
713 HDC screenDC = GetDC(NULL);
714 int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
715 ReleaseDC(NULL, screenDC);
716
717 copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth);
718 }
719
720 if (copyContents)
721 {
722 /* The source bitmap may already be selected in a device context,
723 use GetDIBits/StretchDIBits and not StretchBlt */
724
725 HDC dc;
726 void * bits;
727
728 dc = CreateCompatibleDC(NULL);
729
730 bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
731 bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
732 bi->bmiHeader.biSizeImage = 0;
733 bi->bmiHeader.biClrUsed = 0;
734 bi->bmiHeader.biClrImportant = 0;
735
736 /* Fill in biSizeImage */
737 GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
738 bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage);
739
740 if (bits)
741 {
742 HBITMAP oldBmp;
743
744 /* Get the image bits of the source bitmap */
745 GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
746
747 /* Copy it to the destination bitmap */
748 oldBmp = SelectObject(dc, res);
749 StretchDIBits(dc, 0, 0, desiredx, desiredy,
750 0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight,
751 bits, bi, DIB_RGB_COLORS, SRCCOPY);
752 SelectObject(dc, oldBmp);
753
754 HeapFree(GetProcessHeap(), 0, bits);
755 }
756
757 DeleteDC(dc);
758 }
759
760 if (flags & LR_COPYDELETEORG)
761 {
762 DeleteObject(hnd);
763 }
764 }
765 HeapFree(GetProcessHeap(), 0, bi);
766 return (HICON)res;
767 }
768 case IMAGE_ICON:
769 {
770 static BOOL IconMsgDisplayed = FALSE;
771 /* FIXME: support loading the image as shared from an instance */
772 if (!IconMsgDisplayed)
773 {
774 DPRINT("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
775 IconMsgDisplayed = TRUE;
776 }
777 return CopyIcon(hnd);
778 // return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
779 }
780
781 case IMAGE_CURSOR:
782 {
783 static BOOL IconMsgDisplayed = FALSE;
784 /* FIXME: support loading the image as shared from an instance */
785 if (!IconMsgDisplayed)
786 {
787 DPRINT("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
788 IconMsgDisplayed = TRUE;
789 }
790 /* Should call CURSORICON_ExtCopy but more testing
791 * needs to be done before we change this
792 */
793 if (flags) DPRINT1("FIXME: Flags are ignored\n");
794 return CopyCursor(hnd);
795 }
796 }
797 return NULL;
798 }
799