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