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