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