apply 46848 from yarotows
[reactos.git] / reactos / 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 /** Internal functions ********************************************************/
16
17 HDC FASTCALL
18 DC_AllocDC(PUNICODE_STRING Driver)
19 {
20 PDC NewDC;
21 PDC_ATTR pdcattr;
22 HDC hDC;
23 PWSTR Buf = NULL;
24 XFORM xformTemplate;
25 PBRUSH pbrush;
26 HSURF hsurf;
27
28 if (Driver != NULL)
29 {
30 Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
31 if (!Buf)
32 {
33 DPRINT1("ExAllocatePoolWithTag failed\n");
34 return NULL;
35 }
36 RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
37 }
38
39 NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC);
40 if (!NewDC)
41 {
42 if (Buf)
43 {
44 ExFreePoolWithTag(Buf, TAG_DC);
45 }
46 DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
47 return NULL;
48 }
49
50 hDC = NewDC->BaseObject.hHmgr;
51
52 NewDC->pdcattr = &NewDC->dcattr;
53 DC_AllocateDcAttr(hDC);
54
55 if (Driver != NULL)
56 {
57 RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING));
58 NewDC->rosdc.DriverName.Buffer = Buf;
59 }
60 pdcattr = NewDC->pdcattr;
61
62 // FIXME: no floating point in the kernel!
63 xformTemplate.eM11 = 1.0f;
64 xformTemplate.eM12 = 0.0f;
65 xformTemplate.eM21 = 0.0f;
66 xformTemplate.eM22 = 1.0f;
67 xformTemplate.eDx = 0.0f;
68 xformTemplate.eDy = 0.0f;
69 XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate);
70 XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate);
71 XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate);
72
73 // Setup syncing bits for the dcattr data packets.
74 pdcattr->flXform = DEVICE_TO_PAGE_INVALID;
75
76 pdcattr->ulDirty_ = 0; // Server side
77
78 pdcattr->iMapMode = MM_TEXT;
79 pdcattr->iGraphicsMode = GM_COMPATIBLE;
80 pdcattr->jFillMode = ALTERNATE;
81
82 pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG!
83 pdcattr->szlWindowExt.cy = 1;
84 pdcattr->szlViewportExt.cx = 1;
85 pdcattr->szlViewportExt.cy = 1;
86
87 pdcattr->crForegroundClr = 0;
88 pdcattr->ulForegroundClr = 0;
89
90 pdcattr->ulBackgroundClr = 0xffffff;
91 pdcattr->crBackgroundClr = 0xffffff;
92
93 pdcattr->ulPenClr = RGB(0, 0, 0);
94 pdcattr->crPenClr = RGB(0, 0, 0);
95
96 pdcattr->ulBrushClr = RGB(255, 255, 255); // Do this way too.
97 pdcattr->crBrushClr = RGB(255, 255, 255);
98
99 //// This fixes the default brush and pen settings. See DC_InitDC.
100
101 /* Create the default fill brush */
102 pdcattr->hbrush = NtGdiGetStockObject(WHITE_BRUSH);
103 NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
104 EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NewDC);
105
106 /* Create the default pen / line brush */
107 pdcattr->hpen = NtGdiGetStockObject(BLACK_PEN);
108 NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen);
109 EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrLine, NewDC);
110
111 /* Create the default text brush */
112 pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(BLACK_BRUSH));
113 EBRUSHOBJ_vInit(&NewDC->eboText, pbrush, NewDC);
114 pdcattr->ulDirty_ |= DIRTY_TEXT;
115
116 /* Create the default background brush */
117 pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(WHITE_BRUSH));
118 EBRUSHOBJ_vInit(&NewDC->eboBackground, pbrush, NewDC);
119
120 pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT);
121 TextIntRealizeFont(pdcattr->hlfntNew,NULL);
122 NewDC->hlfntCur = pdcattr->hlfntNew;
123 NewDC->dclevel.plfnt = GDIOBJ_GetKernelObj(pdcattr->hlfntNew);
124
125 NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
126 NewDC->dclevel.ppal = PALETTE_ShareLockPalette(NewDC->dclevel.hpal);
127 /* This should never fail */
128 ASSERT(NewDC->dclevel.ppal);
129
130 NewDC->dclevel.laPath.eMiterLimit = 10.0; // FIXME: use FLOATL or FLOATOBJ!
131
132 NewDC->dclevel.lSaveDepth = 1;
133
134 hsurf = (HBITMAP)PrimarySurface.pSurface; // <- what kind of haxx0ry is that?
135 NewDC->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
136
137 return NewDC;
138 }
139
140 BOOL INTERNAL_CALL
141 DC_Cleanup(PVOID ObjectBody)
142 {
143 PDC pDC = (PDC)ObjectBody;
144
145 /* Free driver name (HACK) */
146 if (pDC->rosdc.DriverName.Buffer)
147 ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC);
148
149 /* Deselect dc objects */
150 DC_vSelectSurface(pDC, NULL);
151 DC_vSelectFillBrush(pDC, NULL);
152 DC_vSelectLineBrush(pDC, NULL);
153 DC_vSelectPalette(pDC, NULL);
154
155 /* Dereference default brushes */
156 BRUSH_ShareUnlockBrush(pDC->eboText.pbrush);
157 BRUSH_ShareUnlockBrush(pDC->eboBackground.pbrush);
158
159 /* Cleanup the dc brushes */
160 EBRUSHOBJ_vCleanup(&pDC->eboFill);
161 EBRUSHOBJ_vCleanup(&pDC->eboLine);
162 EBRUSHOBJ_vCleanup(&pDC->eboText);
163 EBRUSHOBJ_vCleanup(&pDC->eboBackground);
164
165 return TRUE;
166 }
167
168 BOOL
169 FASTCALL
170 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
171 {
172 INT Index;
173 PGDI_TABLE_ENTRY Entry;
174 PDC pDC;
175
176 if (!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE;
177 pDC = DC_LockDc(hDC);
178 if (pDC)
179 {
180 /*
181 System Regions:
182 These regions do not use attribute sections and when allocated, use
183 gdiobj level functions.
184 */
185 if (pDC->rosdc.hClipRgn)
186 { // FIXME! HAX!!!
187 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
188 Entry = &GdiHandleTable->Entries[Index];
189 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
190 Entry->UserData = NULL;
191 //
192 if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
193 }
194 if (pDC->rosdc.hVisRgn)
195 { // FIXME! HAX!!!
196 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hVisRgn);
197 Entry = &GdiHandleTable->Entries[Index];
198 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
199 Entry->UserData = NULL;
200 //
201 if (!GDIOBJ_SetOwnership(pDC->rosdc.hVisRgn, Owner)) return FALSE;
202 }
203 if (pDC->rosdc.hGCClipRgn)
204 { // FIXME! HAX!!!
205 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
206 Entry = &GdiHandleTable->Entries[Index];
207 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
208 Entry->UserData = NULL;
209 //
210 if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
211 }
212 if (pDC->dclevel.hPath)
213 {
214 if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
215 }
216 DC_UnlockDc(pDC);
217 }
218
219 return TRUE;
220 }
221
222
223 HDC FASTCALL
224 IntGdiCreateDC(
225 PUNICODE_STRING Driver,
226 PUNICODE_STRING Device,
227 PVOID pUMdhpdev,
228 CONST PDEVMODEW InitData,
229 BOOL CreateAsIC)
230 {
231 HDC hdc;
232 PDC pdc;
233 PDC_ATTR pdcattr;
234 HRGN hVisRgn;
235 UNICODE_STRING StdDriver;
236 BOOL calledFromUser;
237
238 RtlInitUnicodeString(&StdDriver, L"DISPLAY");
239
240 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device);
241
242 if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
243 {
244 if (CreateAsIC)
245 {
246 if (! IntPrepareDriverIfNeeded())
247 {
248 /* Here, we have two possibilities:
249 * a) return NULL, and hope that the caller
250 * won't call us in a loop
251 * b) bugcheck, but caller is unable to
252 * react on the problem
253 */
254 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
255 return NULL;*/
256 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE);
257 }
258 }
259 else
260 {
261 calledFromUser = UserIsEntered();
262 if (!calledFromUser)
263 {
264 UserEnterExclusive();
265 }
266
267 if (! co_IntGraphicsCheck(TRUE))
268 {
269 if (!calledFromUser)
270 {
271 UserLeave();
272 }
273 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
274 return NULL;
275 }
276
277 if (!calledFromUser)
278 {
279 UserLeave();
280 }
281
282 }
283 }
284
285 /* Check for existing DC object */
286 if ((hdc = DC_FindOpenDC(Driver)) != NULL)
287 {
288 hdc = NtGdiCreateCompatibleDC(hdc);
289 if (!hdc)
290 DPRINT1("NtGdiCreateCompatibleDC() failed\n");
291 return hdc;
292 }
293
294 /* Allocate a DC object */
295 pdc = DC_AllocDC(Driver);
296 if (pdc == NULL)
297 {
298 DPRINT1("DC_AllocDC() failed\n");
299 return NULL;
300 }
301 hdc = pdc->BaseObject.hHmgr;
302 pdcattr = pdc->pdcattr;
303
304 pdc->dctype = DC_TYPE_DIRECT;
305
306 pdc->dhpdev = PrimarySurface.dhpdev;
307 if (pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device.
308 pdc->ppdev = (PVOID)&PrimarySurface;
309
310 // ATM we only have one display.
311 pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY;
312
313 pdc->flGraphicsCaps = PrimarySurface.devinfo.flGraphicsCaps;
314 pdc->flGraphicsCaps2 = PrimarySurface.devinfo.flGraphicsCaps2;
315
316 pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
317
318 pdcattr->jROP2 = R2_COPYPEN;
319
320 pdc->erclWindow.top = pdc->erclWindow.left = 0;
321 pdc->erclWindow.right = pdc->ppdev->gdiinfo.ulHorzRes;
322 pdc->erclWindow.bottom = pdc->ppdev->gdiinfo.ulVertRes;
323 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW.
324
325 pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
326
327 hVisRgn = IntSysCreateRectRgn(0, 0, pdc->ppdev->gdiinfo.ulHorzRes,
328 pdc->ppdev->gdiinfo.ulVertRes);
329
330 if (!CreateAsIC)
331 {
332 pdc->pSurfInfo = NULL;
333 // pdc->dclevel.pSurface =
334 DC_UnlockDc(pdc);
335
336 /* Initialize the DC state */
337 IntGdiSetTextColor(hdc, RGB(0, 0, 0));
338 IntGdiSetBkColor(hdc, RGB(255, 255, 255));
339 }
340 else
341 {
342 /* From MSDN2:
343 The CreateIC function creates an information context for the specified device.
344 The information context provides a fast way to get information about the
345 device without creating a device context (DC). However, GDI drawing functions
346 cannot accept a handle to an information context.
347 */
348 pdc->dctype = DC_TYPE_INFO;
349 // pdc->pSurfInfo =
350 // DC_vSelectSurface(pdc, NULL);
351 pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255);
352 pdcattr->crForegroundClr = RGB(0, 0, 0);
353 DC_UnlockDc(pdc);
354 }
355 DC_InitDC(hdc);
356
357 if (hVisRgn)
358 {
359 GdiSelectVisRgn(hdc, hVisRgn);
360 REGION_FreeRgnByHandle(hVisRgn);
361 }
362
363 IntGdiSetTextAlign(hdc, TA_TOP);
364 IntGdiSetBkMode(hdc, OPAQUE);
365
366 return hdc;
367 }
368
369
370 HDC APIENTRY
371 NtGdiOpenDCW(
372 PUNICODE_STRING Device,
373 DEVMODEW *InitData,
374 PUNICODE_STRING pustrLogAddr,
375 ULONG iType,
376 BOOL bDisplay,
377 HANDLE hspool,
378 VOID *pDriverInfo2,
379 VOID *pUMdhpdev)
380 {
381 UNICODE_STRING SafeDevice;
382 DEVMODEW SafeInitData;
383 PVOID Dhpdev;
384 HDC Ret;
385 NTSTATUS Status = STATUS_SUCCESS;
386
387 if (!Device) return UserGetDesktopDC(iType,FALSE,TRUE);
388
389 if (InitData)
390 {
391 _SEH2_TRY
392 {
393 if (pUMdhpdev)
394 {
395 ProbeForWrite(pUMdhpdev, sizeof(PVOID), 1);
396 }
397 ProbeForRead(InitData, sizeof(DEVMODEW), 1);
398 RtlCopyMemory(&SafeInitData, InitData, sizeof(DEVMODEW));
399 }
400 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
401 {
402 Status = _SEH2_GetExceptionCode();
403 }
404 _SEH2_END;
405
406 if (!NT_SUCCESS(Status))
407 {
408 SetLastNtError(Status);
409 return NULL;
410 }
411 /* FIXME - InitData can have some more bytes! */
412 }
413
414 if (Device)
415 {
416 Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
417 if (!NT_SUCCESS(Status))
418 {
419 SetLastNtError(Status);
420 return NULL;
421 }
422 }
423
424 Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL,
425 NULL,
426 pUMdhpdev ? &Dhpdev : NULL,
427 InitData ? &SafeInitData : NULL,
428 (BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW
429
430 // FIXME!!!!
431 if (pUMdhpdev) pUMdhpdev = Dhpdev;
432
433 return Ret;
434 }
435
436 HDC FASTCALL
437 IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
438 {
439 HDC hDC;
440 UNICODE_STRING DriverName;
441 RtlInitUnicodeString(&DriverName, L"DISPLAY");
442
443 if (DcType != DC_TYPE_MEMORY)
444 hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
445 else
446 hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
447 //
448 // There is room to grow here~
449 //
450
451 //
452 // If NULL, first time through! Build the default (was window) dc!
453 // Setup clean DC state for the system.
454 //
455 if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG!
456 { // This is a cheesy way to do this.
457 PDC dc = DC_LockDc(hDC);
458 HSURF hsurf;
459 defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
460 if (!defaultDCstate)
461 {
462 DC_UnlockDc(dc);
463 return NULL;
464 }
465 RtlZeroMemory(defaultDCstate, sizeof(DC));
466 defaultDCstate->pdcattr = &defaultDCstate->dcattr;
467 hsurf = (HSURF)PrimarySurface.pSurface; // HAX²
468 defaultDCstate->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
469 DC_vCopyState(dc, defaultDCstate, TRUE);
470 DC_UnlockDc(dc);
471 }
472 return hDC;
473 }
474
475 BOOL
476 FASTCALL
477 IntGdiDeleteDC(HDC hDC, BOOL Force)
478 {
479 PDC DCToDelete = DC_LockDc(hDC);
480
481 if (DCToDelete == NULL)
482 {
483 SetLastWin32Error(ERROR_INVALID_HANDLE);
484 return FALSE;
485 }
486
487 if (!Force)
488 {
489 if (DCToDelete->fs & DC_FLAG_PERMANENT)
490 {
491 DPRINT1("No! You Naughty Application!\n");
492 DC_UnlockDc(DCToDelete);
493 return UserReleaseDC(NULL, hDC, FALSE);
494 }
495 }
496
497 /* First delete all saved DCs */
498 while (DCToDelete->dclevel.lSaveDepth > 1)
499 {
500 PDC savedDC;
501 HDC savedHDC;
502
503 savedHDC = DCToDelete->hdcNext;
504 savedDC = DC_LockDc(savedHDC);
505 if (savedDC == NULL)
506 {
507 break;
508 }
509 DCToDelete->hdcNext = savedDC->hdcNext;
510 DCToDelete->dclevel.lSaveDepth--;
511 DC_UnlockDc(savedDC);
512 IntGdiDeleteDC(savedHDC, Force);
513 }
514
515 /* Free GDI resources allocated to this DC */
516 if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE))
517 {
518 /*
519 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
520 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
521 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
522 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
523 }
524 if (DCToDelete->rosdc.hClipRgn)
525 {
526 GreDeleteObject(DCToDelete->rosdc.hClipRgn);
527 }
528 if (DCToDelete->rosdc.hVisRgn)
529 {
530 GreDeleteObject(DCToDelete->rosdc.hVisRgn);
531 }
532 if (NULL != DCToDelete->rosdc.CombinedClip)
533 {
534 IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip);
535 }
536 if (DCToDelete->rosdc.hGCClipRgn)
537 {
538 GreDeleteObject(DCToDelete->rosdc.hGCClipRgn);
539 }
540 if (DCToDelete->dclevel.prgnMeta)
541 {
542 GreDeleteObject(((PROSRGNDATA)DCToDelete->dclevel.prgnMeta)->BaseObject.hHmgr);
543 }
544 if (DCToDelete->prgnAPI)
545 {
546 GreDeleteObject(((PROSRGNDATA)DCToDelete->prgnAPI)->BaseObject.hHmgr);
547 }
548 PATH_Delete(DCToDelete->dclevel.hPath);
549
550 DC_UnlockDc(DCToDelete);
551 GreDeleteObject(hDC);
552 return TRUE;
553 }
554
555 HDC FASTCALL
556 DC_FindOpenDC(PUNICODE_STRING Driver)
557 {
558 return NULL;
559 }
560
561 /*!
562 * Initialize some common fields in the Device Context structure.
563 */
564 VOID FASTCALL
565 DC_InitDC(HDC DCHandle)
566 {
567 // NtGdiRealizeDefaultPalette(DCHandle);
568
569 //// Removed for now.. See above brush and pen.
570 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
571 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
572 ////
573 //NtGdiSelectFont(DCHandle, hFont);
574
575 /*
576 {
577 int res;
578 res = CLIPPING_UpdateGCRegion(DCToInit);
579 ASSERT ( res != ERROR );
580 }
581 */
582
583 /* Set virtual resolution */
584 NtGdiSetVirtualResolution(DCHandle, 0, 0, 0, 0);
585 }
586
587 BOOL
588 FASTCALL
589 MakeInfoDC(PDC pdc, BOOL bSet)
590 {
591 PSURFACE pSurface;
592 SIZEL sizl;
593
594 /* Can not be a display DC. */
595 if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
596 if (bSet)
597 {
598 if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
599 return FALSE;
600
601 pSurface = pdc->dclevel.pSurface;
602 pdc->fs |= DC_FLAG_TEMPINFODC;
603 pdc->pSurfInfo = pSurface;
604 pdc->dctype = DC_TYPE_INFO;
605 pdc->dclevel.pSurface = NULL;
606
607 PDEV_sizl(pdc->ppdev, &sizl);
608
609 if ( sizl.cx == pdc->dclevel.sizl.cx &&
610 sizl.cy == pdc->dclevel.sizl.cy )
611 return TRUE;
612
613 pdc->dclevel.sizl.cx = sizl.cx;
614 pdc->dclevel.sizl.cy = sizl.cy;
615 }
616 else
617 {
618 if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
619 return FALSE;
620
621 pSurface = pdc->pSurfInfo;
622 pdc->fs &= ~DC_FLAG_TEMPINFODC;
623 pdc->dclevel.pSurface = pSurface;
624 pdc->dctype = DC_TYPE_DIRECT;
625 pdc->pSurfInfo = NULL;
626
627 if ( !pSurface ||
628 (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
629 pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
630 return TRUE;
631
632 pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
633 pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
634 }
635 return IntSetDefaultRegion(pdc);
636 }
637
638 /*
639 * @implemented
640 */
641 BOOL
642 APIENTRY
643 NtGdiMakeInfoDC(
644 IN HDC hdc,
645 IN BOOL bSet)
646 {
647 BOOL Ret;
648 PDC pdc = DC_LockDc(hdc);
649 if (pdc)
650 {
651 Ret = MakeInfoDC(pdc, bSet);
652 DC_UnlockDc(pdc);
653 return Ret;
654 }
655 return FALSE;
656 }
657
658 HDC APIENTRY
659 NtGdiCreateCompatibleDC(HDC hDC)
660 {
661 PDC pdcNew, pdcOld;
662 PDC_ATTR pdcattrNew, pdcattrOld;
663 HDC hdcNew, DisplayDC = NULL;
664 HRGN hVisRgn;
665 UNICODE_STRING DriverName;
666 DWORD Layout = 0;
667 HSURF hsurf;
668
669 if (hDC == NULL)
670 {
671 RtlInitUnicodeString(&DriverName, L"DISPLAY");
672 DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
673 if (NULL == DisplayDC)
674 {
675 DPRINT1("Failed to create DisplayDC\n");
676 return NULL;
677 }
678 hDC = DisplayDC;
679 }
680
681 /* Allocate a new DC based on the original DC's device */
682 pdcOld = DC_LockDc(hDC);
683 if (NULL == pdcOld)
684 {
685 if (NULL != DisplayDC)
686 {
687 NtGdiDeleteObjectApp(DisplayDC);
688 }
689 DPRINT1("Failed to lock hDC\n");
690 return NULL;
691 }
692 pdcNew = DC_AllocDC(&pdcOld->rosdc.DriverName);
693 if (!pdcNew)
694 {
695 DPRINT1("Failed to create pdcNew\n");
696 DC_UnlockDc(pdcOld);
697 if (DisplayDC)
698 {
699 NtGdiDeleteObjectApp(DisplayDC);
700 }
701 return NULL;
702 }
703 hdcNew = pdcNew->BaseObject.hHmgr;
704
705 pdcattrOld = pdcOld->pdcattr;
706 pdcattrNew = pdcNew->pdcattr;
707
708 /* Copy information from original DC to new DC */
709 pdcNew->dclevel.hdcSave = hdcNew;
710
711 pdcNew->dhpdev = pdcOld->dhpdev;
712
713 /* DriverName is copied in the AllocDC routine */
714 pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg;
715 pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt;
716 pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg;
717 pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt;
718
719 pdcNew->dctype = DC_TYPE_MEMORY; // Always!
720 hsurf = NtGdiGetStockObject(DEFAULT_BITMAP);
721 pdcNew->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
722 pdcNew->ppdev = pdcOld->ppdev;
723 pdcNew->dclevel.hpal = pdcOld->dclevel.hpal;
724
725 pdcattrNew->lTextAlign = pdcattrOld->lTextAlign;
726 pdcattrNew->lBkMode = pdcattrOld->lBkMode;
727 pdcattrNew->jBkMode = pdcattrOld->jBkMode;
728 pdcattrNew->jROP2 = pdcattrOld->jROP2;
729 pdcattrNew->dwLayout = pdcattrOld->dwLayout;
730 if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout;
731 pdcNew->dclevel.flPath = pdcOld->dclevel.flPath;
732 pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_;
733 pdcattrNew->iCS_CP = pdcattrOld->iCS_CP;
734
735 pdcNew->erclWindow.left = pdcNew->erclWindow.top = 0;
736 pdcNew->erclWindow.right = pdcNew->erclWindow.bottom = 1;
737
738 DC_UnlockDc(pdcNew);
739 DC_UnlockDc(pdcOld);
740 if (NULL != DisplayDC)
741 {
742 NtGdiDeleteObjectApp(DisplayDC);
743 }
744
745 hVisRgn = IntSysCreateRectRgn(0, 0, 1, 1);
746 if (hVisRgn)
747 {
748 GdiSelectVisRgn(hdcNew, hVisRgn);
749 REGION_FreeRgnByHandle(hVisRgn);
750 }
751 if (Layout) NtGdiSetLayout(hdcNew, -1, Layout);
752
753 DC_InitDC(hdcNew);
754 return hdcNew;
755 }
756
757
758 BOOL
759 APIENTRY
760 NtGdiDeleteObjectApp(HANDLE DCHandle)
761 {
762 GDIOBJTYPE ObjType;
763
764 /* Complete all pending operations */
765 NtGdiFlushUserBatch();
766
767 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
768
769 if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
770
771 ObjType = GDI_HANDLE_GET_TYPE(DCHandle) >> GDI_ENTRY_UPPER_SHIFT;
772
773 if (GreGetObjectOwner( DCHandle, ObjType))
774 {
775 switch(ObjType)
776 {
777 case GDIObjType_DC_TYPE:
778 return IntGdiDeleteDC(DCHandle, FALSE);
779
780 case GDIObjType_RGN_TYPE:
781 case GDIObjType_SURF_TYPE:
782 case GDIObjType_PAL_TYPE:
783 case GDIObjType_LFONT_TYPE:
784 case GDIObjType_BRUSH_TYPE:
785 return GreDeleteObject((HGDIOBJ) DCHandle);
786
787 default:
788 return FALSE;
789 }
790 }
791 return (DCHandle != NULL);
792 }
793