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