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