be3ad345476229893b2feeeef5684e26bebdf3b6
[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);
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 PATH_Delete(DCToDelete->dclevel.hPath);
543
544 DC_UnlockDc(DCToDelete);
545 GreDeleteObject(hDC);
546 return TRUE;
547 }
548
549 HDC FASTCALL
550 DC_FindOpenDC(PUNICODE_STRING Driver)
551 {
552 return NULL;
553 }
554
555 /*!
556 * Initialize some common fields in the Device Context structure.
557 */
558 VOID FASTCALL
559 DC_InitDC(HDC DCHandle)
560 {
561 // NtGdiRealizeDefaultPalette(DCHandle);
562
563 //// Removed for now.. See above brush and pen.
564 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
565 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
566 ////
567 //NtGdiSelectFont(DCHandle, hFont);
568
569 /*
570 {
571 int res;
572 res = CLIPPING_UpdateGCRegion(DCToInit);
573 ASSERT ( res != ERROR );
574 }
575 */
576
577 /* Set virtual resolution */
578 NtGdiSetVirtualResolution(DCHandle, 0, 0, 0, 0);
579 }
580
581 /*
582 * @unimplemented
583 */
584 BOOL
585 APIENTRY
586 NtGdiMakeInfoDC(
587 IN HDC hdc,
588 IN BOOL bSet)
589 {
590 UNIMPLEMENTED;
591 return FALSE;
592 }
593
594 HDC APIENTRY
595 NtGdiCreateCompatibleDC(HDC hDC)
596 {
597 PDC pdcNew, pdcOld;
598 PDC_ATTR pdcattrNew, pdcattrOld;
599 HDC hdcNew, DisplayDC = NULL;
600 HRGN hVisRgn;
601 UNICODE_STRING DriverName;
602 DWORD Layout = 0;
603 HSURF hsurf;
604
605 if (hDC == NULL)
606 {
607 RtlInitUnicodeString(&DriverName, L"DISPLAY");
608 DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
609 if (NULL == DisplayDC)
610 {
611 DPRINT1("Failed to create DisplayDC\n");
612 return NULL;
613 }
614 hDC = DisplayDC;
615 }
616
617 /* Allocate a new DC based on the original DC's device */
618 pdcOld = DC_LockDc(hDC);
619 if (NULL == pdcOld)
620 {
621 if (NULL != DisplayDC)
622 {
623 NtGdiDeleteObjectApp(DisplayDC);
624 }
625 DPRINT1("Failed to lock hDC\n");
626 return NULL;
627 }
628 pdcNew = DC_AllocDC(&pdcOld->rosdc.DriverName);
629 if (!pdcNew)
630 {
631 DPRINT1("Failed to create pdcNew\n");
632 DC_UnlockDc(pdcOld);
633 if (DisplayDC)
634 {
635 NtGdiDeleteObjectApp(DisplayDC);
636 }
637 return NULL;
638 }
639 hdcNew = pdcNew->BaseObject.hHmgr;
640
641 pdcattrOld = pdcOld->pdcattr;
642 pdcattrNew = pdcNew->pdcattr;
643
644 /* Copy information from original DC to new DC */
645 pdcNew->dclevel.hdcSave = hdcNew;
646
647 pdcNew->dhpdev = pdcOld->dhpdev;
648
649 pdcNew->rosdc.bitsPerPixel = pdcOld->rosdc.bitsPerPixel;
650
651 /* DriverName is copied in the AllocDC routine */
652 pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg;
653 pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt;
654 pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg;
655 pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt;
656
657 pdcNew->dctype = DC_TYPE_MEMORY; // Always!
658 hsurf = NtGdiGetStockObject(DEFAULT_BITMAP);
659 pdcNew->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
660 pdcNew->ppdev = pdcOld->ppdev;
661 pdcNew->dclevel.hpal = pdcOld->dclevel.hpal;
662
663 pdcattrNew->lTextAlign = pdcattrOld->lTextAlign;
664 pdcattrNew->lBkMode = pdcattrOld->lBkMode;
665 pdcattrNew->jBkMode = pdcattrOld->jBkMode;
666 pdcattrNew->jROP2 = pdcattrOld->jROP2;
667 pdcattrNew->dwLayout = pdcattrOld->dwLayout;
668 if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout;
669 pdcNew->dclevel.flPath = pdcOld->dclevel.flPath;
670 pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_;
671 pdcattrNew->iCS_CP = pdcattrOld->iCS_CP;
672
673 pdcNew->erclWindow.left = pdcNew->erclWindow.top = 0;
674 pdcNew->erclWindow.right = pdcNew->erclWindow.bottom = 1;
675
676 DC_UnlockDc(pdcNew);
677 DC_UnlockDc(pdcOld);
678 if (NULL != DisplayDC)
679 {
680 NtGdiDeleteObjectApp(DisplayDC);
681 }
682
683 hVisRgn = IntSysCreateRectRgn(0, 0, 1, 1);
684 if (hVisRgn)
685 {
686 GdiSelectVisRgn(hdcNew, hVisRgn);
687 REGION_FreeRgnByHandle(hVisRgn);
688 }
689 if (Layout) NtGdiSetLayout(hdcNew, -1, Layout);
690
691 DC_InitDC(hdcNew);
692 return hdcNew;
693 }
694
695
696 BOOL
697 APIENTRY
698 NtGdiDeleteObjectApp(HANDLE DCHandle)
699 {
700 /* Complete all pending operations */
701 NtGdiFlushUserBatch();
702
703 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
704
705 if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
706 return GreDeleteObject((HGDIOBJ) DCHandle);
707
708 if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
709
710 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
711 {
712 SetLastWin32Error(ERROR_INVALID_HANDLE);
713 return FALSE;
714 }
715
716 return IntGdiDeleteDC(DCHandle, FALSE);
717 }
718
719 BOOL
720 APIENTRY
721 NewNtGdiDeleteObjectApp(HANDLE DCHandle)
722 {
723 GDIOBJTYPE ObjType;
724
725 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
726
727 ObjType = GDI_HANDLE_GET_TYPE(DCHandle) >> GDI_ENTRY_UPPER_SHIFT;
728
729 if (GreGetObjectOwner( DCHandle, ObjType))
730 {
731 switch(ObjType)
732 {
733 case GDIObjType_DC_TYPE:
734 return IntGdiDeleteDC(DCHandle, FALSE);
735
736 case GDIObjType_RGN_TYPE:
737 case GDIObjType_SURF_TYPE:
738 case GDIObjType_PAL_TYPE:
739 case GDIObjType_LFONT_TYPE:
740 case GDIObjType_BRUSH_TYPE:
741 return GreDeleteObject((HGDIOBJ) DCHandle);
742
743 default:
744 return FALSE;
745 }
746 }
747 return (DCHandle != NULL);
748 }
749