[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 srcPoint.y = height < 0 ?
944 psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines) : StartScan;
945
946 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
947
948 ret = IntEngCopyBits(&psurfDest->SurfObj,
949 &psurf->SurfObj,
950 NULL,
951 &exlo.xlo,
952 &rcDest,
953 &srcPoint);
954
955 SURFACE_ShareUnlockSurface(psurfDest);
956
957 if(!ret)
958 ScanLines = 0;
959 else
960 {
961 Status = STATUS_SUCCESS;
962 _SEH2_TRY
963 {
964 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
965 }
966 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
967 {
968 Status = _SEH2_GetExceptionCode();
969 }
970 _SEH2_END
971
972 if(!NT_SUCCESS(Status))
973 {
974 DPRINT1("Unable to copy bits to the user provided pointer\n");
975 ScanLines = 0;
976 }
977 }
978
979 GreDeleteObject(hBmpDest);
980 EXLATEOBJ_vCleanup(&exlo);
981 }
982 else ScanLines = abs(height);
983
984 done:
985
986 if(pDC) DC_UnlockDc(pDC);
987 if(psurf) SURFACE_ShareUnlockSurface(psurf);
988 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
989
990 return ScanLines;
991 }
992
993
994 INT
995 APIENTRY
996 NtGdiStretchDIBitsInternal(
997 HDC hDC,
998 INT XDest,
999 INT YDest,
1000 INT DestWidth,
1001 INT DestHeight,
1002 INT XSrc,
1003 INT YSrc,
1004 INT SrcWidth,
1005 INT SrcHeight,
1006 LPBYTE Bits,
1007 LPBITMAPINFO BitsInfo,
1008 DWORD Usage,
1009 DWORD ROP,
1010 UINT cjMaxInfo,
1011 UINT cjMaxBits,
1012 HANDLE hcmXform)
1013 {
1014 PDC pdc;
1015 INT ret = 0;
1016 LONG height;
1017 LONG width;
1018 WORD planes, bpp;
1019 DWORD compr, size;
1020 HBITMAP hBitmap;
1021 HBITMAP hOldBitmap;
1022 HDC hdcMem;
1023 PVOID pvBits;
1024 PBYTE safeBits;
1025
1026 if (!Bits || !BitsInfo)
1027 return 0;
1028
1029 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1030 if(!safeBits)
1031 {
1032 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1033 return 0;
1034 }
1035
1036 _SEH2_TRY
1037 {
1038 ProbeForRead(BitsInfo, cjMaxInfo, 1);
1039 ProbeForRead(Bits, cjMaxBits, 1);
1040 if (DIB_GetBitmapInfo(&BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size) == -1)
1041 {
1042 DPRINT1("Invalid bitmap\n");
1043 _SEH2_YIELD(goto cleanup;)
1044 }
1045 RtlCopyMemory(safeBits, Bits, cjMaxBits);
1046 }
1047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1048 {
1049 DPRINT1("Error, failed to read the DIB bits\n");
1050 _SEH2_YIELD(goto cleanup;)
1051 }
1052 _SEH2_END
1053
1054 if (width < 0)
1055 {
1056 DPRINT1("Bitmap has a negative width\n");
1057 return 0;
1058 }
1059
1060 hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
1061
1062 if (!(pdc = DC_LockDc(hDC)))
1063 {
1064 ExFreePoolWithTag(safeBits, TAG_DIB);
1065 EngSetLastError(ERROR_INVALID_HANDLE);
1066 return 0;
1067 }
1068
1069 if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
1070 DestWidth == SrcWidth && DestHeight == SrcHeight &&
1071 compr == BI_RGB &&
1072 ROP == SRCCOPY)
1073 {
1074 BITMAP bmp;
1075 ret = IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp);
1076 if (ret &&
1077 bmp.bmBitsPixel == bpp &&
1078 bmp.bmWidth == SrcWidth &&
1079 bmp.bmHeight == SrcHeight &&
1080 bmp.bmPlanes == planes)
1081 {
1082 /* fast path */
1083 ret = IntSetDIBits(pdc, hBitmap, 0, height, safeBits, BitsInfo, Usage);
1084 DC_UnlockDc(pdc);
1085 goto cleanup;
1086 }
1087 }
1088
1089 /* slow path - need to use StretchBlt */
1090
1091 hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
1092 DC_UnlockDc(pdc);
1093
1094 if(!hBitmap)
1095 {
1096 DPRINT1("Error, failed to create a DIB section\n");
1097 goto cleanup;
1098 }
1099
1100 hdcMem = NtGdiCreateCompatibleDC(hDC);
1101
1102 RtlCopyMemory(pvBits, safeBits, cjMaxBits);
1103 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
1104
1105 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
1106 left (negative biHeight) */
1107 ret = NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1108 hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
1109 SrcWidth, SrcHeight, ROP, 0);
1110
1111 if(ret)
1112 ret = SrcHeight;
1113 NtGdiSelectBitmap(hdcMem, hOldBitmap);
1114 NtGdiDeleteObjectApp(hdcMem);
1115 GreDeleteObject(hBitmap);
1116
1117 cleanup:
1118 ExFreePoolWithTag(safeBits, TAG_DIB);
1119 return ret;
1120 }
1121
1122
1123 HBITMAP
1124 FASTCALL
1125 IntCreateDIBitmap(
1126 PDC Dc,
1127 INT width,
1128 INT height,
1129 UINT bpp,
1130 DWORD init,
1131 LPBYTE bits,
1132 PBITMAPINFO data,
1133 DWORD coloruse)
1134 {
1135 HBITMAP handle;
1136 BOOL fColor;
1137
1138 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1139 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1140
1141 if (bpp != 1) fColor = TRUE;
1142 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1143 else
1144 {
1145 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1146 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1147
1148 // Check if the first color of the colormap is black
1149 if ((col == RGB(0, 0, 0)))
1150 {
1151 rgb++;
1152 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1153
1154 // If the second color is white, create a monochrome bitmap
1155 fColor = (col != RGB(0xff,0xff,0xff));
1156 }
1157 else fColor = TRUE;
1158 }
1159
1160 // Now create the bitmap
1161 if (fColor)
1162 {
1163 handle = IntCreateCompatibleBitmap(Dc, width, height);
1164 }
1165 else
1166 {
1167 handle = GreCreateBitmap(width,
1168 height,
1169 1,
1170 1,
1171 NULL);
1172 }
1173
1174 if (height < 0)
1175 height = -height;
1176
1177 if (NULL != handle && CBM_INIT == init)
1178 {
1179 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1180 }
1181
1182 return handle;
1183 }
1184
1185 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1186 // The DDB that is created will be whatever bit depth your reference DC is
1187 HBITMAP
1188 APIENTRY
1189 NtGdiCreateDIBitmapInternal(
1190 IN HDC hDc,
1191 IN INT cx,
1192 IN INT cy,
1193 IN DWORD fInit,
1194 IN OPTIONAL LPBYTE pjInit,
1195 IN OPTIONAL LPBITMAPINFO pbmi,
1196 IN DWORD iUsage,
1197 IN UINT cjMaxInitInfo,
1198 IN UINT cjMaxBits,
1199 IN FLONG fl,
1200 IN HANDLE hcmXform)
1201 {
1202 NTSTATUS Status = STATUS_SUCCESS;
1203 PBYTE safeBits = NULL;
1204 HBITMAP hbmResult = NULL;
1205
1206 if(pjInit && (fInit == CBM_INIT))
1207 {
1208 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1209 if(!safeBits)
1210 {
1211 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1212 return NULL;
1213 }
1214 }
1215
1216 _SEH2_TRY
1217 {
1218 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1219 if(pjInit && (fInit == CBM_INIT))
1220 {
1221 ProbeForRead(pjInit, cjMaxBits, 1);
1222 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1223 }
1224 }
1225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1226 {
1227 Status = _SEH2_GetExceptionCode();
1228 }
1229 _SEH2_END
1230
1231 if(!NT_SUCCESS(Status))
1232 {
1233 SetLastNtError(Status);
1234 goto cleanup;
1235 }
1236
1237 hbmResult = GreCreateDIBitmapInternal(hDc,
1238 cx,
1239 cy,
1240 fInit,
1241 safeBits,
1242 pbmi,
1243 iUsage,
1244 fl,
1245 hcmXform);
1246
1247 cleanup:
1248 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1249 return hbmResult;
1250 }
1251
1252 HBITMAP
1253 FASTCALL
1254 GreCreateDIBitmapInternal(
1255 IN HDC hDc,
1256 IN INT cx,
1257 IN INT cy,
1258 IN DWORD fInit,
1259 IN OPTIONAL LPBYTE pjInit,
1260 IN OPTIONAL PBITMAPINFO pbmi,
1261 IN DWORD iUsage,
1262 IN FLONG fl,
1263 IN HANDLE hcmXform)
1264 {
1265 PDC Dc;
1266 HBITMAP Bmp;
1267 WORD bpp;
1268 HDC hdcDest;
1269
1270 if (!hDc) /* 1bpp monochrome bitmap */
1271 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1272 hdcDest = NtGdiCreateCompatibleDC(0);
1273 if(!hdcDest)
1274 {
1275 return NULL;
1276 }
1277 }
1278 else
1279 {
1280 hdcDest = hDc;
1281 }
1282
1283 Dc = DC_LockDc(hdcDest);
1284 if (!Dc)
1285 {
1286 EngSetLastError(ERROR_INVALID_HANDLE);
1287 return NULL;
1288 }
1289 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1290 * if bpp != 1 and ignore the real value that was passed */
1291 if (pbmi)
1292 bpp = pbmi->bmiHeader.biBitCount;
1293 else
1294 bpp = 0;
1295 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1296 DC_UnlockDc(Dc);
1297
1298 if(!hDc)
1299 {
1300 NtGdiDeleteObjectApp(hdcDest);
1301 }
1302 return Bmp;
1303 }
1304
1305
1306 HBITMAP
1307 APIENTRY
1308 NtGdiCreateDIBSection(
1309 IN HDC hDC,
1310 IN OPTIONAL HANDLE hSection,
1311 IN DWORD dwOffset,
1312 IN BITMAPINFO* bmi,
1313 IN DWORD Usage,
1314 IN UINT cjHeader,
1315 IN FLONG fl,
1316 IN ULONG_PTR dwColorSpace,
1317 OUT PVOID *Bits)
1318 {
1319 HBITMAP hbitmap = 0;
1320 DC *dc;
1321 BOOL bDesktopDC = FALSE;
1322 NTSTATUS Status = STATUS_SUCCESS;
1323
1324 if (!bmi) return hbitmap; // Make sure.
1325
1326 _SEH2_TRY
1327 {
1328 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1329 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1330 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
1331 }
1332 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1333 {
1334 Status = _SEH2_GetExceptionCode();
1335 }
1336 _SEH2_END
1337
1338 if(!NT_SUCCESS(Status))
1339 {
1340 SetLastNtError(Status);
1341 return NULL;
1342 }
1343
1344 // If the reference hdc is null, take the desktop dc
1345 if (hDC == 0)
1346 {
1347 hDC = NtGdiCreateCompatibleDC(0);
1348 bDesktopDC = TRUE;
1349 }
1350
1351 if ((dc = DC_LockDc(hDC)))
1352 {
1353 hbitmap = DIB_CreateDIBSection(dc,
1354 bmi,
1355 Usage,
1356 Bits,
1357 hSection,
1358 dwOffset,
1359 0);
1360 DC_UnlockDc(dc);
1361 }
1362 else
1363 {
1364 EngSetLastError(ERROR_INVALID_HANDLE);
1365 }
1366
1367 if (bDesktopDC)
1368 NtGdiDeleteObjectApp(hDC);
1369
1370 return hbitmap;
1371 }
1372
1373 HBITMAP
1374 APIENTRY
1375 DIB_CreateDIBSection(
1376 PDC dc,
1377 CONST BITMAPINFO *bmi,
1378 UINT usage,
1379 LPVOID *bits,
1380 HANDLE section,
1381 DWORD offset,
1382 DWORD ovr_pitch)
1383 {
1384 HBITMAP res = 0;
1385 SURFACE *bmp = NULL;
1386 void *mapBits = NULL;
1387 HPALETTE hpal ;
1388
1389 // Fill BITMAP32 structure with DIB data
1390 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1391 INT effHeight;
1392 ULONG totalSize;
1393 BITMAP bm;
1394 SIZEL Size;
1395 HANDLE hSecure;
1396
1397 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1398 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1399 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1400
1401 /* CreateDIBSection should fail for compressed formats */
1402 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1403 {
1404 return (HBITMAP)NULL;
1405 }
1406
1407 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1408 bm.bmType = 0;
1409 bm.bmWidth = bi->biWidth;
1410 bm.bmHeight = effHeight;
1411 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1412
1413 bm.bmPlanes = bi->biPlanes;
1414 bm.bmBitsPixel = bi->biBitCount;
1415 bm.bmBits = NULL;
1416
1417 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1418 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1419 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1420 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1421
1422 if (section)
1423 {
1424 SYSTEM_BASIC_INFORMATION Sbi;
1425 NTSTATUS Status;
1426 DWORD mapOffset;
1427 LARGE_INTEGER SectionOffset;
1428 SIZE_T mapSize;
1429
1430 Status = ZwQuerySystemInformation(SystemBasicInformation,
1431 &Sbi,
1432 sizeof Sbi,
1433 0);
1434 if (!NT_SUCCESS(Status))
1435 {
1436 return NULL;
1437 }
1438
1439 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1440 mapSize = bi->biSizeImage + (offset - mapOffset);
1441
1442 SectionOffset.LowPart = mapOffset;
1443 SectionOffset.HighPart = 0;
1444
1445 Status = ZwMapViewOfSection(section,
1446 NtCurrentProcess(),
1447 &mapBits,
1448 0,
1449 0,
1450 &SectionOffset,
1451 &mapSize,
1452 ViewShare,
1453 0,
1454 PAGE_READWRITE);
1455 if (!NT_SUCCESS(Status))
1456 {
1457 EngSetLastError(ERROR_INVALID_PARAMETER);
1458 return NULL;
1459 }
1460
1461 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1462 }
1463 else if (ovr_pitch && offset)
1464 bm.bmBits = (LPVOID) offset;
1465 else
1466 {
1467 offset = 0;
1468 bm.bmBits = EngAllocUserMem(totalSize, 0);
1469 if(!bm.bmBits) goto cleanup;
1470 }
1471
1472 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1473 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1474
1475 if (usage == DIB_PAL_COLORS)
1476 {
1477 if(dc)
1478 {
1479 PPALETTE pdcPal ;
1480 pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
1481 hpal = DIB_MapPaletteColors(pdcPal, bmi);
1482 PALETTE_UnlockPalette(pdcPal);
1483 }
1484 else
1485 {
1486 /* For DIB Brushes */
1487 DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
1488 /* HACK */
1489 hpal = (HPALETTE) 0xFFFFFFFF;
1490 }
1491 }
1492 else
1493 {
1494 hpal = BuildDIBPalette(bmi);
1495 }
1496
1497 if(!hpal)
1498 {
1499 DPRINT1("Error : Could not create a palette for the DIB.\n");
1500 goto cleanup;
1501 }
1502
1503 // Create Device Dependent Bitmap and add DIB pointer
1504 Size.cx = bm.bmWidth;
1505 Size.cy = abs(bm.bmHeight);
1506 res = GreCreateBitmapEx(bm.bmWidth,
1507 abs(bm.bmHeight),
1508 bm.bmWidthBytes,
1509 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1510 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1511 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1512 bi->biSizeImage,
1513 bm.bmBits,
1514 0);
1515 if (!res)
1516 {
1517 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1518 goto cleanup;
1519 }
1520 bmp = SURFACE_LockSurface(res);
1521 if (NULL == bmp)
1522 {
1523 EngSetLastError(ERROR_INVALID_HANDLE);
1524 goto cleanup;
1525 }
1526
1527 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1528 table between the DIB and the X physical device. Obviously,
1529 this is left out of the ReactOS implementation. Instead,
1530 we call NtGdiSetDIBColorTable. */
1531 bmp->hDIBSection = section;
1532 bmp->hSecure = hSecure;
1533 bmp->dwOffset = offset;
1534 bmp->flags = API_BITMAP;
1535 bmp->biClrImportant = bi->biClrImportant;
1536 bmp->SurfObj.fjBitmap &= ~BMF_DONT_FREE;
1537
1538 /* HACK */
1539 if(hpal != (HPALETTE)0xFFFFFFFF)
1540 {
1541 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1542 /* Lazy delete hpal, it will be freed at surface release */
1543 GreDeleteObject(hpal);
1544 }
1545
1546 // Clean up in case of errors
1547 cleanup:
1548 if (!res || !bmp || !bm.bmBits)
1549 {
1550 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1551 if (bm.bmBits)
1552 {
1553 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1554 if (section)
1555 {
1556 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1557 bm.bmBits = NULL;
1558 }
1559 else
1560 if (!offset)
1561 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1562 }
1563
1564 if (bmp)
1565 bmp = NULL;
1566
1567 if (res)
1568 {
1569 SURFACE_FreeSurfaceByHandle(res);
1570 res = 0;
1571 }
1572 }
1573
1574 if (bmp)
1575 {
1576 SURFACE_UnlockSurface(bmp);
1577 }
1578
1579 // Return BITMAP handle and storage location
1580 if (NULL != bm.bmBits && NULL != bits)
1581 {
1582 *bits = bm.bmBits;
1583 }
1584
1585 return res;
1586 }
1587
1588 /***********************************************************************
1589 * DIB_GetBitmapInfo
1590 *
1591 * Get the info from a bitmap header.
1592 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1593 */
1594 int
1595 FASTCALL
1596 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1597 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1598 {
1599 if (header->biSize == sizeof(BITMAPCOREHEADER))
1600 {
1601 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1602 *width = core->bcWidth;
1603 *height = core->bcHeight;
1604 *planes = core->bcPlanes;
1605 *bpp = core->bcBitCount;
1606 *compr = BI_RGB;
1607 *size = 0;
1608 return 0;
1609 }
1610 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
1611 {
1612 *width = header->biWidth;
1613 *height = header->biHeight;
1614 *planes = header->biPlanes;
1615 *bpp = header->biBitCount;
1616 *compr = header->biCompression;
1617 *size = header->biSizeImage;
1618 return 1;
1619 }
1620 DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
1621 return -1;
1622 }
1623
1624 /***********************************************************************
1625 * DIB_GetDIBImageBytes
1626 *
1627 * Return the number of bytes used to hold the image in a DIB bitmap.
1628 * 11/16/1999 (RJJ) lifted from wine
1629 */
1630
1631 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1632 {
1633 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1634 }
1635
1636 /***********************************************************************
1637 * DIB_BitmapInfoSize
1638 *
1639 * Return the size of the bitmap info structure including color table.
1640 * 11/16/1999 (RJJ) lifted from wine
1641 */
1642
1643 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1644 {
1645 unsigned int colors, size, masks = 0;
1646
1647 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1648 {
1649 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1650 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1651 return sizeof(BITMAPCOREHEADER) + colors *
1652 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1653 }
1654 else /* assume BITMAPINFOHEADER */
1655 {
1656 colors = info->bmiHeader.biClrUsed;
1657 if (colors > 256) colors = 256;
1658 if (!colors && (info->bmiHeader.biBitCount <= 8))
1659 colors = 1 << info->bmiHeader.biBitCount;
1660 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1661 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1662 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1663 }
1664 }
1665
1666 HPALETTE
1667 FASTCALL
1668 DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
1669 {
1670 PALETTEENTRY* ppalEntries;
1671 ULONG nNumColors,i;
1672 USHORT *lpIndex;
1673 HPALETTE hpal;
1674
1675 if (!(ppal->flFlags & PAL_INDEXED))
1676 {
1677 return NULL;
1678 }
1679
1680 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1681 if (lpbmi->bmiHeader.biClrUsed)
1682 {
1683 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1684 }
1685
1686 /* Don't have more colors than we need */
1687 nNumColors = min(ppal->NumColors, nNumColors);
1688
1689 ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
1690 if (ppalEntries == NULL)
1691 {
1692 DPRINT1("Could not allocate palette entries\n");
1693 return NULL;
1694 }
1695
1696 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1697
1698 for (i = 0; i < nNumColors; i++)
1699 {
1700 if (*lpIndex < ppal->NumColors)
1701 {
1702 ppalEntries[i] = ppal->IndexedColors[*lpIndex];
1703 }
1704 else
1705 {
1706 ppalEntries[i].peRed = 0;
1707 ppalEntries[i].peGreen = 0;
1708 ppalEntries[i].peBlue = 0;
1709 ppalEntries[i].peFlags = 0;
1710 }
1711
1712 lpIndex++;
1713 }
1714
1715 hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
1716
1717 ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
1718
1719 return hpal;
1720 }
1721
1722 HPALETTE
1723 FASTCALL
1724 BuildDIBPalette(CONST BITMAPINFO *bmi)
1725 {
1726 BYTE bits;
1727 ULONG ColorCount;
1728 HPALETTE hPal;
1729 ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
1730 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1731 INT paletteType;
1732
1733 // Determine Bits Per Pixel
1734 bits = bmi->bmiHeader.biBitCount;
1735
1736 // Determine paletteType from Bits Per Pixel
1737 if (bits <= 8)
1738 {
1739 paletteType = PAL_INDEXED;
1740 RedMask = GreenMask = BlueMask = 0;
1741 }
1742 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1743 {
1744 paletteType = PAL_BITFIELDS;
1745 if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
1746 {
1747 PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
1748 RedMask = pV4Header->bV4RedMask;
1749 GreenMask = pV4Header->bV4GreenMask;
1750 BlueMask = pV4Header->bV4BlueMask;
1751 }
1752 else
1753 {
1754 RedMask = pdwColors[0];
1755 GreenMask = pdwColors[1];
1756 BlueMask = pdwColors[2];
1757 }
1758 }
1759 else
1760 {
1761 paletteType = PAL_BITFIELDS;
1762 switch (bits)
1763 {
1764 case 16:
1765 paletteType |= PAL_RGB16_555;
1766 RedMask = 0x7C00;
1767 GreenMask = 0x03E0;
1768 BlueMask = 0x001F;
1769 break;
1770
1771 case 24:
1772 case 32:
1773 paletteType |= PAL_BGR;
1774 RedMask = 0xFF0000;
1775 GreenMask = 0x00FF00;
1776 BlueMask = 0x0000FF;
1777 break;
1778 }
1779 }
1780
1781 if (bmi->bmiHeader.biClrUsed == 0)
1782 {
1783 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1784 }
1785 else
1786 {
1787 ColorCount = bmi->bmiHeader.biClrUsed;
1788 }
1789
1790 if (PAL_INDEXED == paletteType)
1791 {
1792 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1793 }
1794 else
1795 {
1796 hPal = PALETTE_AllocPalette(paletteType, 0,
1797 NULL,
1798 RedMask, GreenMask, BlueMask);
1799 }
1800
1801 return hPal;
1802 }
1803
1804 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1805 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1806 BITMAPINFO*
1807 FASTCALL
1808 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1809 {
1810 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1811 BITMAPINFO* pNewBmi ;
1812 UINT numColors = 0, ColorsSize = 0;
1813
1814 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1815 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1816
1817 if(pbmci->bmciHeader.bcBitCount <= 8)
1818 {
1819 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1820 if(Usage == DIB_PAL_COLORS)
1821 {
1822 ColorsSize = numColors * sizeof(WORD);
1823 }
1824 else
1825 {
1826 ColorsSize = numColors * sizeof(RGBQUAD);
1827 }
1828 }
1829 else if (Usage == DIB_PAL_COLORS)
1830 {
1831 /* Invalid at high Res */
1832 return NULL;
1833 }
1834
1835 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1836 if(!pNewBmi) return NULL;
1837
1838 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1839
1840 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1841 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1842 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1843 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1844 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1845 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1846 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1847 pNewBmi->bmiHeader.biHeight,
1848 pNewBmi->bmiHeader.biBitCount);
1849
1850 if(Usage == DIB_PAL_COLORS)
1851 {
1852 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1853 }
1854 else
1855 {
1856 UINT i;
1857 for(i=0; i<numColors; i++)
1858 {
1859 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1860 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1861 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1862 }
1863 }
1864
1865 return pNewBmi ;
1866 }
1867
1868 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
1869 VOID
1870 FASTCALL
1871 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
1872 {
1873 if(converted != orig)
1874 ExFreePoolWithTag(converted, TAG_DIB);
1875 }
1876
1877
1878
1879
1880
1881
1882 /* EOF */