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