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