* Sync up to trunk head (r65353).
[reactos.git] / win32ss / gdi / gdi32 / objects / text.c
1 #include <precomp.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 /*
7 * @implemented
8 */
9 BOOL
10 WINAPI
11 TextOutA(
12 _In_ HDC hdc,
13 _In_ INT nXStart,
14 _In_ INT nYStart,
15 _In_reads_(cchString) LPCSTR lpString,
16 _In_ INT cchString)
17 {
18 ANSI_STRING StringA;
19 UNICODE_STRING StringU;
20 BOOL bResult;
21
22 if (lpString != NULL)
23 {
24 RtlInitAnsiString(&StringA, (LPSTR)lpString);
25 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
26 }
27 else
28 {
29 StringU.Buffer = NULL;
30 }
31
32 bResult = TextOutW(hdc, nXStart, nYStart, StringU.Buffer, cchString);
33
34 RtlFreeUnicodeString(&StringU);
35 return bResult;
36 }
37
38
39 /*
40 * @implemented
41 */
42 BOOL
43 WINAPI
44 TextOutW(
45 _In_ HDC hdc,
46 _In_ INT nXStart,
47 _In_ INT nYStart,
48 _In_reads_(cchString) LPCWSTR lpString,
49 _In_ INT cchString)
50 {
51 return NtGdiExtTextOutW(hdc,
52 nXStart,
53 nYStart,
54 0, NULL,
55 (LPWSTR)lpString,
56 cchString,
57 NULL,
58 0);
59 }
60
61
62 /*
63 * @unimplemented
64 */
65 BOOL
66 WINAPI
67 PolyTextOutA(
68 _In_ HDC hdc,
69 _In_reads_(cStrings) const POLYTEXTA *pptxt,
70 _In_ INT cStrings)
71 {
72 for (; cStrings>0; cStrings--, pptxt++)
73 {
74 if (!ExtTextOutA(hdc,
75 pptxt->x,
76 pptxt->y,
77 pptxt->uiFlags,
78 &pptxt->rcl,
79 pptxt->lpstr,
80 pptxt->n,
81 pptxt->pdx))
82 {
83 return FALSE;
84 }
85 }
86
87 return TRUE;
88 }
89
90
91 /*
92 * @unimplemented
93 */
94 BOOL
95 WINAPI
96 PolyTextOutW(
97 _In_ HDC hdc,
98 _In_reads_(cStrings) const POLYTEXTW *pptxt,
99 _In_ INT cStrings)
100 {
101 for (; cStrings>0; cStrings--, pptxt++)
102 {
103 if (!ExtTextOutW(hdc,
104 pptxt->x,
105 pptxt->y,
106 pptxt->uiFlags,
107 &pptxt->rcl,
108 pptxt->lpstr,
109 pptxt->n,
110 pptxt->pdx))
111 {
112 return FALSE;
113 }
114 }
115
116 return TRUE;
117 }
118
119
120 /*
121 * @implemented
122 */
123 DWORD
124 WINAPI
125 GdiGetCodePage(
126 _In_ HDC hdc)
127 {
128 PDC_ATTR pdcattr;
129
130 /* Get the DC attribute */
131 pdcattr = GdiGetDcAttr(hdc);
132 if (pdcattr == NULL)
133 {
134 SetLastError(ERROR_INVALID_PARAMETER);
135 return 0;
136 }
137
138 if (pdcattr->ulDirty_ & DIRTY_CHARSET)
139 return LOWORD(NtGdiGetCharSet(hdc));
140
141 return LOWORD(pdcattr->iCS_CP);
142 }
143
144
145 /*
146 * @unimplemented
147 */
148 INT
149 WINAPI
150 GetTextCharacterExtra(
151 _In_ HDC hdc)
152 {
153 PDC_ATTR pdcattr;
154
155 /* Get the DC attribute */
156 pdcattr = GdiGetDcAttr(hdc);
157 if (pdcattr == NULL)
158 {
159 /* Do not set LastError here! */
160 return 0x8000000;
161 }
162
163 return pdcattr->lTextExtra;
164 }
165
166
167 /*
168 * @implemented
169 */
170 INT
171 WINAPI
172 GetTextCharset(
173 _In_ HDC hdc)
174 {
175 /* MSDN docs say this is equivalent */
176 return NtGdiGetTextCharsetInfo(hdc,NULL,0);
177 }
178
179
180 /*
181 * @implemented
182 */
183 BOOL
184 WINAPI
185 GetTextMetricsA(
186 _In_ HDC hdc,
187 _Out_ LPTEXTMETRICA lptm)
188 {
189 TMW_INTERNAL tmwi;
190
191 if (!NtGdiGetTextMetricsW(hdc, &tmwi, sizeof(TMW_INTERNAL)))
192 {
193 return FALSE;
194 }
195
196 FONT_TextMetricWToA(&tmwi.TextMetric, lptm);
197 return TRUE;
198 }
199
200
201 /*
202 * @implemented
203 */
204 BOOL
205 WINAPI
206 GetTextMetricsW(
207 _In_ HDC hdc,
208 _Out_ LPTEXTMETRICW lptm)
209 {
210 TMW_INTERNAL tmwi;
211
212 if (!NtGdiGetTextMetricsW(hdc, &tmwi, sizeof(TMW_INTERNAL)))
213 {
214 return FALSE;
215 }
216
217 *lptm = tmwi.TextMetric;
218 return TRUE;
219 }
220
221
222 /*
223 * @implemented
224 */
225 BOOL
226 APIENTRY
227 GetTextExtentPointA(
228 _In_ HDC hdc,
229 _In_reads_(cchString) LPCSTR lpString,
230 _In_ INT cchString,
231 _Out_ LPSIZE lpsz)
232 {
233 ANSI_STRING StringA;
234 UNICODE_STRING StringU;
235 BOOL ret;
236
237 RtlInitAnsiString(&StringA, (LPSTR)lpString);
238 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
239
240 ret = GetTextExtentPointW(hdc, StringU.Buffer, cchString, lpsz);
241
242 RtlFreeUnicodeString(&StringU);
243
244 return ret;
245 }
246
247
248 /*
249 * @implemented
250 */
251 BOOL
252 APIENTRY
253 GetTextExtentPointW(
254 _In_ HDC hdc,
255 _In_reads_(cchString) LPCWSTR lpString,
256 _In_ INT cchString,
257 _Out_ LPSIZE lpsz)
258 {
259 return NtGdiGetTextExtent(hdc, (LPWSTR)lpString, cchString, lpsz, 0);
260 }
261
262
263 /*
264 * @implemented
265 */
266 BOOL
267 WINAPI
268 GetTextExtentExPointW(
269 _In_ HDC hdc,
270 _In_reads_(cchString) LPCWSTR lpszString,
271 _In_ INT cchString,
272 _In_ INT nMaxExtent,
273 _Out_opt_ LPINT lpnFit,
274 _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx,
275 _Out_ LPSIZE lpSize)
276 {
277
278 /* Windows doesn't check nMaxExtent validity in unicode version */
279 if (nMaxExtent < -1)
280 {
281 DPRINT("nMaxExtent is invalid: %d\n", nMaxExtent);
282 }
283
284 return NtGdiGetTextExtentExW (
285 hdc, (LPWSTR)lpszString, cchString, nMaxExtent, (PULONG)lpnFit, (PULONG)lpnDx, lpSize, 0 );
286 }
287
288
289 /*
290 * @implemented
291 */
292 BOOL
293 WINAPI
294 GetTextExtentExPointWPri(
295 _In_ HDC hdc,
296 _In_reads_(cwc) LPWSTR lpwsz,
297 _In_ ULONG cwc,
298 _In_ ULONG dxMax,
299 _Out_opt_ ULONG *pcCh,
300 _Out_writes_to_opt_(cwc, *pcCh) PULONG pdxOut,
301 _In_ LPSIZE psize)
302 {
303 return NtGdiGetTextExtentExW(hdc, lpwsz, cwc, dxMax, pcCh, pdxOut, psize, 0);
304 }
305
306 /*
307 * @implemented
308 */
309 BOOL
310 WINAPI
311 GetTextExtentExPointA(
312 _In_ HDC hdc,
313 _In_reads_(cchString) LPCSTR lpszStr,
314 _In_ INT cchString,
315 _In_ INT nMaxExtent,
316 _Out_opt_ LPINT lpnFit,
317 _Out_writes_to_opt_ (cchString, *lpnFit) LPINT lpnDx,
318 _Out_ LPSIZE lpSize)
319 {
320 NTSTATUS Status;
321 LPWSTR lpszStrW;
322 BOOL bResult = FALSE;
323
324 if (nMaxExtent < -1)
325 {
326 SetLastError(ERROR_INVALID_PARAMETER);
327 return FALSE;
328 }
329
330 Status = HEAP_strdupA2W(&lpszStrW, lpszStr);
331 if (!NT_SUCCESS (Status))
332 {
333 SetLastError(RtlNtStatusToDosError(Status));
334 return FALSE;
335 }
336
337 bResult = NtGdiGetTextExtentExW(hdc,
338 lpszStrW,
339 cchString,
340 nMaxExtent,
341 (PULONG)lpnFit,
342 (PULONG)lpnDx,
343 lpSize,
344 0);
345
346 HEAP_free(lpszStrW);
347
348 return bResult;
349 }
350
351
352 /*
353 * @implemented
354 */
355 BOOL
356 WINAPI
357 GetTextExtentPoint32A(
358 _In_ HDC hdc,
359 _In_reads_(cchString) LPCSTR lpString,
360 _In_ INT cchString,
361 _Out_ LPSIZE lpSize)
362 {
363 ANSI_STRING StringA;
364 UNICODE_STRING StringU;
365 BOOL ret;
366
367 StringA.Buffer = (LPSTR)lpString;
368 StringA.Length = cchString;
369 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
370
371 ret = GetTextExtentPoint32W(hdc, StringU.Buffer, cchString, lpSize);
372
373 RtlFreeUnicodeString(&StringU);
374
375 return ret;
376 }
377
378
379 /*
380 * @implemented
381 */
382 BOOL
383 WINAPI
384 GetTextExtentPoint32W(
385 _In_ HDC hdc,
386 _In_reads_(cchString) LPCWSTR lpString,
387 _In_ int cchString,
388 _Out_ LPSIZE lpSize)
389 {
390 return NtGdiGetTextExtent(hdc, (LPWSTR)lpString, cchString, lpSize, 0);
391 }
392
393 /*
394 * @implemented
395 */
396 BOOL
397 WINAPI
398 GetTextExtentExPointI(
399 _In_ HDC hdc,
400 _In_reads_(cgi) LPWORD pgiIn,
401 _In_ INT cgi,
402 _In_ INT nMaxExtent,
403 _Out_opt_ LPINT lpnFit,
404 _Out_writes_to_opt_(cwchString, *lpnFit) LPINT lpnDx,
405 _Out_ LPSIZE lpSize)
406 {
407 return NtGdiGetTextExtentExW(hdc,
408 pgiIn,
409 cgi,
410 nMaxExtent,
411 (PULONG)lpnFit,
412 (PULONG)lpnDx,
413 lpSize,
414 GTEF_INDICES);
415 }
416
417 /*
418 * @implemented
419 */
420 BOOL
421 WINAPI
422 GetTextExtentPointI(
423 _In_ HDC hdc,
424 _In_reads_(cgi) LPWORD pgiIn,
425 _In_ int cgi,
426 _Out_ LPSIZE lpSize)
427 {
428 return NtGdiGetTextExtent(hdc, pgiIn, cgi, lpSize, GTEF_INDICES);
429 }
430
431 /*
432 * @implemented
433 */
434 BOOL
435 WINAPI
436 ExtTextOutA(
437 _In_ HDC hdc,
438 _In_ INT x,
439 _In_ INT y,
440 _In_ UINT fuOptions,
441 _In_opt_ const RECT *lprc,
442 _In_reads_opt_(cch) LPCSTR lpString,
443 _In_ UINT cch,
444 _In_reads_opt_(cch) const INT *lpDx)
445 {
446 ANSI_STRING StringA;
447 UNICODE_STRING StringU;
448 BOOL ret;
449
450 RtlInitAnsiString(&StringA, (LPSTR)lpString);
451 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
452
453 ret = ExtTextOutW(hdc, x, y, fuOptions, lprc, StringU.Buffer, cch, lpDx);
454
455 RtlFreeUnicodeString(&StringU);
456
457 return ret;
458 }
459
460
461 /*
462 * @implemented
463 */
464 BOOL
465 WINAPI
466 ExtTextOutW(
467 _In_ HDC hdc,
468 _In_ INT x,
469 _In_ INT y,
470 _In_ UINT fuOptions,
471 _In_opt_ const RECT *lprc,
472 _In_reads_opt_(cwc) LPCWSTR lpString,
473 _In_ UINT cwc,
474 _In_reads_opt_(cwc) const INT *lpDx)
475 {
476 return NtGdiExtTextOutW(hdc,
477 x,
478 y,
479 fuOptions,
480 (LPRECT)lprc,
481 (LPWSTR)lpString,
482 cwc,
483 (LPINT)lpDx,
484 0);
485 }
486
487
488 /*
489 * @implemented
490 */
491 INT
492 WINAPI
493 GetTextFaceW(
494 _In_ HDC hdc,
495 _In_ INT cwcMax,
496 _Out_writes_to_opt_(cwcMax, return) LPWSTR pFaceName)
497 {
498 /* Validate parameters */
499 if (pFaceName && cwcMax <= 0)
500 {
501 /* Set last error and return failure */
502 GdiSetLastError(ERROR_INVALID_PARAMETER);
503 return 0;
504 }
505
506 /* Forward to kernel */
507 return NtGdiGetTextFaceW(hdc, cwcMax, pFaceName, FALSE);
508 }
509
510
511 /*
512 * @implemented
513 */
514 INT
515 WINAPI
516 GetTextFaceA(
517 _In_ HDC hdc,
518 _In_ INT cchMax,
519 _Out_writes_to_opt_(cchMax, return) LPSTR lpName)
520 {
521 INT res;
522 LPWSTR nameW;
523
524 /* Validate parameters */
525 if (lpName && cchMax <= 0)
526 {
527 /* Set last error and return failure */
528 GdiSetLastError(ERROR_INVALID_PARAMETER);
529 return 0;
530 }
531
532 res = GetTextFaceW(hdc, 0, NULL);
533 nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
534 if (nameW == NULL)
535 {
536 return 0;
537 }
538
539 GetTextFaceW( hdc, res, nameW );
540
541 if (lpName)
542 {
543 if (cchMax && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, lpName, cchMax, NULL, NULL))
544 lpName[cchMax-1] = 0;
545 res = strlen(lpName);
546 }
547 else
548 {
549 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
550 }
551
552 HeapFree( GetProcessHeap(), 0, nameW );
553 return res;
554 }
555
556
557 /*
558 * @implemented
559 */
560 INT
561 WINAPI
562 GetTextFaceAliasW(
563 _In_ HDC hdc,
564 _In_ INT cwcMax,
565 _Out_writes_to_opt_(cwcMax, return) LPWSTR pszOut)
566 {
567 if (pszOut && !cwcMax)
568 {
569 GdiSetLastError(ERROR_INVALID_PARAMETER);
570 return 0;
571 }
572
573 return NtGdiGetTextFaceW(hdc, cwcMax, pszOut, TRUE);
574 }
575
576
577 BOOL
578 WINAPI
579 GetFontResourceInfoW(
580 _In_z_ LPCWSTR lpFileName,
581 _Inout_ DWORD *pdwBufSize,
582 _Out_writes_to_(*pdwBufSize, *pdwBufSize) PVOID lpBuffer,
583 _In_ DWORD dwType)
584 {
585 BOOL bRet;
586 UNICODE_STRING NtFileName;
587
588 if (!lpFileName || !pdwBufSize || !lpBuffer)
589 {
590 SetLastError(ERROR_INVALID_PARAMETER);
591 return FALSE;
592 }
593
594 if (!RtlDosPathNameToNtPathName_U(lpFileName,
595 &NtFileName,
596 NULL,
597 NULL))
598 {
599 SetLastError(ERROR_PATH_NOT_FOUND);
600 return FALSE;
601 }
602
603 bRet = NtGdiGetFontResourceInfoInternalW(
604 NtFileName.Buffer,
605 (NtFileName.Length / sizeof(WCHAR)) + 1,
606 1,
607 *pdwBufSize,
608 pdwBufSize,
609 lpBuffer,
610 dwType);
611
612 RtlFreeHeap(RtlGetProcessHeap(), 0, NtFileName.Buffer);
613
614 return bRet;
615 }
616
617
618 /*
619 * @unimplemented
620 */
621 INT
622 WINAPI
623 SetTextCharacterExtra(
624 _In_ HDC hdc,
625 _In_ INT nCharExtra)
626 {
627 PDC_ATTR pdcattr;
628 INT nOldCharExtra;
629
630 if (nCharExtra == 0x80000000)
631 {
632 SetLastError(ERROR_INVALID_PARAMETER);
633 return 0x80000000;
634 }
635
636 #if 0
637 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
638 {
639 return MFDRV_SetTextCharacterExtra( hdc, nCharExtra ); // Wine port.
640 }
641 #endif
642
643 /* Get the DC attribute */
644 pdcattr = GdiGetDcAttr(hdc);
645 if (pdcattr == NULL)
646 {
647 SetLastError(ERROR_INVALID_PARAMETER);
648 return 0x8000000;
649 }
650
651 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
652 {
653 if (pdcattr->ulDirty_ & DC_FONTTEXT_DIRTY)
654 {
655 NtGdiFlush(); // Sync up pdcattr from Kernel space.
656 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
657 }
658 }
659
660 nOldCharExtra = pdcattr->lTextExtra;
661 pdcattr->lTextExtra = nCharExtra;
662 return nOldCharExtra;
663 }
664
665 /*
666 * @implemented
667 *
668 */
669 UINT
670 WINAPI
671 GetTextAlign(
672 _In_ HDC hdc)
673 {
674 PDC_ATTR pdcattr;
675
676 /* Get the DC attribute */
677 pdcattr = GdiGetDcAttr(hdc);
678 if (pdcattr == NULL)
679 {
680 /* Do not set LastError here! */
681 return GDI_ERROR;
682 }
683
684 return pdcattr->lTextAlign;
685 }
686
687
688 /*
689 * @implemented
690 *
691 */
692 COLORREF
693 WINAPI
694 GetTextColor(
695 _In_ HDC hdc)
696 {
697 PDC_ATTR pdcattr;
698
699 /* Get the DC attribute */
700 pdcattr = GdiGetDcAttr(hdc);
701 if (pdcattr == NULL)
702 {
703 /* Do not set LastError here! */
704 return CLR_INVALID;
705 }
706
707 return pdcattr->ulForegroundClr;
708 }
709
710
711 /*
712 * @unimplemented
713 */
714 UINT
715 WINAPI
716 SetTextAlign(
717 _In_ HDC hdc,
718 _In_ UINT fMode)
719 {
720 PDC_ATTR pdcattr;
721 INT fOldMode;
722
723 /* Get the DC attribute */
724 pdcattr = GdiGetDcAttr(hdc);
725 if (pdcattr == NULL)
726 {
727 SetLastError(ERROR_INVALID_PARAMETER);
728 return GDI_ERROR;
729 }
730
731 #if 0
732 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
733 {
734 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
735 return MFDRV_SetTextAlign( hdc, fMode )
736 else
737 {
738 PLDC pLDC = pdcattr->pvLDC;
739 if ( !pLDC )
740 {
741 SetLastError(ERROR_INVALID_HANDLE);
742 return FALSE;
743 }
744 if (pLDC->iType == LDC_EMFLDC)
745 {
746 if return EMFDRV_SetTextAlign( hdc, fMode )
747 }
748 }
749 }
750 #endif
751
752 fOldMode = pdcattr->lTextAlign;
753 pdcattr->lTextAlign = fMode; // Raw
754 if (pdcattr->dwLayout & LAYOUT_RTL)
755 {
756 if ((fMode & TA_CENTER) != TA_CENTER) fMode ^= TA_RIGHT;
757 }
758
759 pdcattr->flTextAlign = fMode & TA_MASK;
760 return fOldMode;
761 }
762
763
764 /*
765 * @implemented
766 */
767 COLORREF
768 WINAPI
769 SetTextColor(
770 _In_ HDC hdc,
771 _In_ COLORREF crColor)
772 {
773 PDC_ATTR pdcattr;
774 COLORREF crOldColor = CLR_INVALID;
775
776 /* Get the DC attribute */
777 pdcattr = GdiGetDcAttr(hdc);
778 if (pdcattr == NULL)
779 {
780 SetLastError(ERROR_INVALID_PARAMETER);
781 return GDI_ERROR;
782 }
783
784 #if 0
785 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
786 {
787 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
788 return MFDRV_SetTextColor( hDC, crColor );
789 else
790 {
791 PLDC pLDC = pdcattr->pvLDC;
792 if ( !pLDC )
793 {
794 SetLastError(ERROR_INVALID_HANDLE);
795 return FALSE;
796 }
797 if (pLDC->iType == LDC_EMFLDC)
798 {
799 if return EMFDRV_SetTextColor( hDC, crColor );
800 }
801 }
802 }
803 #endif
804
805 crOldColor = (COLORREF) pdcattr->ulForegroundClr;
806 pdcattr->ulForegroundClr = (ULONG)crColor;
807
808 if (pdcattr->crForegroundClr != crColor)
809 {
810 pdcattr->ulDirty_ |= (DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL);
811 pdcattr->crForegroundClr = crColor;
812 }
813
814 return crOldColor;
815 }
816
817 /*
818 * @implemented
819 */
820 BOOL
821 WINAPI
822 SetTextJustification(
823 _In_ HDC hdc,
824 _In_ INT nBreakExtra,
825 _In_ INT nBreakCount)
826 {
827 PDC_ATTR pdcattr;
828
829 /* Get the DC attribute */
830 pdcattr = GdiGetDcAttr(hdc);
831 if (pdcattr == NULL)
832 {
833 /* Do not set LastError here! */
834 return GDI_ERROR;
835 }
836
837 #if 0
838 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
839 {
840 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
841 return MFDRV_SetTextJustification( hdc, nBreakExtra, nBreakCount )
842 else
843 {
844 SetLastError(ERROR_INVALID_HANDLE);
845 return FALSE;
846 }
847 #endif
848
849 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
850 {
851 if (pdcattr->ulDirty_ & DC_FONTTEXT_DIRTY)
852 {
853 NtGdiFlush(); // Sync up pdcattr from Kernel space.
854 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
855 }
856 }
857
858 pdcattr->cBreak = nBreakCount;
859 pdcattr->lBreakExtra = nBreakExtra;
860 return TRUE;
861 }
862
863 /*
864 * @implemented
865 */
866 UINT
867 WINAPI
868 GetStringBitmapA(
869 _In_ HDC hdc,
870 _In_ LPSTR psz,
871 _In_ BOOL bDoCall,
872 _In_ UINT cj,
873 _Out_writes_(cj) BYTE *lpSB)
874 {
875
876 NTSTATUS Status;
877 PWSTR pwsz;
878 UINT uResult = 0;
879
880 if (!bDoCall)
881 {
882 return 0;
883 }
884
885 Status = HEAP_strdupA2W(&pwsz, psz);
886 if (!NT_SUCCESS(Status))
887 {
888 SetLastError (RtlNtStatusToDosError(Status));
889 }
890 else
891 {
892 uResult = NtGdiGetStringBitmapW(hdc, pwsz, 1, lpSB, cj);
893 HEAP_free(pwsz);
894 }
895
896 return uResult;
897
898 }
899
900 /*
901 * @implemented
902 */
903 UINT
904 WINAPI
905 GetStringBitmapW(
906 _In_ HDC hdc,
907 _In_ LPWSTR pwsz,
908 _In_ BOOL bDoCall,
909 _In_ UINT cj,
910 _Out_writes_(cj) BYTE *lpSB)
911 {
912 if (!bDoCall)
913 {
914 return 0;
915 }
916
917 return NtGdiGetStringBitmapW(hdc, pwsz, 1, lpSB, cj);
918
919 }
920
921 /*
922 * @implemented
923 */
924 BOOL
925 WINAPI
926 GetETM(
927 _In_ HDC hdc,
928 _Out_ EXTTEXTMETRIC *petm)
929 {
930 BOOL bResult;
931
932 bResult = NtGdiGetETM(hdc, petm);
933
934 if (bResult && petm)
935 {
936 petm->emKernPairs = (WORD)GetKerningPairsA(hdc, 0, 0);
937 }
938
939 return bResult;
940 }