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