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