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