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