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