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