- Check that all pins have been closed when the last filter reference is gone
[reactos.git] / reactos / subsystems / win32 / win32k / objects / font.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/font.c
5 * PURPOSE: Font
6 * PROGRAMMER:
7 */
8
9 /** Includes ******************************************************************/
10
11 #include <w32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /** Internal ******************************************************************/
17
18 DWORD
19 FASTCALL
20 GreGetCharacterPlacementW(
21 HDC hdc,
22 LPWSTR pwsz,
23 INT nCount,
24 INT nMaxExtent,
25 LPGCP_RESULTSW pgcpw,
26 DWORD dwFlags)
27 {
28 SIZE Size = {0,0};
29
30 if (!pgcpw)
31 {
32 if (GreGetTextExtentW( hdc, pwsz, nCount, &Size, 1))
33 return MAKELONG(Size.cx, Size.cy);
34 }
35 UNIMPLEMENTED;
36 return 0;
37 }
38
39 INT
40 FASTCALL
41 FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
42 {
43 if( Buffer == NULL ) return sizeof(LOGFONTW);
44
45 switch (Count)
46 {
47 case sizeof(ENUMLOGFONTEXDVW):
48 RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
49 &TFont->logfont,
50 sizeof(ENUMLOGFONTEXDVW));
51 break;
52 case sizeof(ENUMLOGFONTEXW):
53 RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
54 &TFont->logfont.elfEnumLogfontEx,
55 sizeof(ENUMLOGFONTEXW));
56 break;
57
58 case sizeof(EXTLOGFONTW):
59 case sizeof(ENUMLOGFONTW):
60 RtlCopyMemory((LPENUMLOGFONTW) Buffer,
61 &TFont->logfont.elfEnumLogfontEx.elfLogFont,
62 sizeof(ENUMLOGFONTW));
63 break;
64
65 case sizeof(LOGFONTW):
66 RtlCopyMemory((LPLOGFONTW) Buffer,
67 &TFont->logfont.elfEnumLogfontEx.elfLogFont,
68 sizeof(LOGFONTW));
69 break;
70
71 default:
72 SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
73 return 0;
74 }
75 return Count;
76 }
77
78 DWORD
79 FASTCALL
80 IntGetCharDimensions(HDC hdc, PTEXTMETRICW ptm, PDWORD height)
81 {
82 PDC pdc;
83 PDC_ATTR pdcattr;
84 PTEXTOBJ TextObj;
85 SIZE sz;
86 TMW_INTERNAL tmwi;
87 BOOL Good;
88
89 static const WCHAR alphabet[] = {
90 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
91 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
92 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
93
94 if(!ftGdiGetTextMetricsW(hdc, &tmwi)) return 0;
95
96 pdc = DC_LockDc(hdc);
97
98 if (!pdc) return 0;
99
100 pdcattr = pdc->pdcattr;
101
102 TextObj = RealizeFontInit(pdcattr->hlfntNew);
103 if ( !TextObj )
104 {
105 DC_UnlockDc(pdc);
106 return 0;
107 }
108 Good = TextIntGetTextExtentPoint(pdc, TextObj, alphabet, 52, 0, NULL, 0, &sz);
109 TEXTOBJ_UnlockText(TextObj);
110 DC_UnlockDc(pdc);
111
112 if (!Good) return 0;
113 if (ptm) *ptm = tmwi.TextMetric;
114 if (height) *height = tmwi.TextMetric.tmHeight;
115
116 return (sz.cx / 26 + 1) / 2;
117 }
118
119
120 DWORD
121 FASTCALL
122 IntGetFontLanguageInfo(PDC Dc)
123 {
124 PDC_ATTR pdcattr;
125 FONTSIGNATURE fontsig;
126 static const DWORD GCP_DBCS_MASK=0x003F0000,
127 GCP_DIACRITIC_MASK=0x00000000,
128 FLI_GLYPHS_MASK=0x00000000,
129 GCP_GLYPHSHAPE_MASK=0x00000040,
130 GCP_KASHIDA_MASK=0x00000000,
131 GCP_LIGATE_MASK=0x00000000,
132 GCP_USEKERNING_MASK=0x00000000,
133 GCP_REORDER_MASK=0x00000060;
134
135 DWORD result=0;
136
137 ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
138
139 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
140 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
141 result|=GCP_DBCS;
142
143 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
144 result|=GCP_DIACRITIC;
145
146 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
147 result|=FLI_GLYPHS;
148
149 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
150 result|=GCP_GLYPHSHAPE;
151
152 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
153 result|=GCP_KASHIDA;
154
155 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
156 result|=GCP_LIGATE;
157
158 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
159 result|=GCP_USEKERNING;
160
161 pdcattr = Dc->pdcattr;
162
163 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
164 if ( pdcattr->lTextAlign & TA_RTLREADING )
165 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
166 result|=GCP_REORDER;
167
168 return result;
169 }
170
171 PTEXTOBJ
172 FASTCALL
173 RealizeFontInit(HFONT hFont)
174 {
175 NTSTATUS Status = STATUS_SUCCESS;
176 PTEXTOBJ pTextObj;
177
178 pTextObj = TEXTOBJ_LockText(hFont);
179
180 if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT))
181 {
182 Status = TextIntRealizeFont(hFont, pTextObj);
183 if (!NT_SUCCESS(Status))
184 {
185 TEXTOBJ_UnlockText(pTextObj);
186 return NULL;
187 }
188 }
189 return pTextObj;
190 }
191
192 /** Functions ******************************************************************/
193
194 INT
195 APIENTRY
196 NtGdiAddFontResourceW(
197 IN WCHAR *pwszFiles,
198 IN ULONG cwc,
199 IN ULONG cFiles,
200 IN FLONG fl,
201 IN DWORD dwPidTid,
202 IN OPTIONAL DESIGNVECTOR *pdv)
203 {
204 UNICODE_STRING SafeFileName;
205 PWSTR src;
206 NTSTATUS Status;
207 int Ret;
208
209 /* FIXME - Protect with SEH? */
210 RtlInitUnicodeString(&SafeFileName, pwszFiles);
211
212 /* Reserve for prepending '\??\' */
213 SafeFileName.Length += 4 * sizeof(WCHAR);
214 SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
215
216 src = SafeFileName.Buffer;
217 SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
218 if(!SafeFileName.Buffer)
219 {
220 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
221 return 0;
222 }
223
224 /* Prepend '\??\' */
225 RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
226
227 Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
228 if(!NT_SUCCESS(Status))
229 {
230 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
231 SetLastNtError(Status);
232 return 0;
233 }
234
235 Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
236
237 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
238 return Ret;
239 }
240
241 /*
242 * @unimplemented
243 */
244 DWORD
245 APIENTRY
246 NtGdiGetCharacterPlacementW(
247 IN HDC hdc,
248 IN LPWSTR pwsz,
249 IN INT nCount,
250 IN INT nMaxExtent,
251 IN OUT LPGCP_RESULTSW pgcpw,
252 IN DWORD dwFlags)
253 {
254 UNIMPLEMENTED;
255 return 0;
256 }
257
258 DWORD
259 APIENTRY
260 NtGdiGetFontData(
261 HDC hDC,
262 DWORD Table,
263 DWORD Offset,
264 LPVOID Buffer,
265 DWORD Size)
266 {
267 PDC Dc;
268 PDC_ATTR pdcattr;
269 HFONT hFont;
270 PTEXTOBJ TextObj;
271 PFONTGDI FontGdi;
272 DWORD Result = GDI_ERROR;
273 NTSTATUS Status = STATUS_SUCCESS;
274
275 if (Buffer && Size)
276 {
277 _SEH2_TRY
278 {
279 ProbeForRead(Buffer, Size, 1);
280 }
281 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
282 {
283 Status = _SEH2_GetExceptionCode();
284 }
285 _SEH2_END
286 }
287
288 if (!NT_SUCCESS(Status)) return Result;
289
290 Dc = DC_LockDc(hDC);
291 if (Dc == NULL)
292 {
293 SetLastWin32Error(ERROR_INVALID_HANDLE);
294 return GDI_ERROR;
295 }
296 pdcattr = Dc->pdcattr;
297
298 hFont = pdcattr->hlfntNew;
299 TextObj = RealizeFontInit(hFont);
300 DC_UnlockDc(Dc);
301
302 if (TextObj == NULL)
303 {
304 SetLastWin32Error(ERROR_INVALID_HANDLE);
305 return GDI_ERROR;
306 }
307
308 FontGdi = ObjToGDI(TextObj->Font, FONT);
309
310 Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
311
312 TEXTOBJ_UnlockText(TextObj);
313
314 return Result;
315 }
316
317 /*
318 * @implemented
319 */
320 DWORD
321 APIENTRY
322 NtGdiGetFontUnicodeRanges(
323 IN HDC hdc,
324 OUT OPTIONAL LPGLYPHSET pgs)
325 {
326 PDC pDc;
327 PDC_ATTR pdcattr;
328 HFONT hFont;
329 PTEXTOBJ TextObj;
330 PFONTGDI FontGdi;
331 DWORD Size = 0;
332 PGLYPHSET pgsSafe;
333 NTSTATUS Status = STATUS_SUCCESS;
334
335 pDc = DC_LockDc(hdc);
336 if (!pDc)
337 {
338 SetLastWin32Error(ERROR_INVALID_HANDLE);
339 return 0;
340 }
341
342 pdcattr = pDc->pdcattr;
343
344 hFont = pdcattr->hlfntNew;
345 TextObj = RealizeFontInit(hFont);
346
347 if ( TextObj == NULL)
348 {
349 SetLastWin32Error(ERROR_INVALID_HANDLE);
350 goto Exit;
351 }
352 FontGdi = ObjToGDI(TextObj->Font, FONT);
353
354 Size = ftGetFontUnicodeRanges( FontGdi, NULL);
355
356 if (Size && pgs)
357 {
358 pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
359 if (!pgsSafe)
360 {
361 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
362 Size = 0;
363 goto Exit;
364 }
365
366 Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
367
368 if (Size)
369 {
370 _SEH2_TRY
371 {
372 ProbeForWrite(pgs, Size, 1);
373 RtlCopyMemory(pgs, pgsSafe, Size);
374 }
375 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
376 {
377 Status = _SEH2_GetExceptionCode();
378 }
379 _SEH2_END
380
381 if (!NT_SUCCESS(Status)) Size = 0;
382 }
383 ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
384 }
385 Exit:
386 TEXTOBJ_UnlockText(TextObj);
387 DC_UnlockDc(pDc);
388 return Size;
389 }
390
391 ULONG
392 APIENTRY
393 NtGdiGetGlyphOutline(
394 IN HDC hdc,
395 IN WCHAR wch,
396 IN UINT iFormat,
397 OUT LPGLYPHMETRICS pgm,
398 IN ULONG cjBuf,
399 OUT OPTIONAL PVOID UnsafeBuf,
400 IN LPMAT2 pmat2,
401 IN BOOL bIgnoreRotation)
402 {
403 ULONG Ret = GDI_ERROR;
404 PDC dc;
405 PVOID pvBuf = NULL;
406 GLYPHMETRICS gm;
407 NTSTATUS Status = STATUS_SUCCESS;
408
409 dc = DC_LockDc(hdc);
410 if (!dc)
411 {
412 SetLastWin32Error(ERROR_INVALID_HANDLE);
413 return GDI_ERROR;
414 }
415
416 if (UnsafeBuf && cjBuf)
417 {
418 pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT);
419 if (!pvBuf)
420 {
421 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
422 goto Exit;
423 }
424 }
425
426 Ret = ftGdiGetGlyphOutline( dc,
427 wch,
428 iFormat,
429 pgm ? &gm : NULL,
430 cjBuf,
431 pvBuf,
432 pmat2,
433 bIgnoreRotation);
434
435 if (pvBuf)
436 {
437 _SEH2_TRY
438 {
439 ProbeForWrite(UnsafeBuf, cjBuf, 1);
440 RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
441 }
442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
443 {
444 Status = _SEH2_GetExceptionCode();
445 }
446 _SEH2_END
447
448 ExFreePoolWithTag(pvBuf, TAG_GDITEXT);
449 }
450
451 if (pgm)
452 {
453 _SEH2_TRY
454 {
455 ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
456 RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
457 }
458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
459 {
460 Status = _SEH2_GetExceptionCode();
461 }
462 _SEH2_END
463 }
464
465 if (! NT_SUCCESS(Status))
466 {
467 SetLastWin32Error(ERROR_INVALID_PARAMETER);
468 Ret = GDI_ERROR;
469 }
470
471 Exit:
472 DC_UnlockDc(dc);
473 return Ret;
474 }
475
476 DWORD
477 APIENTRY
478 NtGdiGetKerningPairs(HDC hDC,
479 ULONG NumPairs,
480 LPKERNINGPAIR krnpair)
481 {
482 PDC dc;
483 PDC_ATTR pdcattr;
484 PTEXTOBJ TextObj;
485 PFONTGDI FontGDI;
486 DWORD Count;
487 KERNINGPAIR *pKP;
488 NTSTATUS Status = STATUS_SUCCESS;
489
490 dc = DC_LockDc(hDC);
491 if (!dc)
492 {
493 SetLastWin32Error(ERROR_INVALID_HANDLE);
494 return 0;
495 }
496
497 pdcattr = dc->pdcattr;
498 TextObj = RealizeFontInit(pdcattr->hlfntNew);
499 DC_UnlockDc(dc);
500
501 if (!TextObj)
502 {
503 SetLastWin32Error(ERROR_INVALID_HANDLE);
504 return 0;
505 }
506
507 FontGDI = ObjToGDI(TextObj->Font, FONT);
508 TEXTOBJ_UnlockText(TextObj);
509
510 Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
511
512 if ( Count && krnpair )
513 {
514 if (Count > NumPairs)
515 {
516 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
517 return 0;
518 }
519 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), TAG_GDITEXT);
520 if (!pKP)
521 {
522 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
523 return 0;
524 }
525 ftGdiGetKerningPairs(FontGDI,Count,pKP);
526 _SEH2_TRY
527 {
528 ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1);
529 RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
530 }
531 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
532 {
533 Status = _SEH2_GetExceptionCode();
534 }
535 _SEH2_END
536 if (!NT_SUCCESS(Status))
537 {
538 SetLastWin32Error(ERROR_INVALID_PARAMETER);
539 Count = 0;
540 }
541 ExFreePoolWithTag(pKP,TAG_GDITEXT);
542 }
543 return Count;
544 }
545
546 /*
547 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
548 472, this is NtGdiGetOutlineTextMetricsInternalW.
549 */
550 ULONG
551 APIENTRY
552 NtGdiGetOutlineTextMetricsInternalW (HDC hDC,
553 ULONG Data,
554 OUTLINETEXTMETRICW *otm,
555 TMDIFF *Tmd)
556 {
557 PDC dc;
558 PDC_ATTR pdcattr;
559 PTEXTOBJ TextObj;
560 PFONTGDI FontGDI;
561 HFONT hFont = 0;
562 ULONG Size;
563 OUTLINETEXTMETRICW *potm;
564 NTSTATUS Status = STATUS_SUCCESS;
565
566 dc = DC_LockDc(hDC);
567 if (!dc)
568 {
569 SetLastWin32Error(ERROR_INVALID_HANDLE);
570 return 0;
571 }
572 pdcattr = dc->pdcattr;
573 hFont = pdcattr->hlfntNew;
574 TextObj = RealizeFontInit(hFont);
575 DC_UnlockDc(dc);
576 if (!TextObj)
577 {
578 SetLastWin32Error(ERROR_INVALID_HANDLE);
579 return 0;
580 }
581 FontGDI = ObjToGDI(TextObj->Font, FONT);
582 TEXTOBJ_UnlockText(TextObj);
583 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
584 if (!otm) return Size;
585 if (Size > Data)
586 {
587 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
588 return 0;
589 }
590 potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
591 if (!potm)
592 {
593 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
594 return 0;
595 }
596 IntGetOutlineTextMetrics(FontGDI, Size, potm);
597 if (otm)
598 {
599 _SEH2_TRY
600 {
601 ProbeForWrite(otm, Size, 1);
602 RtlCopyMemory(otm, potm, Size);
603 }
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
605 {
606 Status = _SEH2_GetExceptionCode();
607 }
608 _SEH2_END
609
610 if (!NT_SUCCESS(Status))
611 {
612 SetLastWin32Error(ERROR_INVALID_PARAMETER);
613 Size = 0;
614 }
615 }
616 ExFreePoolWithTag(potm,TAG_GDITEXT);
617 return Size;
618 }
619
620 W32KAPI
621 BOOL
622 APIENTRY
623 NtGdiGetFontResourceInfoInternalW(
624 IN LPWSTR pwszFiles,
625 IN ULONG cwc,
626 IN ULONG cFiles,
627 IN UINT cjIn,
628 OUT LPDWORD pdwBytes,
629 OUT LPVOID pvBuf,
630 IN DWORD dwType)
631 {
632 NTSTATUS Status = STATUS_SUCCESS;
633 DWORD dwBytes;
634 UNICODE_STRING SafeFileNames;
635 BOOL bRet = FALSE;
636 ULONG cbStringSize;
637
638 union
639 {
640 LOGFONTW logfontw;
641 WCHAR FullName[LF_FULLFACESIZE];
642 } Buffer;
643
644 /* FIXME: handle cFiles > 0 */
645
646 /* Check for valid dwType values
647 dwType == 4 seems to be handled by gdi32 only */
648 if (dwType == 4 || dwType > 5)
649 {
650 SetLastWin32Error(ERROR_INVALID_PARAMETER);
651 return FALSE;
652 }
653
654 /* Allocate a safe unicode string buffer */
655 cbStringSize = cwc * sizeof(WCHAR);
656 SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
657 SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
658 cbStringSize,
659 TAG('R','T','S','U'));
660 if (!SafeFileNames.Buffer)
661 {
662 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
663 return FALSE;
664 }
665
666 /* Check buffers and copy pwszFiles to safe unicode string */
667 _SEH2_TRY
668 {
669 ProbeForRead(pwszFiles, cbStringSize, 1);
670 ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
671 ProbeForWrite(pvBuf, cjIn, 1);
672
673 RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
674 }
675 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
676 {
677 Status = _SEH2_GetExceptionCode();
678 }
679 _SEH2_END
680
681 if(!NT_SUCCESS(Status))
682 {
683 SetLastNtError(Status);
684 /* Free the string buffer for the safe filename */
685 ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
686 return FALSE;
687 }
688
689 /* Do the actual call */
690 bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
691
692 /* Check if succeeded and the buffer is big enough */
693 if (bRet && cjIn >= dwBytes)
694 {
695 /* Copy the data back to caller */
696 _SEH2_TRY
697 {
698 /* Buffers are already probed */
699 RtlCopyMemory(pvBuf, &Buffer, dwBytes);
700 *pdwBytes = dwBytes;
701 }
702 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
703 {
704 Status = _SEH2_GetExceptionCode();
705 }
706 _SEH2_END
707
708 if(!NT_SUCCESS(Status))
709 {
710 SetLastNtError(Status);
711 bRet = FALSE;
712 }
713 }
714
715 /* Free the string for the safe filenames */
716 ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
717
718 return bRet;
719 }
720
721 /*
722 * @unimplemented
723 */
724 BOOL
725 APIENTRY
726 NtGdiGetRealizationInfo(
727 IN HDC hdc,
728 OUT PREALIZATION_INFO pri,
729 IN HFONT hf)
730 {
731 PDC pDc;
732 PTEXTOBJ pTextObj;
733 PFONTGDI pFontGdi;
734 PDC_ATTR pdcattr;
735 BOOL Ret = FALSE;
736 INT i = 0;
737 REALIZATION_INFO ri;
738
739 pDc = DC_LockDc(hdc);
740 if (!pDc)
741 {
742 SetLastWin32Error(ERROR_INVALID_HANDLE);
743 return 0;
744 }
745 pdcattr = pDc->pdcattr;
746 pTextObj = RealizeFontInit(pdcattr->hlfntNew);
747 pFontGdi = ObjToGDI(pTextObj->Font, FONT);
748 TEXTOBJ_UnlockText(pTextObj);
749 DC_UnlockDc(pDc);
750
751 Ret = ftGdiRealizationInfo(pFontGdi, &ri);
752 if (Ret)
753 {
754 if (pri)
755 {
756 NTSTATUS Status = STATUS_SUCCESS;
757 _SEH2_TRY
758 {
759 ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1);
760 RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO));
761 }
762 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
763 {
764 Status = _SEH2_GetExceptionCode();
765 }
766 _SEH2_END
767
768 if(!NT_SUCCESS(Status))
769 {
770 SetLastNtError(Status);
771 return FALSE;
772 }
773 }
774 do
775 {
776 if (GdiHandleTable->cfPublic[i].hf == hf)
777 {
778 GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology;
779 GdiHandleTable->cfPublic[i].iUniq = ri.iUniq;
780 GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown;
781 GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount;
782 GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION;
783 }
784 i++;
785 }
786 while ( i < GDI_CFONT_MAX );
787 }
788 return Ret;
789 }
790
791 HFONT
792 APIENTRY
793 NtGdiHfontCreate(
794 IN PENUMLOGFONTEXDVW pelfw,
795 IN ULONG cjElfw,
796 IN LFTYPE lft,
797 IN FLONG fl,
798 IN PVOID pvCliData )
799 {
800 ENUMLOGFONTEXDVW SafeLogfont;
801 HFONT hNewFont;
802 PTEXTOBJ TextObj;
803 NTSTATUS Status = STATUS_SUCCESS;
804
805 /* Silence GCC warnings */
806 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
807 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
808
809 if (!pelfw)
810 {
811 return NULL;
812 }
813
814 _SEH2_TRY
815 {
816 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
817 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
818 }
819 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
820 {
821 Status = _SEH2_GetExceptionCode();
822 }
823 _SEH2_END
824
825 if (!NT_SUCCESS(Status))
826 {
827 return NULL;
828 }
829
830 TextObj = TEXTOBJ_AllocTextWithHandle();
831 if (!TextObj)
832 {
833 return NULL;
834 }
835 hNewFont = TextObj->BaseObject.hHmgr;
836
837 TextObj->lft = lft;
838 TextObj->fl = fl;
839 RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
840
841 if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
842 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
843 {
844 /* this should really depend on whether GM_ADVANCED is set */
845 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
846 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
847 }
848 TEXTOBJ_UnlockText(TextObj);
849
850 if (pvCliData && hNewFont)
851 {
852 // FIXME: use GDIOBJ_InsertUserData
853 KeEnterCriticalRegion();
854 {
855 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hNewFont);
856 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
857 Entry->UserData = pvCliData;
858 }
859 KeLeaveCriticalRegion();
860 }
861
862 return hNewFont;
863 }
864
865 /*
866 * @implemented
867 */
868 HFONT
869 APIENTRY
870 NtGdiSelectFont(
871 IN HDC hDC,
872 IN HFONT hFont)
873 {
874 PDC pDC;
875 PDC_ATTR pdcattr;
876 HFONT hOrgFont = NULL;
877
878 if (hDC == NULL || hFont == NULL) return NULL;
879
880 pDC = DC_LockDc(hDC);
881 if (!pDC)
882 {
883 return NULL;
884 }
885
886 pdcattr = pDC->pdcattr;
887
888 /* FIXME: what if not successful? */
889 if(NT_SUCCESS(TextIntRealizeFont((HFONT)hFont,NULL)))
890 {
891 hOrgFont = pdcattr->hlfntNew;
892 pdcattr->hlfntNew = hFont;
893 }
894
895 DC_UnlockDc(pDC);
896
897 return hOrgFont;
898 }
899
900
901 /* EOF */