* Sync up to trunk head (r64995).
[reactos.git] / win32ss / gdi / ntgdi / dibobj.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/dibobj.c
5 * PURPOSE: Dib object functions
6 * PROGRAMMER:
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static const RGBQUAD EGAColorsQuads[16] =
15 {
16 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
17 { 0x00, 0x00, 0x00, 0x00 },
18 { 0x00, 0x00, 0x80, 0x00 },
19 { 0x00, 0x80, 0x00, 0x00 },
20 { 0x00, 0x80, 0x80, 0x00 },
21 { 0x80, 0x00, 0x00, 0x00 },
22 { 0x80, 0x00, 0x80, 0x00 },
23 { 0x80, 0x80, 0x00, 0x00 },
24 { 0x80, 0x80, 0x80, 0x00 },
25 { 0xc0, 0xc0, 0xc0, 0x00 },
26 { 0x00, 0x00, 0xff, 0x00 },
27 { 0x00, 0xff, 0x00, 0x00 },
28 { 0x00, 0xff, 0xff, 0x00 },
29 { 0xff, 0x00, 0x00, 0x00 },
30 { 0xff, 0x00, 0xff, 0x00 },
31 { 0xff, 0xff, 0x00, 0x00 },
32 { 0xff, 0xff, 0xff, 0x00 }
33 };
34
35 static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
36 {
37 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
38 { 0x00, 0x00, 0x00, 0x00 },
39 { 0x00, 0x00, 0x80, 0x00 },
40 { 0x00, 0x80, 0x00, 0x00 },
41 { 0x00, 0x80, 0x80, 0x00 },
42 { 0x80, 0x00, 0x00, 0x00 },
43 { 0x80, 0x00, 0x80, 0x00 },
44 { 0x80, 0x80, 0x00, 0x00 },
45 { 0xc0, 0xc0, 0xc0, 0x00 },
46 { 0xc0, 0xdc, 0xc0, 0x00 },
47 { 0xf0, 0xca, 0xa6, 0x00 },
48 { 0xf0, 0xfb, 0xff, 0x00 },
49 { 0xa4, 0xa0, 0xa0, 0x00 },
50 { 0x80, 0x80, 0x80, 0x00 },
51 { 0x00, 0x00, 0xf0, 0x00 },
52 { 0x00, 0xff, 0x00, 0x00 },
53 { 0x00, 0xff, 0xff, 0x00 },
54 { 0xff, 0x00, 0x00, 0x00 },
55 { 0xff, 0x00, 0xff, 0x00 },
56 { 0xff, 0xff, 0x00, 0x00 },
57 { 0xff, 0xff, 0xff, 0x00 }
58 };
59
60 PPALETTE
61 NTAPI
62 CreateDIBPalette(
63 _In_ const BITMAPINFO *pbmi,
64 _In_ PDC pdc,
65 _In_ ULONG iUsage)
66 {
67 PPALETTE ppal;
68 ULONG i, cBitsPixel, cColors;
69
70 if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
71 {
72 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
73 cBitsPixel = pbci->bmciHeader.bcBitCount;
74 }
75 else
76 {
77 cBitsPixel = pbmi->bmiHeader.biBitCount;
78 }
79
80 /* Check if the colors are indexed */
81 if (cBitsPixel <= 8)
82 {
83 /* We create a "full" palette */
84 cColors = 1 << cBitsPixel;
85
86 /* Allocate the palette */
87 ppal = PALETTE_AllocPalette(PAL_INDEXED,
88 cColors,
89 NULL,
90 0,
91 0,
92 0);
93
94 /* Check if the BITMAPINFO specifies how many colors to use */
95 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
96 (pbmi->bmiHeader.biClrUsed != 0))
97 {
98 /* This is how many colors we can actually process */
99 cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
100 }
101
102 /* Check how to use the colors */
103 if (iUsage == DIB_PAL_COLORS)
104 {
105 COLORREF crColor;
106
107 /* The colors are an array of WORD indices into the DC palette */
108 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
109
110 /* Use the DCs palette or, if no DC is given, the default one */
111 PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
112
113 /* Loop all color indices in the DIB */
114 for (i = 0; i < cColors; i++)
115 {
116 /* Get the palette index and handle wraparound when exceeding
117 the number of colors in the DC palette */
118 WORD wIndex = pwColors[i] % ppalDC->NumColors;
119
120 /* USe the RGB value from the DC palette */
121 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
122 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
123 }
124 }
125 else if (iUsage == DIB_PAL_BRUSHHACK)
126 {
127 /* The colors are an array of WORD indices into the DC palette */
128 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
129
130 /* Loop all color indices in the DIB */
131 for (i = 0; i < cColors; i++)
132 {
133 /* Set the index directly as the RGB color, the real palette
134 containing RGB values will be calculated when the brush is
135 realized */
136 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
137 }
138
139 /* Mark the palette as a brush hack palette */
140 ppal->flFlags |= PAL_BRUSHHACK;
141 }
142 // else if (iUsage == 2)
143 // {
144 // FIXME: this one is undocumented
145 // ASSERT(FALSE);
146 // }
147 else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
148 {
149 /* The colors are an array of RGBQUAD values */
150 RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
151
152 // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
153
154 /* Loop all color indices in the DIB */
155 for (i = 0; i < cColors; i++)
156 {
157 /* Get the color value and translate it to a COLORREF */
158 RGBQUAD rgb = prgb[i];
159 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
160
161 /* Set the RGB value in the palette */
162 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
163 }
164 }
165 else
166 {
167 /* The colors are an array of RGBTRIPLE values */
168 RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
169
170 /* Loop all color indices in the DIB */
171 for (i = 0; i < cColors; i++)
172 {
173 /* Get the color value and translate it to a COLORREF */
174 RGBTRIPLE rgb = prgb[i];
175 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
176
177 /* Set the RGB value in the palette */
178 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
179 }
180 }
181 }
182 else
183 {
184 /* This is a bitfield / RGB palette */
185 ULONG flRedMask, flGreenMask, flBlueMask;
186
187 /* Check if the DIB contains bitfield values */
188 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
189 (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
190 {
191 /* Check if we have a v4/v5 header */
192 if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
193 {
194 /* The masks are dedicated fields in the header */
195 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
196 flRedMask = pbmV4Header->bV4RedMask;
197 flGreenMask = pbmV4Header->bV4GreenMask;
198 flBlueMask = pbmV4Header->bV4BlueMask;
199 }
200 else
201 {
202 /* The masks are the first 3 values in the DIB color table */
203 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
204 flRedMask = pdwColors[0];
205 flGreenMask = pdwColors[1];
206 flBlueMask = pdwColors[2];
207 }
208 }
209 else
210 {
211 /* Check what bit depth we have. Note: optimization flags are
212 calculated in PALETTE_AllocPalette() */
213 if (cBitsPixel == 16)
214 {
215 /* This is an RGB 555 palette */
216 flRedMask = 0x7C00;
217 flGreenMask = 0x03E0;
218 flBlueMask = 0x001F;
219 }
220 else
221 {
222 /* This is an RGB 888 palette */
223 flRedMask = 0xFF0000;
224 flGreenMask = 0x00FF00;
225 flBlueMask = 0x0000FF;
226 }
227 }
228
229 /* Allocate the bitfield palette */
230 ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
231 0,
232 NULL,
233 flRedMask,
234 flGreenMask,
235 flBlueMask);
236 }
237
238 /* We're done, return the palette */
239 return ppal;
240 }
241
242 // Converts a DIB to a device-dependent bitmap
243 static INT
244 FASTCALL
245 IntSetDIBits(
246 PDC DC,
247 HBITMAP hBitmap,
248 UINT StartScan,
249 UINT ScanLines,
250 CONST VOID *Bits,
251 CONST BITMAPINFO *bmi,
252 UINT ColorUse)
253 {
254 HBITMAP SourceBitmap;
255 PSURFACE psurfDst, psurfSrc;
256 INT result = 0;
257 RECT rcDst;
258 POINTL ptSrc;
259 EXLATEOBJ exlo;
260 PPALETTE ppalDIB = 0;
261
262 if (!bmi) return 0;
263
264 SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
265 ScanLines,
266 0,
267 BitmapFormat(bmi->bmiHeader.biBitCount,
268 bmi->bmiHeader.biCompression),
269 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
270 bmi->bmiHeader.biSizeImage,
271 (PVOID)Bits,
272 0);
273 if (!SourceBitmap)
274 {
275 DPRINT1("Error: Could not create a bitmap.\n");
276 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
277 return 0;
278 }
279
280 psurfDst = SURFACE_ShareLockSurface(hBitmap);
281 psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
282
283 if(!(psurfSrc && psurfDst))
284 {
285 DPRINT1("Error: Could not lock surfaces\n");
286 goto cleanup;
287 }
288
289 /* Create a palette for the DIB */
290 ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
291 if (!ppalDIB)
292 {
293 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
294 goto cleanup;
295 }
296
297 /* Initialize EXLATEOBJ */
298 EXLATEOBJ_vInitialize(&exlo,
299 ppalDIB,
300 psurfDst->ppal,
301 RGB(0xff, 0xff, 0xff),
302 RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
303 0); // DC->pdcattr->crForegroundClr);
304
305 rcDst.top = StartScan;
306 rcDst.left = 0;
307 rcDst.bottom = rcDst.top + ScanLines;
308 rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
309 ptSrc.x = 0;
310 ptSrc.y = 0;
311
312 result = IntEngCopyBits(&psurfDst->SurfObj,
313 &psurfSrc->SurfObj,
314 NULL,
315 &exlo.xlo,
316 &rcDst,
317 &ptSrc);
318 if(result)
319 result = ScanLines;
320
321 EXLATEOBJ_vCleanup(&exlo);
322
323 cleanup:
324 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
325 if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
326 if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
327 GreDeleteObject(SourceBitmap);
328
329 return result;
330 }
331
332 static
333 HBITMAP
334 IntGdiCreateMaskFromRLE(
335 DWORD Width,
336 DWORD Height,
337 ULONG Compression,
338 const BYTE* Bits,
339 DWORD BitsSize)
340 {
341 HBITMAP Mask;
342 DWORD x, y;
343 SURFOBJ* SurfObj;
344 UINT i = 0;
345 BYTE Data, NumPixels, ToSkip;
346
347 ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
348
349 /* Create the bitmap */
350 Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
351 if (!Mask)
352 return NULL;
353
354 SurfObj = EngLockSurface((HSURF)Mask);
355 if (!SurfObj)
356 {
357 GreDeleteObject(Mask);
358 return NULL;
359 }
360 ASSERT(SurfObj->pvBits != NULL);
361
362 x = y = 0;
363
364 while (i < BitsSize)
365 {
366 NumPixels = Bits[i];
367 Data = Bits[i + 1];
368 i += 2;
369
370 if (NumPixels != 0)
371 {
372 if ((x + NumPixels) > Width)
373 NumPixels = Width - x;
374
375 if (NumPixels == 0)
376 continue;
377
378 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
379 x += NumPixels;
380 continue;
381 }
382
383 if (Data < 3)
384 {
385 switch (Data)
386 {
387 case 0:
388 /* End of line */
389 y++;
390 if (y == Height)
391 goto done;
392 x = 0;
393 break;
394 case 1:
395 /* End of file */
396 goto done;
397 case 2:
398 /* Jump */
399 if (i >= (BitsSize - 1))
400 goto done;
401 x += Bits[i];
402 if (x > Width)
403 x = Width;
404 y += Bits[i + 1];
405 if (y >= Height)
406 goto done;
407 i += 2;
408 break;
409 }
410 /* Done for this run */
411 continue;
412 }
413
414 /* Embedded data into the RLE */
415 NumPixels = Data;
416 if (Compression == BI_RLE8)
417 ToSkip = NumPixels;
418 else
419 ToSkip = (NumPixels / 2) + (NumPixels & 1);
420
421 if ((i + ToSkip) > BitsSize)
422 goto done;
423 ToSkip = (ToSkip + 1) & ~1;
424
425 if ((x + NumPixels) > Width)
426 NumPixels = Width - x;
427
428 if (NumPixels != 0)
429 {
430 DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
431 x += NumPixels;
432 }
433 i += ToSkip;
434 }
435
436 done:
437 EngUnlockSurface(SurfObj);
438 return Mask;
439 }
440
441 W32KAPI
442 INT
443 APIENTRY
444 NtGdiSetDIBitsToDeviceInternal(
445 IN HDC hDC,
446 IN INT XDest,
447 IN INT YDest,
448 IN DWORD Width,
449 IN DWORD Height,
450 IN INT XSrc,
451 IN INT YSrc,
452 IN DWORD StartScan,
453 IN DWORD ScanLines,
454 IN LPBYTE Bits,
455 IN LPBITMAPINFO bmi,
456 IN DWORD ColorUse,
457 IN UINT cjMaxBits,
458 IN UINT cjMaxInfo,
459 IN BOOL bTransformCoordinates,
460 IN OPTIONAL HANDLE hcmXform)
461 {
462 INT ret = 0;
463 NTSTATUS Status = STATUS_SUCCESS;
464 PDC pDC;
465 HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
466 SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
467 SURFACE *pSurf;
468 RECTL rcDest;
469 POINTL ptSource;
470 //INT DIBWidth;
471 SIZEL SourceSize;
472 EXLATEOBJ exlo;
473 PPALETTE ppalDIB = NULL;
474 LPBITMAPINFO pbmiSafe;
475
476 if (!Bits) return 0;
477
478 pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
479 if (!pbmiSafe) return 0;
480
481 _SEH2_TRY
482 {
483 ProbeForRead(bmi, cjMaxInfo, 1);
484 ProbeForRead(Bits, cjMaxBits, 1);
485 RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
486 bmi = pbmiSafe;
487 }
488 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
489 {
490 Status = _SEH2_GetExceptionCode();
491 }
492 _SEH2_END
493
494 if (!NT_SUCCESS(Status))
495 {
496 goto Exit2;
497 }
498
499 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
500
501 pDC = DC_LockDc(hDC);
502 if (!pDC)
503 {
504 EngSetLastError(ERROR_INVALID_HANDLE);
505 goto Exit2;
506 }
507
508 if (pDC->dctype == DC_TYPE_INFO)
509 {
510 DC_UnlockDc(pDC);
511 goto Exit;
512 }
513
514 rcDest.left = XDest;
515 rcDest.top = YDest;
516 if (bTransformCoordinates)
517 {
518 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
519 }
520 rcDest.left += pDC->ptlDCOrig.x;
521 rcDest.top += pDC->ptlDCOrig.y;
522 rcDest.right = rcDest.left + Width;
523 rcDest.bottom = rcDest.top + Height;
524 rcDest.top += StartScan;
525
526 ptSource.x = XSrc;
527 ptSource.y = YSrc;
528
529 SourceSize.cx = bmi->bmiHeader.biWidth;
530 SourceSize.cy = ScanLines;
531
532 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
533
534 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
535 ScanLines,
536 0,
537 BitmapFormat(bmi->bmiHeader.biBitCount,
538 bmi->bmiHeader.biCompression),
539 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
540 bmi->bmiHeader.biSizeImage,
541 Bits,
542 0);
543
544 if (!hSourceBitmap)
545 {
546 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
547 Status = STATUS_NO_MEMORY;
548 goto Exit;
549 }
550
551 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
552 if (!pSourceSurf)
553 {
554 Status = STATUS_UNSUCCESSFUL;
555 goto Exit;
556 }
557
558 /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
559 if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
560 {
561 hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
562 ScanLines,
563 bmi->bmiHeader.biCompression,
564 Bits,
565 cjMaxBits);
566 if (!hMaskBitmap)
567 {
568 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
569 Status = STATUS_NO_MEMORY;
570 goto Exit;
571 }
572 pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
573 if (!pMaskSurf)
574 {
575 Status = STATUS_UNSUCCESSFUL;
576 goto Exit;
577 }
578 }
579
580 /* Create a palette for the DIB */
581 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
582 if (!ppalDIB)
583 {
584 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
585 Status = STATUS_NO_MEMORY;
586 goto Exit;
587 }
588
589 /* This is actually a blit */
590 DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
591 pSurf = pDC->dclevel.pSurface;
592 if (!pSurf)
593 {
594 DC_vFinishBlit(pDC, NULL);
595 ret = ScanLines;
596 goto Exit;
597 }
598
599 ASSERT(pSurf->ppal);
600
601 /* Initialize EXLATEOBJ */
602 EXLATEOBJ_vInitialize(&exlo,
603 ppalDIB,
604 pSurf->ppal,
605 RGB(0xff, 0xff, 0xff),
606 pDC->pdcattr->crBackgroundClr,
607 pDC->pdcattr->crForegroundClr);
608
609 pDestSurf = &pSurf->SurfObj;
610
611 /* Copy the bits */
612 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
613 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
614 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
615 Status = IntEngBitBlt(pDestSurf,
616 pSourceSurf,
617 pMaskSurf,
618 &pDC->co.ClipObj,
619 &exlo.xlo,
620 &rcDest,
621 &ptSource,
622 pMaskSurf ? &ptSource : NULL,
623 NULL,
624 NULL,
625 pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
626
627 /* Cleanup EXLATEOBJ */
628 EXLATEOBJ_vCleanup(&exlo);
629
630 /* We're done */
631 DC_vFinishBlit(pDC, NULL);
632
633 Exit:
634 if (NT_SUCCESS(Status))
635 {
636 ret = ScanLines;
637 }
638
639 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
640
641 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
642 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
643 if (pMaskSurf) EngUnlockSurface(pMaskSurf);
644 if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
645 DC_UnlockDc(pDC);
646 Exit2:
647 ExFreePoolWithTag(pbmiSafe, 'pmTG');
648 return ret;
649 }
650
651
652 /* Converts a device-dependent bitmap to a DIB */
653 INT
654 APIENTRY
655 GreGetDIBitsInternal(
656 HDC hDC,
657 HBITMAP hBitmap,
658 UINT StartScan,
659 UINT ScanLines,
660 LPBYTE Bits,
661 LPBITMAPINFO Info,
662 UINT Usage,
663 UINT MaxBits,
664 UINT MaxInfo)
665 {
666 BITMAPCOREINFO* pbmci = NULL;
667 PSURFACE psurf = NULL;
668 PDC pDC;
669 LONG width, height;
670 WORD planes, bpp;
671 DWORD compr, size ;
672 USHORT i;
673 int bitmap_type;
674 RGBQUAD* rgbQuads;
675 VOID* colorPtr;
676
677 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
678
679 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
680 return 0;
681
682 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
683 rgbQuads = colorPtr;
684
685 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
686 &width,
687 &height,
688 &planes,
689 &bpp,
690 &compr,
691 &size);
692 if(bitmap_type == -1)
693 {
694 DPRINT("Wrong bitmap format\n");
695 EngSetLastError(ERROR_INVALID_PARAMETER);
696 return 0;
697 }
698 else if(bitmap_type == 0)
699 {
700 /* We need a BITMAPINFO to create a DIB, but we have to fill
701 * the BITMAPCOREINFO we're provided */
702 pbmci = (BITMAPCOREINFO*)Info;
703 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
704 if(Info == NULL)
705 {
706 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
707 return 0;
708 }
709 rgbQuads = Info->bmiColors;
710 }
711
712 pDC = DC_LockDc(hDC);
713 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
714 {
715 ScanLines = 0;
716 goto done;
717 }
718
719 /* Get a pointer to the source bitmap object */
720 psurf = SURFACE_ShareLockSurface(hBitmap);
721 if (psurf == NULL)
722 {
723 ScanLines = 0;
724 goto done;
725 }
726
727 /* Fill in the structure */
728 switch(bpp)
729 {
730 case 0: /* Only info */
731 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
732 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
733 -psurf->SurfObj.sizlBitmap.cy :
734 psurf->SurfObj.sizlBitmap.cy;;
735 Info->bmiHeader.biPlanes = 1;
736 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
737 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
738 Info->bmiHeader.biHeight,
739 Info->bmiHeader.biBitCount);
740 if(psurf->hSecure)
741 {
742 switch(Info->bmiHeader.biBitCount)
743 {
744 case 16:
745 case 32:
746 Info->bmiHeader.biCompression = BI_BITFIELDS;
747 break;
748 default:
749 Info->bmiHeader.biCompression = BI_RGB;
750 break;
751 }
752 }
753 else if(Info->bmiHeader.biBitCount > 8)
754 {
755 Info->bmiHeader.biCompression = BI_BITFIELDS;
756 }
757 else
758 {
759 Info->bmiHeader.biCompression = BI_RGB;
760 }
761 Info->bmiHeader.biXPelsPerMeter = 0;
762 Info->bmiHeader.biYPelsPerMeter = 0;
763 Info->bmiHeader.biClrUsed = 0;
764 Info->bmiHeader.biClrImportant = 0;
765 ScanLines = abs(Info->bmiHeader.biHeight);
766 goto done;
767
768 case 1:
769 case 4:
770 case 8:
771 Info->bmiHeader.biClrUsed = 0;
772
773 /* If the bitmap if a DIB section and has the same format than what
774 * we're asked, go ahead! */
775 if((psurf->hSecure) &&
776 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
777 {
778 if(Usage == DIB_RGB_COLORS)
779 {
780 ULONG colors = min(psurf->ppal->NumColors, 256);
781 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
782 for(i = 0; i < colors; i++)
783 {
784 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
785 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
786 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
787 rgbQuads[i].rgbReserved = 0;
788 }
789 }
790 else
791 {
792 for(i = 0; i < 256; i++)
793 ((WORD*)rgbQuads)[i] = i;
794 }
795 }
796 else
797 {
798 if(Usage == DIB_PAL_COLORS)
799 {
800 for(i = 0; i < 256; i++)
801 {
802 ((WORD*)rgbQuads)[i] = i;
803 }
804 }
805 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
806 {
807 /* For color DDBs in native depth (mono DDBs always have
808 a black/white palette):
809 Generate the color map from the selected palette */
810 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
811 if(!pDcPal)
812 {
813 ScanLines = 0 ;
814 goto done ;
815 }
816 for (i = 0; i < pDcPal->NumColors; i++)
817 {
818 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
819 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
820 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
821 rgbQuads[i].rgbReserved = 0;
822 }
823 PALETTE_ShareUnlockPalette(pDcPal);
824 }
825 else
826 {
827 switch (bpp)
828 {
829 case 1:
830 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
831 rgbQuads[0].rgbReserved = 0;
832 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
833 rgbQuads[1].rgbReserved = 0;
834 break;
835
836 case 4:
837 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
838 break;
839
840 case 8:
841 {
842 INT r, g, b;
843 RGBQUAD *color;
844 memcpy(rgbQuads, DefLogPaletteQuads,
845 10 * sizeof(RGBQUAD));
846 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
847 10 * sizeof(RGBQUAD));
848 color = rgbQuads + 10;
849 for(r = 0; r <= 5; r++) /* FIXME */
850 {
851 for(g = 0; g <= 5; g++)
852 {
853 for(b = 0; b <= 5; b++)
854 {
855 color->rgbRed = (r * 0xff) / 5;
856 color->rgbGreen = (g * 0xff) / 5;
857 color->rgbBlue = (b * 0xff) / 5;
858 color->rgbReserved = 0;
859 color++;
860 }
861 }
862 }
863 }
864 }
865 }
866 }
867 break;
868
869 case 15:
870 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
871 {
872 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
873 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
874 ((PDWORD)Info->bmiColors)[2] = 0x001f;
875 }
876 break;
877
878 case 16:
879 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
880 {
881 if (psurf->hSecure)
882 {
883 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
884 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
885 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
886 }
887 else
888 {
889 ((PDWORD)Info->bmiColors)[0] = 0xf800;
890 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
891 ((PDWORD)Info->bmiColors)[2] = 0x001f;
892 }
893 }
894 break;
895
896 case 24:
897 case 32:
898 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
899 {
900 if (psurf->hSecure)
901 {
902 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
903 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
904 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
905 }
906 else
907 {
908 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
909 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
910 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
911 }
912 }
913 break;
914 }
915 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
916
917 if(Bits && ScanLines)
918 {
919 /* Create a DIBSECTION, blt it, profit */
920 PVOID pDIBits ;
921 HBITMAP hBmpDest;
922 PSURFACE psurfDest;
923 EXLATEOBJ exlo;
924 RECT rcDest;
925 POINTL srcPoint;
926 BOOL ret ;
927
928 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
929 {
930 ScanLines = 0;
931 goto done;
932 }
933 else
934 {
935 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
936 }
937
938 /* Fixup values */
939 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
940 Info->bmiHeader.biHeight = (height < 0) ?
941 -(LONG)ScanLines : ScanLines;
942 /* Create the DIB */
943 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
944 /* Restore them */
945 Info->bmiHeader.biWidth = width;
946 Info->bmiHeader.biHeight = height;
947
948 if(!hBmpDest)
949 {
950 DPRINT1("Unable to create a DIB Section!\n");
951 EngSetLastError(ERROR_INVALID_PARAMETER);
952 ScanLines = 0;
953 goto done ;
954 }
955
956 psurfDest = SURFACE_ShareLockSurface(hBmpDest);
957
958 RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
959
960 srcPoint.x = 0;
961
962 if(height < 0)
963 {
964 srcPoint.y = 0;
965
966 if(ScanLines <= StartScan)
967 {
968 ScanLines = 1;
969 SURFACE_ShareUnlockSurface(psurfDest);
970 GreDeleteObject(hBmpDest);
971 goto done;
972 }
973
974 ScanLines -= StartScan;
975 }
976 else
977 {
978 srcPoint.y = StartScan;
979 }
980
981 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
982
983 ret = IntEngCopyBits(&psurfDest->SurfObj,
984 &psurf->SurfObj,
985 NULL,
986 &exlo.xlo,
987 &rcDest,
988 &srcPoint);
989
990 SURFACE_ShareUnlockSurface(psurfDest);
991
992 if(!ret)
993 ScanLines = 0;
994 else
995 {
996 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
997 }
998
999 GreDeleteObject(hBmpDest);
1000 EXLATEOBJ_vCleanup(&exlo);
1001 }
1002 else ScanLines = abs(height);
1003
1004 done:
1005
1006 if(pDC) DC_UnlockDc(pDC);
1007 if(psurf) SURFACE_ShareUnlockSurface(psurf);
1008 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
1009
1010 return ScanLines;
1011 }
1012
1013 INT
1014 APIENTRY
1015 NtGdiGetDIBitsInternal(
1016 _In_ HDC hdc,
1017 _In_ HBITMAP hbm,
1018 _In_ UINT iStartScan,
1019 _In_ UINT cScans,
1020 _Out_opt_ LPBYTE pjBits,
1021 _Inout_ LPBITMAPINFO pbmiUser,
1022 _In_ UINT iUsage,
1023 _In_ UINT cjMaxBits,
1024 _In_ UINT cjMaxInfo)
1025 {
1026 PBITMAPINFO pbmi;
1027 HANDLE hSecure = NULL;
1028 INT iResult = 0;
1029 UINT cjAlloc;
1030
1031 /* Check for bad iUsage */
1032 if (iUsage > 2) return 0;
1033
1034 /* Check if the size of the bitmap info is large enough */
1035 if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
1036 {
1037 return 0;
1038 }
1039
1040 /* Use maximum size */
1041 cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
1042
1043 // HACK: the underlying code sucks and doesn't care for the size, so we
1044 // give it the maximum ever needed
1045 cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
1046
1047 /* Allocate a buffer the bitmapinfo */
1048 pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
1049 if (!pbmi)
1050 {
1051 /* Fail */
1052 return 0;
1053 }
1054
1055 /* Use SEH */
1056 _SEH2_TRY
1057 {
1058 /* Probe and copy the BITMAPINFO */
1059 ProbeForRead(pbmiUser, cjMaxInfo, 1);
1060 RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
1061 }
1062 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1063 {
1064 _SEH2_YIELD(goto cleanup;)
1065 }
1066 _SEH2_END;
1067
1068 /* Check if the header size is large enough */
1069 if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
1070 (pbmi->bmiHeader.biSize > cjMaxInfo))
1071 {
1072 goto cleanup;
1073 }
1074
1075 /* Check if the caller provided bitmap bits */
1076 if (pjBits)
1077 {
1078 /* Secure the user mode memory */
1079 hSecure = EngSecureMem(pjBits, cjMaxBits);
1080 if (!hSecure)
1081 {
1082 goto cleanup;
1083 }
1084 }
1085
1086 /* Now call the internal function */
1087 iResult = GreGetDIBitsInternal(hdc,
1088 hbm,
1089 iStartScan,
1090 cScans,
1091 pjBits,
1092 pbmi,
1093 iUsage,
1094 cjMaxBits,
1095 cjMaxInfo);
1096
1097 /* Check for success */
1098 if (iResult)
1099 {
1100 /* Use SEH to copy back to user mode */
1101 _SEH2_TRY
1102 {
1103 /* Copy the data back */
1104 ProbeForWrite(pbmiUser, cjMaxInfo, 1);
1105 RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
1106 }
1107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1108 {
1109 /* Ignore */
1110 }
1111 _SEH2_END;
1112 }
1113
1114 cleanup:
1115 if (hSecure) EngUnsecureMem(hSecure);
1116 ExFreePoolWithTag(pbmi, 'imBG');
1117
1118 return iResult;
1119 }
1120
1121
1122 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
1123
1124 W32KAPI
1125 INT
1126 APIENTRY
1127 NtGdiStretchDIBitsInternal(
1128 IN HDC hdc,
1129 IN INT xDst,
1130 IN INT yDst,
1131 IN INT cxDst,
1132 IN INT cyDst,
1133 IN INT xSrc,
1134 IN INT ySrc,
1135 IN INT cxSrc,
1136 IN INT cySrc,
1137 IN OPTIONAL LPBYTE pjInit,
1138 IN LPBITMAPINFO pbmi,
1139 IN DWORD dwUsage,
1140 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
1141 IN UINT cjMaxInfo,
1142 IN UINT cjMaxBits,
1143 IN HANDLE hcmXform)
1144 {
1145 BOOL bResult = FALSE;
1146 SIZEL sizel;
1147 RECTL rcSrc, rcDst;
1148 PDC pdc;
1149 HBITMAP hbmTmp = 0;
1150 PSURFACE psurfTmp = 0, psurfDst = 0;
1151 PPALETTE ppalDIB = 0;
1152 EXLATEOBJ exlo;
1153 PVOID pvBits;
1154
1155 if (!(pdc = DC_LockDc(hdc)))
1156 {
1157 EngSetLastError(ERROR_INVALID_HANDLE);
1158 return 0;
1159 }
1160
1161 /* Check for info / mem DC without surface */
1162 if (!pdc->dclevel.pSurface)
1163 {
1164 DC_UnlockDc(pdc);
1165 // CHECKME
1166 return TRUE;
1167 }
1168
1169 /* Transform dest size */
1170 sizel.cx = cxDst;
1171 sizel.cy = cyDst;
1172 IntLPtoDP(pdc, (POINTL*)&sizel, 1);
1173 DC_UnlockDc(pdc);
1174
1175 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
1176 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
1177 {
1178 /* Yes, we can! */
1179 return NtGdiSetDIBitsToDeviceInternal(hdc,
1180 xDst,
1181 yDst,
1182 cxDst,
1183 cyDst,
1184 xSrc,
1185 ySrc,
1186 0,
1187 cySrc,
1188 pjInit,
1189 pbmi,
1190 dwUsage,
1191 cjMaxBits,
1192 cjMaxInfo,
1193 TRUE,
1194 hcmXform);
1195 }
1196
1197 if (pjInit && (cjMaxBits > 0))
1198 {
1199 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
1200 if (!pvBits)
1201 {
1202 return 0;
1203 }
1204
1205 _SEH2_TRY
1206 {
1207 ProbeForRead(pjInit, cjMaxBits, 1);
1208 RtlCopyMemory(pvBits, pjInit, cjMaxBits);
1209 }
1210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1211 {
1212 ExFreePoolWithTag(pvBits, 'pmeT');
1213 _SEH2_YIELD(return 0);
1214 }
1215 _SEH2_END
1216 }
1217 else
1218 {
1219 pvBits = NULL;
1220 }
1221
1222 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
1223 if (!(pdc = DC_LockDc(hdc)))
1224 {
1225 DPRINT1("Could not lock dc\n");
1226 EngSetLastError(ERROR_INVALID_HANDLE);
1227 goto cleanup;
1228 }
1229
1230 /* Calculate source and destination rect */
1231 rcSrc.left = xSrc;
1232 rcSrc.top = ySrc;
1233 rcSrc.right = xSrc + abs(cxSrc);
1234 rcSrc.bottom = ySrc + abs(cySrc);
1235 rcDst.left = xDst;
1236 rcDst.top = yDst;
1237 rcDst.right = rcDst.left + cxDst;
1238 rcDst.bottom = rcDst.top + cyDst;
1239 IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
1240 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1241
1242 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
1243 pbmi->bmiHeader.biHeight,
1244 0,
1245 BitmapFormat(pbmi->bmiHeader.biBitCount,
1246 pbmi->bmiHeader.biCompression),
1247 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
1248 pbmi->bmiHeader.biSizeImage,
1249 pvBits,
1250 0);
1251
1252 if (!hbmTmp)
1253 {
1254 bResult = FALSE;
1255 goto cleanup;
1256 }
1257
1258 psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
1259 if (!psurfTmp)
1260 {
1261 bResult = FALSE;
1262 goto cleanup;
1263 }
1264
1265 /* Create a palette for the DIB */
1266 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
1267 if (!ppalDIB)
1268 {
1269 bResult = FALSE;
1270 goto cleanup;
1271 }
1272
1273 /* Prepare DC for blit */
1274 DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
1275
1276 psurfDst = pdc->dclevel.pSurface;
1277
1278 /* Initialize XLATEOBJ */
1279 EXLATEOBJ_vInitialize(&exlo,
1280 ppalDIB,
1281 psurfDst->ppal,
1282 RGB(0xff, 0xff, 0xff),
1283 pdc->pdcattr->crBackgroundClr,
1284 pdc->pdcattr->crForegroundClr);
1285
1286 /* Perform the stretch operation */
1287 bResult = IntEngStretchBlt(&psurfDst->SurfObj,
1288 &psurfTmp->SurfObj,
1289 NULL,
1290 &pdc->co.ClipObj,
1291 &exlo.xlo,
1292 &pdc->dclevel.ca,
1293 &rcDst,
1294 &rcSrc,
1295 NULL,
1296 &pdc->eboFill.BrushObject,
1297 NULL,
1298 ROP_TO_ROP4(dwRop));
1299
1300 /* Cleanup */
1301 DC_vFinishBlit(pdc, NULL);
1302 EXLATEOBJ_vCleanup(&exlo);
1303 cleanup:
1304 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
1305 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
1306 if (hbmTmp) GreDeleteObject(hbmTmp);
1307 if (pdc) DC_UnlockDc(pdc);
1308 if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
1309
1310 return bResult;
1311 }
1312
1313
1314 HBITMAP
1315 FASTCALL
1316 IntCreateDIBitmap(
1317 PDC Dc,
1318 INT width,
1319 INT height,
1320 UINT planes,
1321 UINT bpp,
1322 ULONG compression,
1323 DWORD init,
1324 LPBYTE bits,
1325 PBITMAPINFO data,
1326 DWORD coloruse)
1327 {
1328 HBITMAP handle;
1329 BOOL fColor;
1330 ULONG BmpFormat = 0;
1331
1332 if (planes && bpp)
1333 BmpFormat = BitmapFormat(planes * bpp, compression);
1334
1335 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1336 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1337
1338 if (BmpFormat != BMF_1BPP) fColor = TRUE;
1339 else if ((coloruse > DIB_RGB_COLORS) || ((init & CBM_INIT) == 0) || !data) fColor = FALSE;
1340 else
1341 {
1342 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1343 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1344
1345 // Check if the first color of the colormap is black
1346 if (col == RGB(0, 0, 0))
1347 {
1348 rgb++;
1349 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1350
1351 // If the second color is white, create a monochrome bitmap
1352 fColor = (col != RGB(0xff,0xff,0xff));
1353 }
1354 else fColor = TRUE;
1355 }
1356
1357 // Now create the bitmap
1358 if (fColor)
1359 {
1360 if (init & CBM_CREATDIB)
1361 {
1362 PSURFACE Surface;
1363 PPALETTE Palette;
1364
1365 /* Undocumented flag which creates a DDB of the format specified by the bitmap info. */
1366 handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp);
1367 if (!handle)
1368 return NULL;
1369 /* The palette must also match the given data */
1370 Surface = SURFACE_ShareLockSurface(handle);
1371 ASSERT(Surface);
1372 Palette = CreateDIBPalette(data, Dc, coloruse);
1373 ASSERT(Palette);
1374 SURFACE_vSetPalette(Surface, Palette);
1375
1376 PALETTE_ShareUnlockPalette(Palette);
1377 SURFACE_ShareUnlockSurface(Surface);
1378 }
1379 else
1380 {
1381 /* Create a regular compatible bitmap, in the same format as the device */
1382 handle = IntCreateCompatibleBitmap(Dc, width, height, 0, 0);
1383 }
1384 }
1385 else
1386 {
1387 handle = GreCreateBitmap(width,
1388 height,
1389 1,
1390 1,
1391 NULL);
1392 }
1393
1394 if (height < 0)
1395 height = -height;
1396
1397 if ((NULL != handle) && (CBM_INIT & init))
1398 {
1399 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1400 }
1401
1402 return handle;
1403 }
1404
1405 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1406 // The DDB that is created will be whatever bit depth your reference DC is
1407 HBITMAP
1408 APIENTRY
1409 NtGdiCreateDIBitmapInternal(
1410 IN HDC hDc,
1411 IN INT cx,
1412 IN INT cy,
1413 IN DWORD fInit,
1414 IN OPTIONAL LPBYTE pjInit,
1415 IN OPTIONAL LPBITMAPINFO pbmi,
1416 IN DWORD iUsage,
1417 IN UINT cjMaxInitInfo,
1418 IN UINT cjMaxBits,
1419 IN FLONG fl,
1420 IN HANDLE hcmXform)
1421 {
1422 NTSTATUS Status = STATUS_SUCCESS;
1423 PBYTE safeBits = NULL;
1424 HBITMAP hbmResult = NULL;
1425
1426 if(pjInit && (fInit & CBM_INIT))
1427 {
1428 if (cjMaxBits == 0) return NULL;
1429 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1430 if(!safeBits)
1431 {
1432 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1433 return NULL;
1434 }
1435 }
1436
1437 _SEH2_TRY
1438 {
1439 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1440 if(pjInit && (fInit & CBM_INIT))
1441 {
1442 ProbeForRead(pjInit, cjMaxBits, 1);
1443 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1444 }
1445 }
1446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1447 {
1448 Status = _SEH2_GetExceptionCode();
1449 }
1450 _SEH2_END
1451
1452 if(!NT_SUCCESS(Status))
1453 {
1454 SetLastNtError(Status);
1455 goto cleanup;
1456 }
1457
1458 hbmResult = GreCreateDIBitmapInternal(hDc,
1459 cx,
1460 cy,
1461 fInit,
1462 safeBits,
1463 pbmi,
1464 iUsage,
1465 fl,
1466 cjMaxBits,
1467 hcmXform);
1468
1469 cleanup:
1470 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1471 return hbmResult;
1472 }
1473
1474 HBITMAP
1475 NTAPI
1476 GreCreateDIBitmapInternal(
1477 IN HDC hDc,
1478 IN INT cx,
1479 IN INT cy,
1480 IN DWORD fInit,
1481 IN OPTIONAL LPBYTE pjInit,
1482 IN OPTIONAL PBITMAPINFO pbmi,
1483 IN DWORD iUsage,
1484 IN FLONG fl,
1485 IN UINT cjMaxBits,
1486 IN HANDLE hcmXform)
1487 {
1488 PDC Dc;
1489 HBITMAP Bmp;
1490 USHORT bpp, planes;
1491 DWORD compression;
1492 HDC hdcDest;
1493
1494 if (!hDc) /* 1bpp monochrome bitmap */
1495 {
1496 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1497 hdcDest = NtGdiCreateCompatibleDC(0);
1498 if(!hdcDest)
1499 {
1500 return NULL;
1501 }
1502 }
1503 else
1504 {
1505 hdcDest = hDc;
1506 }
1507
1508 Dc = DC_LockDc(hdcDest);
1509 if (!Dc)
1510 {
1511 EngSetLastError(ERROR_INVALID_HANDLE);
1512 return NULL;
1513 }
1514 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1515 * if bpp != 1 and ignore the real value that was passed */
1516 if (pbmi)
1517 {
1518 if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1519 {
1520 BITMAPCOREHEADER* CoreHeader = (BITMAPCOREHEADER*)&pbmi->bmiHeader;
1521 bpp = CoreHeader->bcBitCount;
1522 planes = CoreHeader->bcPlanes ? CoreHeader->bcPlanes : 1;
1523 compression = BI_RGB;
1524 }
1525 else
1526 {
1527 bpp = pbmi->bmiHeader.biBitCount;
1528 planes = pbmi->bmiHeader.biPlanes ? pbmi->bmiHeader.biPlanes : 1;
1529 compression = pbmi->bmiHeader.biCompression;
1530 }
1531 }
1532 else
1533 {
1534 bpp = 0;
1535 planes = 0;
1536 compression = 0;
1537 }
1538 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, planes, compression, fInit, pjInit, pbmi, iUsage);
1539 DC_UnlockDc(Dc);
1540
1541 if(!hDc)
1542 {
1543 NtGdiDeleteObjectApp(hdcDest);
1544 }
1545 return Bmp;
1546 }
1547
1548
1549 HBITMAP
1550 APIENTRY
1551 NtGdiCreateDIBSection(
1552 IN HDC hDC,
1553 IN OPTIONAL HANDLE hSection,
1554 IN DWORD dwOffset,
1555 IN BITMAPINFO* bmi,
1556 IN DWORD Usage,
1557 IN UINT cjHeader,
1558 IN FLONG fl,
1559 IN ULONG_PTR dwColorSpace,
1560 OUT PVOID *Bits)
1561 {
1562 HBITMAP hbitmap = 0;
1563 DC *dc;
1564 BOOL bDesktopDC = FALSE;
1565 NTSTATUS Status = STATUS_SUCCESS;
1566
1567 if (!bmi) return hbitmap; // Make sure.
1568
1569 _SEH2_TRY
1570 {
1571 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1572 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1573 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1574 }
1575 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1576 {
1577 Status = _SEH2_GetExceptionCode();
1578 }
1579 _SEH2_END
1580
1581 if(!NT_SUCCESS(Status))
1582 {
1583 SetLastNtError(Status);
1584 return NULL;
1585 }
1586
1587 // If the reference hdc is null, take the desktop dc
1588 if (hDC == 0)
1589 {
1590 hDC = NtGdiCreateCompatibleDC(0);
1591 bDesktopDC = TRUE;
1592 }
1593
1594 if ((dc = DC_LockDc(hDC)))
1595 {
1596 hbitmap = DIB_CreateDIBSection(dc,
1597 bmi,
1598 Usage,
1599 Bits,
1600 hSection,
1601 dwOffset,
1602 0);
1603 DC_UnlockDc(dc);
1604 }
1605 else
1606 {
1607 EngSetLastError(ERROR_INVALID_HANDLE);
1608 }
1609
1610 if (bDesktopDC)
1611 NtGdiDeleteObjectApp(hDC);
1612
1613 return hbitmap;
1614 }
1615
1616 HBITMAP
1617 APIENTRY
1618 DIB_CreateDIBSection(
1619 PDC dc,
1620 CONST BITMAPINFO *bmi,
1621 UINT usage,
1622 LPVOID *bits,
1623 HANDLE section,
1624 DWORD offset,
1625 DWORD ovr_pitch)
1626 {
1627 HBITMAP res = 0;
1628 SURFACE *bmp = NULL;
1629 void *mapBits = NULL;
1630 PPALETTE ppalDIB = NULL;
1631
1632 // Fill BITMAP32 structure with DIB data
1633 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1634 INT effHeight;
1635 ULONG totalSize;
1636 BITMAP bm;
1637 //SIZEL Size;
1638 HANDLE hSecure;
1639
1640 DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
1641 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1642 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1643
1644 /* CreateDIBSection should fail for compressed formats */
1645 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1646 {
1647 DPRINT1("no compressed format allowed\n");
1648 return (HBITMAP)NULL;
1649 }
1650
1651 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1652 bm.bmType = 0;
1653 bm.bmWidth = bi->biWidth;
1654 bm.bmHeight = effHeight;
1655 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1656
1657 bm.bmPlanes = bi->biPlanes;
1658 bm.bmBitsPixel = bi->biBitCount;
1659 bm.bmBits = NULL;
1660
1661 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1662 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1663 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1664 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1665
1666 if (section)
1667 {
1668 SYSTEM_BASIC_INFORMATION Sbi;
1669 NTSTATUS Status;
1670 DWORD mapOffset;
1671 LARGE_INTEGER SectionOffset;
1672 SIZE_T mapSize;
1673
1674 Status = ZwQuerySystemInformation(SystemBasicInformation,
1675 &Sbi,
1676 sizeof Sbi,
1677 0);
1678 if (!NT_SUCCESS(Status))
1679 {
1680 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1681 return NULL;
1682 }
1683
1684 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1685 mapSize = bi->biSizeImage + (offset - mapOffset);
1686
1687 SectionOffset.LowPart = mapOffset;
1688 SectionOffset.HighPart = 0;
1689
1690 Status = ZwMapViewOfSection(section,
1691 NtCurrentProcess(),
1692 &mapBits,
1693 0,
1694 0,
1695 &SectionOffset,
1696 &mapSize,
1697 ViewShare,
1698 0,
1699 PAGE_READWRITE);
1700 if (!NT_SUCCESS(Status))
1701 {
1702 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1703 EngSetLastError(ERROR_INVALID_PARAMETER);
1704 return NULL;
1705 }
1706
1707 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1708 }
1709 else if (ovr_pitch && offset)
1710 bm.bmBits = (LPVOID) offset;
1711 else
1712 {
1713 offset = 0;
1714 bm.bmBits = EngAllocUserMem(totalSize, 0);
1715 if(!bm.bmBits)
1716 {
1717 DPRINT1("Failed to allocate memory\n");
1718 goto cleanup;
1719 }
1720 }
1721
1722 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1723 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1724
1725
1726 // Create Device Dependent Bitmap and add DIB pointer
1727 //Size.cx = bm.bmWidth;
1728 //Size.cy = abs(bm.bmHeight);
1729 res = GreCreateBitmapEx(bm.bmWidth,
1730 abs(bm.bmHeight),
1731 bm.bmWidthBytes,
1732 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1733 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1734 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1735 bi->biSizeImage,
1736 bm.bmBits,
1737 0);
1738 if (!res)
1739 {
1740 DPRINT1("GreCreateBitmapEx failed\n");
1741 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1742 goto cleanup;
1743 }
1744 bmp = SURFACE_ShareLockSurface(res); // HACK
1745 if (NULL == bmp)
1746 {
1747 DPRINT1("SURFACE_LockSurface failed\n");
1748 EngSetLastError(ERROR_INVALID_HANDLE);
1749 goto cleanup;
1750 }
1751
1752 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1753 table between the DIB and the X physical device. Obviously,
1754 this is left out of the ReactOS implementation. Instead,
1755 we call NtGdiSetDIBColorTable. */
1756 bmp->hDIBSection = section;
1757 bmp->hSecure = hSecure;
1758 bmp->dwOffset = offset;
1759 bmp->flags = API_BITMAP;
1760 bmp->biClrImportant = bi->biClrImportant;
1761
1762 /* Create a palette for the DIB */
1763 ppalDIB = CreateDIBPalette(bmi, dc, usage);
1764
1765 // Clean up in case of errors
1766 cleanup:
1767 if (!res || !bmp || !bm.bmBits || !ppalDIB)
1768 {
1769 DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1770 if (bm.bmBits)
1771 {
1772 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1773 if (section)
1774 {
1775 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1776 bm.bmBits = NULL;
1777 }
1778 else if (!offset)
1779 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1780 }
1781
1782 if (bmp)
1783 {
1784 SURFACE_ShareUnlockSurface(bmp);
1785 bmp = NULL;
1786 }
1787
1788 if (res)
1789 {
1790 GreDeleteObject(res);
1791 res = 0;
1792 }
1793
1794 if(ppalDIB)
1795 {
1796 PALETTE_ShareUnlockPalette(ppalDIB);
1797 }
1798 }
1799
1800 if (bmp)
1801 {
1802 /* If we're here, everything went fine */
1803 SURFACE_vSetPalette(bmp, ppalDIB);
1804 PALETTE_ShareUnlockPalette(ppalDIB);
1805 SURFACE_ShareUnlockSurface(bmp);
1806 }
1807
1808 // Return BITMAP handle and storage location
1809 if (NULL != bm.bmBits && NULL != bits)
1810 {
1811 *bits = bm.bmBits;
1812 }
1813
1814 return res;
1815 }
1816
1817 /***********************************************************************
1818 * DIB_GetBitmapInfo
1819 *
1820 * Get the info from a bitmap header.
1821 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1822 */
1823 int
1824 FASTCALL
1825 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1826 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1827 {
1828 if (header->biSize == sizeof(BITMAPCOREHEADER))
1829 {
1830 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1831 *width = core->bcWidth;
1832 *height = core->bcHeight;
1833 *planes = core->bcPlanes;
1834 *bpp = core->bcBitCount;
1835 *compr = BI_RGB;
1836 *size = 0;
1837 return 0;
1838 }
1839 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1840 {
1841 *width = header->biWidth;
1842 *height = header->biHeight;
1843 *planes = header->biPlanes;
1844 *bpp = header->biBitCount;
1845 *compr = header->biCompression;
1846 *size = header->biSizeImage;
1847 return 1;
1848 }
1849 DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
1850 return -1;
1851 }
1852
1853 /***********************************************************************
1854 * DIB_GetDIBImageBytes
1855 *
1856 * Return the number of bytes used to hold the image in a DIB bitmap.
1857 * 11/16/1999 (RJJ) lifted from wine
1858 */
1859
1860 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1861 {
1862 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1863 }
1864
1865 /***********************************************************************
1866 * DIB_BitmapInfoSize
1867 *
1868 * Return the size of the bitmap info structure including color table.
1869 * 11/16/1999 (RJJ) lifted from wine
1870 */
1871
1872 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1873 {
1874 unsigned int colors, size, masks = 0;
1875
1876 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1877 {
1878 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1879 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1880 return sizeof(BITMAPCOREHEADER) + colors *
1881 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1882 }
1883 else /* Assume BITMAPINFOHEADER */
1884 {
1885 colors = info->bmiHeader.biClrUsed;
1886 if (colors > 256) colors = 256;
1887 if (!colors && (info->bmiHeader.biBitCount <= 8))
1888 colors = 1 << info->bmiHeader.biBitCount;
1889 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1890 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1891 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1892 }
1893 }
1894
1895 HPALETTE
1896 FASTCALL
1897 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
1898 {
1899 PPALETTE ppalNew;
1900 ULONG nNumColors,i;
1901 USHORT *lpIndex;
1902 HPALETTE hpal;
1903
1904 if (!(ppalDc->flFlags & PAL_INDEXED))
1905 {
1906 return NULL;
1907 }
1908
1909 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1910 if (lpbmi->bmiHeader.biClrUsed)
1911 {
1912 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1913 }
1914
1915 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
1916 if (ppalNew == NULL)
1917 {
1918 DPRINT1("Could not allocate palette\n");
1919 return NULL;
1920 }
1921
1922 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1923
1924 for (i = 0; i < nNumColors; i++)
1925 {
1926 ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
1927 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
1928 lpIndex++;
1929 }
1930
1931 hpal = ppalNew->BaseObject.hHmgr;
1932 PALETTE_UnlockPalette(ppalNew);
1933
1934 return hpal;
1935 }
1936
1937 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1938 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1939 BITMAPINFO*
1940 FASTCALL
1941 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1942 {
1943 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1944 BITMAPINFO* pNewBmi ;
1945 UINT numColors = 0, ColorsSize = 0;
1946
1947 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1948 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1949
1950 if(pbmci->bmciHeader.bcBitCount <= 8)
1951 {
1952 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1953 if(Usage == DIB_PAL_COLORS)
1954 {
1955 ColorsSize = numColors * sizeof(WORD);
1956 }
1957 else
1958 {
1959 ColorsSize = numColors * sizeof(RGBQUAD);
1960 }
1961 }
1962 else if (Usage == DIB_PAL_COLORS)
1963 {
1964 /* Invalid at high-res */
1965 return NULL;
1966 }
1967
1968 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1969 if(!pNewBmi) return NULL;
1970
1971 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1972
1973 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1974 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1975 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1976 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1977 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1978 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1979 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1980 pNewBmi->bmiHeader.biHeight,
1981 pNewBmi->bmiHeader.biBitCount);
1982
1983 if(Usage == DIB_PAL_COLORS)
1984 {
1985 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1986 }
1987 else
1988 {
1989 UINT i;
1990 for(i=0; i<numColors; i++)
1991 {
1992 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1993 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1994 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1995 }
1996 }
1997
1998 return pNewBmi ;
1999 }
2000
2001 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
2002 VOID
2003 FASTCALL
2004 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
2005 {
2006 BITMAPCOREINFO* pbmci;
2007 if(converted == orig)
2008 return;
2009
2010 if(usage == -1)
2011 {
2012 /* Caller don't want any conversion */
2013 ExFreePoolWithTag(converted, TAG_DIB);
2014 return;
2015 }
2016
2017 /* Perform inverse conversion */
2018 pbmci = (BITMAPCOREINFO*)orig;
2019
2020 ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
2021 pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
2022 pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
2023 pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
2024 pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
2025
2026 if(pbmci->bmciHeader.bcBitCount <= 8)
2027 {
2028 UINT numColors = converted->bmiHeader.biClrUsed;
2029 if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
2030 if(usage == DIB_PAL_COLORS)
2031 {
2032 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
2033 RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
2034 }
2035 else
2036 {
2037 UINT i;
2038 RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
2039 for(i=0; i<numColors; i++)
2040 {
2041 pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
2042 pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
2043 pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
2044 }
2045 }
2046 }
2047 /* Now free it, it's not needed anymore */
2048 ExFreePoolWithTag(converted, TAG_DIB);
2049 }
2050
2051 /* EOF */