[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / dclife.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: subsystem/win32/win32k/objects/dclife.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <win32k.h>
10 #include <bugcodes.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 //FIXME: windows uses 0x0012009f
16 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
17
18 PSURFACE psurfDefaultBitmap = NULL;
19 PBRUSH pbrDefaultBrush = NULL;
20
21 // FIXME: these should go to floatobj.h or something
22 #define FLOATOBJ_0 {0x00000000, 0x00000000}
23 #define FLOATOBJ_1 {0x40000000, 0x00000002}
24 #define FLOATOBJ_16 {0x40000000, 0x00000006}
25 #define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
26
27 static const FLOATOBJ gef0 = FLOATOBJ_0;
28 static const FLOATOBJ gef1 = FLOATOBJ_1;
29 static const FLOATOBJ gef16 = FLOATOBJ_16;
30
31 static const MATRIX gmxWorldToDeviceDefault =
32 {
33 FLOATOBJ_16, FLOATOBJ_0,
34 FLOATOBJ_0, FLOATOBJ_16,
35 FLOATOBJ_0, FLOATOBJ_0,
36 0, 0, 0x4b
37 };
38
39 static const MATRIX gmxDeviceToWorldDefault =
40 {
41 FLOATOBJ_1_16, FLOATOBJ_0,
42 FLOATOBJ_0, FLOATOBJ_1_16,
43 FLOATOBJ_0, FLOATOBJ_0,
44 0, 0, 0x53
45 };
46
47 static const MATRIX gmxWorldToPageDefault =
48 {
49 FLOATOBJ_1, FLOATOBJ_0,
50 FLOATOBJ_0, FLOATOBJ_1,
51 FLOATOBJ_0, FLOATOBJ_0,
52 0, 0, 0x63
53 };
54
55 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
56 #define gmxWorldToDeviceDefault gmxWorldToPageDefault
57 #define gmxDeviceToWorldDefault gmxWorldToPageDefault
58
59 /** Internal functions ********************************************************/
60
61 INIT_FUNCTION
62 NTSTATUS
63 NTAPI
64 InitDcImpl()
65 {
66 psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
67 if (!psurfDefaultBitmap)
68 return STATUS_UNSUCCESSFUL;
69
70 pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]);
71 if (!pbrDefaultBrush)
72 return STATUS_UNSUCCESSFUL;
73
74 return STATUS_SUCCESS;
75 }
76
77
78 PDC
79 NTAPI
80 DC_AllocDcWithHandle()
81 {
82 PDC pdc;
83 pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
84
85 pdc->pdcattr = &pdc->dcattr;
86
87 return pdc;
88 }
89
90
91 void
92 DC_InitHack(PDC pdc)
93 {
94 TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
95 pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
96
97 /* This should never fail */
98 ASSERT(pdc->dclevel.ppal);
99
100 /* Select regions */
101 pdc->rosdc.hClipRgn = NULL;
102 pdc->rosdc.hGCClipRgn = NULL;
103 }
104
105 VOID
106 NTAPI
107 DC_vInitDc(
108 PDC pdc,
109 DCTYPE dctype,
110 PPDEVOBJ ppdev)
111 {
112 /* Setup some basic fields */
113 pdc->dctype = dctype;
114 pdc->ppdev = ppdev;
115 pdc->dhpdev = ppdev->dhpdev;
116 pdc->hsem = ppdev->hsemDevLock;
117 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
118 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
119 pdc->fs = DC_DIRTY_RAO;
120
121 /* Setup dc attribute */
122 pdc->pdcattr = &pdc->dcattr;
123 pdc->dcattr.pvLDC = NULL;
124 pdc->dcattr.ulDirty_ = DIRTY_DEFAULT;
125 if (ppdev == gppdevPrimary)
126 pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY;
127
128 /* Setup the DC size */
129 if (dctype == DCTYPE_MEMORY)
130 {
131 /* Memory DCs have a 1 x 1 bitmap by default */
132 pdc->dclevel.sizl.cx = 1;
133 pdc->dclevel.sizl.cy = 1;
134 }
135 else
136 {
137 /* Other DC's are as big as the related PDEV */
138 pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes;
139 pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes;
140 }
141
142 /* Setup Window rect based on DC size */
143 pdc->erclWindow.left = 0;
144 pdc->erclWindow.top = 0;
145 pdc->erclWindow.right = pdc->dclevel.sizl.cx;
146 pdc->erclWindow.bottom = pdc->dclevel.sizl.cy;
147
148 if (dctype == DCTYPE_DIRECT)
149 {
150 /* Direct DCs get the surface from the PDEV */
151 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
152
153 pdc->erclBounds.left = 0x7fffffff;
154 pdc->erclBounds.top = 0x7fffffff;
155 pdc->erclBounds.right = 0x80000000;
156 pdc->erclBounds.bottom = 0x80000000;
157 pdc->erclBoundsApp.left = 0xffffffff;
158 pdc->erclBoundsApp.top = 0xfffffffc;
159 pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
160 pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
161 pdc->erclClip = pdc->erclBounds;
162 // pdc->co
163
164 pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
165 }
166 else
167 {
168 /* Non-direct DCs don't have a surface by default */
169 pdc->dclevel.pSurface = NULL;
170
171 // FIXME: HACK, because our code expects a surface
172 pdc->dclevel.pSurface = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
173
174 pdc->erclBounds.left = 0;
175 pdc->erclBounds.top = 0;
176 pdc->erclBounds.right = 0;
177 pdc->erclBounds.bottom = 0;
178 pdc->erclBoundsApp = pdc->erclBounds;
179 pdc->erclClip = pdc->erclWindow;
180 // pdc->co = NULL
181 }
182
183 // pdc->dcattr.VisRectRegion:
184
185 /* Setup coordinate transformation data */
186 pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault;
187 pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault;
188 pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault;
189 pdc->dclevel.efM11PtoD = gef16;
190 pdc->dclevel.efM22PtoD = gef16;
191 pdc->dclevel.efDxPtoD = gef0;
192 pdc->dclevel.efDyPtoD = gef0;
193 pdc->dclevel.efM11_TWIPS = gef0;
194 pdc->dclevel.efM22_TWIPS = gef0;
195 pdc->dclevel.efPr11 = gef0;
196 pdc->dclevel.efPr22 = gef0;
197 pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice;
198 pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld;
199 pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage;
200 pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD;
201 pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD;
202 pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD;
203 pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD;
204 pdc->dcattr.iMapMode = MM_TEXT;
205 pdc->dcattr.dwLayout = 0;
206 pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY |
207 PAGE_TO_DEVICE_IDENTITY |
208 WORLD_TO_PAGE_IDENTITY;
209
210 /* Setup more coordinates */
211 pdc->ptlDCOrig.x = 0;
212 pdc->ptlDCOrig.y = 0;
213 pdc->dcattr.lWindowOrgx = 0;
214 pdc->dcattr.ptlWindowOrg.x = 0;
215 pdc->dcattr.ptlWindowOrg.y = 0;
216 pdc->dcattr.szlWindowExt.cx = 1;
217 pdc->dcattr.szlWindowExt.cy = 1;
218 pdc->dcattr.ptlViewportOrg.x = 0;
219 pdc->dcattr.ptlViewportOrg.y = 0;
220 pdc->dcattr.szlViewportExt.cx = 1;
221 pdc->dcattr.szlViewportExt.cy = 1;
222 pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes;
223 pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes;
224 pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize;
225 pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize;
226 pdc->dcattr.szlVirtualDeviceSize.cx = 0;
227 pdc->dcattr.szlVirtualDeviceSize.cy = 0;
228
229 /* Setup regions */
230 pdc->prgnAPI = NULL;
231 pdc->prgnRao = NULL;
232 /* Allocate a Vis region */
233 pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
234 ASSERT(pdc->prgnVis);
235 GDIOBJ_CopyOwnership(pdc->BaseObject.hHmgr, pdc->prgnVis->BaseObject.hHmgr);
236
237 /* Setup palette */
238 pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
239 pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
240
241 /* Setup path */
242 pdc->dclevel.hPath = NULL;
243 pdc->dclevel.flPath = 0;
244 // pdc->dclevel.lapath:
245
246 /* Setup colors */
247 pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff);
248 pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff);
249 pdc->dcattr.crForegroundClr = RGB(0, 0, 0);
250 pdc->dcattr.ulForegroundClr = RGB(0, 0, 0);
251 pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff);
252 pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff);
253 pdc->dcattr.crPenClr = RGB(0, 0, 0);
254 pdc->dcattr.ulPenClr = RGB(0, 0, 0);
255
256 /* Select the default fill and line brush */
257 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
258 pdc->dcattr.hpen = StockObjects[BLACK_PEN];
259 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
260 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
261 pdc->dclevel.ptlBrushOrigin.x = 0;
262 pdc->dclevel.ptlBrushOrigin.y = 0;
263 pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
264
265 /* Initialize EBRUSHOBJs */
266 EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
267 EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
268 EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
269 EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
270
271 /* Setup fill data */
272 pdc->dcattr.jROP2 = R2_COPYPEN;
273 pdc->dcattr.jBkMode = 2;
274 pdc->dcattr.lBkMode = 2;
275 pdc->dcattr.jFillMode = ALTERNATE;
276 pdc->dcattr.lFillMode = 1;
277 pdc->dcattr.jStretchBltMode = 1;
278 pdc->dcattr.lStretchBltMode = 1;
279 pdc->ptlFillOrigin.x = 0;
280 pdc->ptlFillOrigin.y = 0;
281
282 /* Setup drawing position */
283 pdc->dcattr.ptlCurrent.x = 0;
284 pdc->dcattr.ptlCurrent.y = 0;
285 pdc->dcattr.ptfxCurrent.x = 0;
286 pdc->dcattr.ptfxCurrent.y = 0;
287
288 /* Setup ICM data */
289 pdc->dclevel.lIcmMode = 0;
290 pdc->dcattr.lIcmMode = 0;
291 pdc->dcattr.hcmXform = NULL;
292 pdc->dcattr.flIcmFlags = 0;
293 pdc->dcattr.IcmBrushColor = CLR_INVALID;
294 pdc->dcattr.IcmPenColor = CLR_INVALID;
295 pdc->dcattr.pvLIcm = NULL;
296 pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
297 pdc->dclevel.pColorSpace = NULL; // FIXME
298 pdc->pClrxFormLnk = NULL;
299 // pdc->dclevel.ca =
300
301 /* Setup font data */
302 pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
303 pdc->pPFFList = NULL;
304 pdc->flSimulationFlags = 0;
305 pdc->lEscapement = 0;
306 pdc->prfnt = NULL;
307 pdc->dcattr.flFontMapper = 0;
308 pdc->dcattr.flTextAlign = 0;
309 pdc->dcattr.lTextAlign = 0;
310 pdc->dcattr.lTextExtra = 0;
311 pdc->dcattr.lRelAbs = 1;
312 pdc->dcattr.lBreakExtra = 0;
313 pdc->dcattr.cBreak = 0;
314 pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT];
315 // pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
316
317 /* Other stuff */
318 pdc->hdcNext = NULL;
319 pdc->hdcPrev = NULL;
320 pdc->ipfdDevMax = 0x0000ffff;
321 pdc->ulCopyCount = -1;
322 pdc->ptlDoBanding.x = 0;
323 pdc->ptlDoBanding.y = 0;
324 pdc->dclevel.lSaveDepth = 1;
325 pdc->dclevel.hdcSave = NULL;
326 pdc->dcattr.iGraphicsMode = GM_COMPATIBLE;
327 pdc->dcattr.iCS_CP = 0;
328 pdc->pSurfInfo = NULL;
329
330 }
331
332 BOOL
333 INTERNAL_CALL
334 DC_Cleanup(PVOID ObjectBody)
335 {
336 PDC pdc = (PDC)ObjectBody;
337
338 /* Free DC_ATTR */
339 DC_vFreeDcAttr(pdc);
340
341 /* Delete saved DCs */
342 DC_vRestoreDC(pdc, 1);
343
344 /* Deselect dc objects */
345 DC_vSelectSurface(pdc, NULL);
346 DC_vSelectFillBrush(pdc, NULL);
347 DC_vSelectLineBrush(pdc, NULL);
348 DC_vSelectPalette(pdc, NULL);
349
350 /* Cleanup the dc brushes */
351 EBRUSHOBJ_vCleanup(&pdc->eboFill);
352 EBRUSHOBJ_vCleanup(&pdc->eboLine);
353 EBRUSHOBJ_vCleanup(&pdc->eboText);
354 EBRUSHOBJ_vCleanup(&pdc->eboBackground);
355
356 /* Free regions */
357 if (pdc->rosdc.hClipRgn)
358 GreDeleteObject(pdc->rosdc.hClipRgn);
359 if (pdc->prgnVis)
360 REGION_FreeRgnByHandle(pdc->prgnVis->BaseObject.hHmgr);
361 if (pdc->rosdc.hGCClipRgn)
362 GreDeleteObject(pdc->rosdc.hGCClipRgn);
363 if (NULL != pdc->rosdc.CombinedClip)
364 IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
365
366 PATH_Delete(pdc->dclevel.hPath);
367
368 if(pdc->dclevel.pSurface)
369 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
370
371 PDEVOBJ_vRelease(pdc->ppdev) ;
372
373 return TRUE;
374 }
375
376 BOOL
377 FASTCALL
378 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
379 {
380 INT Index;
381 PGDI_TABLE_ENTRY Entry;
382 PDC pDC;
383 BOOL ret = FALSE;
384
385 if (!GDIOBJ_SetOwnership(hDC, Owner))
386 {
387 DPRINT1("GDIOBJ_SetOwnership failed\n");
388 return FALSE;
389 }
390
391 pDC = DC_LockDc(hDC);
392 if (!pDC)
393 {
394 DPRINT1("Could not lock DC\n");
395 return FALSE;
396 }
397
398 /*
399 System Regions:
400 These regions do not use attribute sections and when allocated, use
401 gdiobj level functions.
402 */
403 if (pDC->rosdc.hClipRgn)
404 { // FIXME! HAX!!!
405 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
406 Entry = &GdiHandleTable->Entries[Index];
407 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
408 Entry->UserData = NULL;
409 //
410 if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) goto leave;
411 }
412 if (pDC->prgnVis)
413 { // FIXME! HAX!!!
414 Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
415 Entry = &GdiHandleTable->Entries[Index];
416 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
417 Entry->UserData = NULL;
418 //
419 if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) goto leave;
420 }
421 if (pDC->rosdc.hGCClipRgn)
422 { // FIXME! HAX!!!
423 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
424 Entry = &GdiHandleTable->Entries[Index];
425 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
426 Entry->UserData = NULL;
427 //
428 if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) goto leave;
429 }
430 if (pDC->dclevel.hPath)
431 {
432 if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) goto leave;
433 }
434 ret = TRUE;
435
436 leave:
437 DC_UnlockDc(pDC);
438
439 return ret;
440 }
441
442
443 int FASTCALL
444 CLIPPING_UpdateGCRegion(DC* Dc);
445
446 static
447 void
448 DC_vUpdateDC(PDC pdc)
449 {
450 HRGN hVisRgn ;
451 PPDEVOBJ ppdev = pdc->ppdev ;
452
453 pdc->dhpdev = ppdev->dhpdev;
454
455 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
456 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
457
458 PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
459 hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
460 ASSERT(hVisRgn);
461 GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
462 GreDeleteObject(hVisRgn);
463
464 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
465 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
466
467 /* Mark EBRUSHOBJs as dirty */
468 pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ;
469 }
470
471 /* Prepare a blit for up to 2 DCs */
472 /* rc1 and rc2 are the rectangles where we want to draw or
473 * from where we take pixels. */
474 VOID
475 FASTCALL
476 DC_vPrepareDCsForBlit(PDC pdc1,
477 RECT rc1,
478 PDC pdc2,
479 RECT rc2)
480 {
481 PDC pdcFirst, pdcSecond;
482 PRECT prcFirst, prcSecond;
483
484 /* Update brushes */
485 if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
486 DC_vUpdateFillBrush(pdc1);
487 if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
488 DC_vUpdateLineBrush(pdc1);
489 if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT)
490 DC_vUpdateTextBrush(pdc1);
491
492 /* Lock them in good order */
493 if(pdc2)
494 {
495 if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
496 {
497 pdcFirst = pdc1;
498 prcFirst = &rc1;
499 pdcSecond = pdc2;
500 prcSecond = &rc2;
501 }
502 else
503 {
504 pdcFirst = pdc2;
505 prcFirst = &rc2;
506 pdcSecond = pdc1;
507 prcSecond = &rc1;
508 }
509 }
510 else
511 {
512 pdcFirst = pdc1 ;
513 prcFirst = &rc1;
514 pdcSecond = NULL;
515 prcSecond = NULL;
516 }
517
518 if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
519 {
520 EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
521 MouseSafetyOnDrawStart(pdcFirst->ppdev,
522 prcFirst->left,
523 prcFirst->top,
524 prcFirst->right,
525 prcFirst->bottom) ;
526 /* Update surface if needed */
527 if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
528 {
529 DC_vUpdateDC(pdcFirst);
530 }
531 }
532 if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
533 {
534 EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
535 MouseSafetyOnDrawStart(pdcSecond->ppdev,
536 prcSecond->left,
537 prcSecond->top,
538 prcSecond->right,
539 prcSecond->bottom) ;
540 /* Update surface if needed */
541 if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
542 {
543 DC_vUpdateDC(pdcSecond);
544 }
545 }
546 }
547
548 /* Finishes a blit for one or two DCs */
549 VOID
550 FASTCALL
551 DC_vFinishBlit(PDC pdc1, PDC pdc2)
552 {
553 if(pdc1->dctype == DCTYPE_DIRECT)
554 {
555 MouseSafetyOnDrawEnd(pdc1->ppdev);
556 EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
557 }
558
559 if(pdc2)
560 {
561 if(pdc2->dctype == DCTYPE_DIRECT)
562 {
563 MouseSafetyOnDrawEnd(pdc2->ppdev);
564 EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
565 }
566 }
567 }
568
569 HDC
570 NTAPI
571 GreOpenDCW(
572 PUNICODE_STRING pustrDevice,
573 DEVMODEW *pdmInit,
574 PUNICODE_STRING pustrLogAddr,
575 ULONG iType,
576 BOOL bDisplay,
577 HANDLE hspool,
578 VOID *pDriverInfo2,
579 VOID *pUMdhpdev)
580 {
581 PPDEVOBJ ppdev;
582 PDC pdc;
583 HDC hdc;
584
585 DPRINT("GreOpenDCW(%S, iType=%ld)\n",
586 pustrDevice ? pustrDevice->Buffer : NULL, iType);
587
588 /* Get a PDEVOBJ for the device */
589 ppdev = EngpGetPDEV(pustrDevice);
590 if (!ppdev)
591 {
592 DPRINT1("Didn't find a suitable PDEV\n");
593 return NULL;
594 }
595
596 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev);
597
598 pdc = DC_AllocDcWithHandle();
599 if (!pdc)
600 {
601 DPRINT1("Could not Allocate a DC\n");
602 PDEVOBJ_vRelease(ppdev);
603 return NULL;
604 }
605 hdc = pdc->BaseObject.hHmgr;
606
607 /* Lock ppdev and initialize the new DC */
608 DC_vInitDc(pdc, iType, ppdev);
609 /* FIXME: HACK! */
610 DC_InitHack(pdc);
611
612 DC_AllocDcAttr(pdc);
613
614 DC_UnlockDc(pdc);
615
616 DPRINT("returning hdc = %p\n", hdc);
617
618 return hdc;
619 }
620
621 HDC
622 APIENTRY
623 NtGdiOpenDCW(
624 PUNICODE_STRING pustrDevice,
625 DEVMODEW *pdmInit,
626 PUNICODE_STRING pustrLogAddr,
627 ULONG iType,
628 BOOL bDisplay,
629 HANDLE hspool,
630 VOID *pDriverInfo2,
631 VOID *pUMdhpdev)
632 {
633 UNICODE_STRING ustrDevice;
634 WCHAR awcDevice[CCHDEVICENAME];
635 DEVMODEW dmInit;
636 PVOID dhpdev;
637 HDC hdc;
638
639 /* Only if a devicename is given, we need any data */
640 if (pustrDevice)
641 {
642 /* Initialize destination string */
643 RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
644
645 _SEH2_TRY
646 {
647 /* Probe the UNICODE_STRING and the buffer */
648 ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
649 ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
650
651 /* Copy the string */
652 RtlCopyUnicodeString(&ustrDevice, pustrDevice);
653
654 if (pdmInit)
655 {
656 /* FIXME: could be larger */
657 ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
658 RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
659 }
660
661 if (pUMdhpdev)
662 {
663 ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
664 }
665 }
666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
667 {
668 SetLastNtError(_SEH2_GetExceptionCode());
669 _SEH2_YIELD(return NULL);
670 }
671 _SEH2_END
672 }
673 else
674 {
675 pdmInit = NULL;
676 pUMdhpdev = NULL;
677 }
678
679 /* FIXME: HACK! */
680 if (pustrDevice)
681 {
682 UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY");
683 if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE))
684 {
685 pustrDevice = NULL;
686 }
687 }
688
689 /* Call the internal function */
690 hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
691 pdmInit ? &dmInit : NULL,
692 NULL, // fixme pwszLogAddress
693 iType,
694 bDisplay,
695 hspool,
696 NULL, //FIXME: pDriverInfo2
697 pUMdhpdev ? &dhpdev : NULL);
698
699 /* If we got a HDC and a UM dhpdev is requested,... */
700 if (hdc && pUMdhpdev)
701 {
702 /* Copy dhpdev to caller (FIXME: use dhpdev?? */
703 _SEH2_TRY
704 {
705 /* Pointer was already probed */
706 *(HANDLE*)pUMdhpdev = dhpdev;
707 }
708 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
709 {
710 /* Ignore error */
711 }
712 _SEH2_END
713 }
714
715 return hdc;
716 }
717
718
719 HDC
720 APIENTRY
721 NtGdiCreateCompatibleDC(HDC hdc)
722 {
723 HDC hdcNew;
724 PPDEVOBJ ppdev;
725 PDC pdc, pdcNew;
726
727 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc);
728
729 /* Did the caller provide a DC? */
730 if (hdc)
731 {
732 /* Yes, try to lock it */
733 pdc = DC_LockDc(hdc);
734 if (!pdc)
735 {
736 DPRINT1("Could not lock source DC %p\n", hdc);
737 return NULL;
738 }
739
740 /* Get the pdev from the DC */
741 ppdev = pdc->ppdev;
742 InterlockedIncrement(&ppdev->cPdevRefs);
743
744 /* Unlock the source DC */
745 DC_UnlockDc(pdc);
746 }
747 else
748 {
749 /* No DC given, get default device */
750 ppdev = EngpGetPDEV(NULL);
751 }
752
753 if (!ppdev)
754 {
755 DPRINT1("Didn't find a suitable PDEV\n");
756 return NULL;
757 }
758
759 /* Allocate a new DC */
760 pdcNew = DC_AllocDcWithHandle();
761 if (!pdcNew)
762 {
763 DPRINT1("Could not allocate a new DC\n");
764 PDEVOBJ_vRelease(ppdev);
765 return NULL;
766 }
767 hdcNew = pdcNew->BaseObject.hHmgr;
768
769 /* Lock ppdev and initialize the new DC */
770 DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
771 /* FIXME: HACK! */
772 DC_InitHack(pdcNew);
773
774 /* Allocate a dc attribute */
775 DC_AllocDcAttr(pdcNew);
776
777 // HACK!
778 DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
779
780 DC_UnlockDc(pdcNew);
781
782 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew);
783
784 return hdcNew;
785 }
786
787 BOOL
788 FASTCALL
789 IntGdiDeleteDC(HDC hDC, BOOL Force)
790 {
791 PDC DCToDelete = DC_LockDc(hDC);
792
793 if (DCToDelete == NULL)
794 {
795 EngSetLastError(ERROR_INVALID_HANDLE);
796 return FALSE;
797 }
798
799 if (!Force)
800 {
801 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
802 * For some reason, it's still a valid handle, pointing to some kernel data.
803 * Not sure if this is a bug, a feature, some cache stuff... Who knows?
804 * See NtGdiDeleteObjectApp test for details */
805 if (DCToDelete->fs & DC_FLAG_PERMANENT)
806 {
807 DC_UnlockDc(DCToDelete);
808 if(UserReleaseDC(NULL, hDC, FALSE))
809 {
810 /* ReactOs feature : call UserReleaseDC
811 * I don't think windows does it.
812 * Still, complain, no one should ever call DeleteDC
813 * on a window DC */
814 DPRINT1("No, you naughty application!\n");
815 return TRUE;
816 }
817 else
818 {
819 /* This is not a window owned DC.
820 * Force its deletion */
821 return IntGdiDeleteDC(hDC, TRUE);
822 }
823 }
824 }
825
826 DC_UnlockDc(DCToDelete);
827
828 if (!IsObjectDead(hDC))
829 {
830 if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
831 {
832 DPRINT1("DC_FreeDC failed\n");
833 }
834 }
835 else
836 {
837 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC);
838 }
839
840 return TRUE;
841 }
842
843 BOOL
844 APIENTRY
845 NtGdiDeleteObjectApp(HANDLE DCHandle)
846 {
847 /* Complete all pending operations */
848 NtGdiFlushUserBatch();
849
850 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
851
852 if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
853 return GreDeleteObject((HGDIOBJ) DCHandle);
854
855 if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
856
857 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
858 {
859 EngSetLastError(ERROR_INVALID_HANDLE);
860 return FALSE;
861 }
862
863 return IntGdiDeleteDC(DCHandle, FALSE);
864 }
865
866 BOOL
867 FASTCALL
868 MakeInfoDC(PDC pdc, BOOL bSet)
869 {
870 PSURFACE pSurface;
871 SIZEL sizl;
872
873 /* Can not be a display DC. */
874 if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
875 if (bSet)
876 {
877 if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
878 return FALSE;
879
880 pSurface = pdc->dclevel.pSurface;
881 pdc->fs |= DC_FLAG_TEMPINFODC;
882 pdc->pSurfInfo = pSurface;
883 pdc->dctype = DC_TYPE_INFO;
884 pdc->dclevel.pSurface = NULL;
885
886 PDEVOBJ_sizl(pdc->ppdev, &sizl);
887
888 if ( sizl.cx == pdc->dclevel.sizl.cx &&
889 sizl.cy == pdc->dclevel.sizl.cy )
890 return TRUE;
891
892 pdc->dclevel.sizl.cx = sizl.cx;
893 pdc->dclevel.sizl.cy = sizl.cy;
894 }
895 else
896 {
897 if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
898 return FALSE;
899
900 pSurface = pdc->pSurfInfo;
901 pdc->fs &= ~DC_FLAG_TEMPINFODC;
902 pdc->dclevel.pSurface = pSurface;
903 pdc->dctype = DC_TYPE_DIRECT;
904 pdc->pSurfInfo = NULL;
905
906 if ( !pSurface ||
907 (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
908 pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
909 return TRUE;
910
911 pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
912 pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
913 }
914 return IntSetDefaultRegion(pdc);
915 }
916
917 /*
918 * @implemented
919 */
920 BOOL
921 APIENTRY
922 NtGdiMakeInfoDC(
923 IN HDC hdc,
924 IN BOOL bSet)
925 {
926 BOOL Ret;
927 PDC pdc = DC_LockDc(hdc);
928 if (pdc)
929 {
930 Ret = MakeInfoDC(pdc, bSet);
931 DC_UnlockDc(pdc);
932 return Ret;
933 }
934 return FALSE;
935 }
936
937
938 HDC FASTCALL
939 IntGdiCreateDC(
940 PUNICODE_STRING Driver,
941 PUNICODE_STRING pustrDevice,
942 PVOID pUMdhpdev,
943 CONST PDEVMODEW pdmInit,
944 BOOL CreateAsIC)
945 {
946 HDC hdc;
947
948 hdc = GreOpenDCW(pustrDevice,
949 pdmInit,
950 NULL,
951 CreateAsIC ? DCTYPE_INFO :
952 (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
953 TRUE,
954 NULL,
955 NULL,
956 pUMdhpdev);
957
958 return hdc;
959 }
960
961 HDC FASTCALL
962 IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
963 {
964 HDC hDC;
965 UNIMPLEMENTED;
966 ASSERT(FALSE);
967
968 if (DcType == DC_TYPE_MEMORY)
969 hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
970 else
971 hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
972
973 return hDC;
974 }
975
976 BOOL
977 FASTCALL
978 IntGdiSetDCOwnerEx( HDC hDC, DWORD OwnerMask, BOOL NoSetBrush)
979 {
980 PDC pDC;
981 BOOL Ret = FALSE;
982
983 if (!hDC || (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)) return FALSE;
984
985 if ((OwnerMask == GDI_OBJ_HMGR_PUBLIC) || OwnerMask == GDI_OBJ_HMGR_NONE)
986 {
987 pDC = DC_LockDc ( hDC );
988 MmCopyFromCaller(&pDC->dcattr, pDC->pdcattr, sizeof(DC_ATTR));
989 DC_vFreeDcAttr(pDC);
990 DC_UnlockDc( pDC );
991
992 if (!DC_SetOwnership( hDC, NULL )) // This hDC is inaccessible!
993 return Ret;
994 }
995
996 if (OwnerMask == GDI_OBJ_HMGR_POWNED)
997 {
998 pDC = DC_LockDc ( hDC );
999 ASSERT(pDC->pdcattr == &pDC->dcattr);
1000 DC_UnlockDc( pDC );
1001
1002 if (!DC_SetOwnership( hDC, PsGetCurrentProcess() )) return Ret;
1003
1004 DC_AllocateDcAttr( hDC ); // Allocate new dcattr
1005
1006 DCU_SynchDcAttrtoUser( hDC ); // Copy data from dc to dcattr
1007 }
1008
1009 if ((OwnerMask != GDI_OBJ_HMGR_NONE) && !NoSetBrush)
1010 {
1011 pDC = DC_LockDc ( hDC );
1012 if (IntGdiSetBrushOwner((PBRUSH)pDC->dclevel.pbrFill, OwnerMask))
1013 IntGdiSetBrushOwner((PBRUSH)pDC->dclevel.pbrLine, OwnerMask);
1014 DC_UnlockDc( pDC );
1015 }
1016 return TRUE;
1017 }