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