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