Author: khornicek Date: Fri Oct 31 15:57:09 2014 New Revision: 65150
URL: http://svn.reactos.org/svn/reactos?rev=65150&view=rev Log: [WIN32K] - don't access user mode buffers directly in the Freetype code
Modified: trunk/reactos/win32ss/gdi/ntgdi/freetype.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/freetype.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/freetype.... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/freetype.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/freetype.c [iso-8859-1] Fri Oct 31 15:57:09 2014 @@ -3365,7 +3365,7 @@ BrushOrigin.x = 0; BrushOrigin.y = 0;
- psurf = dc->dclevel.pSurface ; + psurf = dc->dclevel.pSurface;
if(!psurf) psurf = psurfDefaultBitmap; @@ -3921,7 +3921,7 @@ IN HDC hDC, IN UINT FirstChar, IN ULONG Count, - IN OPTIONAL PWCHAR pwch, + IN OPTIONAL PWCHAR UnSafepwch, IN FLONG fl, OUT PVOID Buffer) { @@ -3937,14 +3937,29 @@ HFONT hFont = 0; NTSTATUS Status = STATUS_SUCCESS; PMATRIX pmxWorldToDevice; - - if (pwch) - { + PWCHAR Safepwch = NULL; + + if (!Buffer) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (UnSafepwch) + { + UINT pwchSize = Count * sizeof(WCHAR); + Safepwch = ExAllocatePoolWithTag(PagedPool, pwchSize, GDITAG_TEXT); + + if(!Safepwch) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + _SEH2_TRY { - ProbeForRead(pwch, - sizeof(PWSTR), - 1); + ProbeForRead(UnSafepwch, pwchSize, 1); + RtlCopyMemory(Safepwch, UnSafepwch, pwchSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -3952,15 +3967,13 @@ } _SEH2_END; } + if (!NT_SUCCESS(Status)) { + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + EngSetLastError(Status); - return FALSE; - } - - if (!Buffer) - { - EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
@@ -3969,6 +3982,10 @@ if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff; if (SafeBuff == NULL) { + + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } @@ -3977,6 +3994,10 @@ if (dc == NULL) { ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); + + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -3991,6 +4012,10 @@ if (TextObj == NULL) { ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); + + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -4014,6 +4039,10 @@ { DPRINT1("WARNING: Could not find desired charmap!\n"); ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); + + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -4035,12 +4064,12 @@ { int adv, lsb, bbx, left, right;
- if (pwch) + if (Safepwch) { if (fl & GCABCW_INDICES) - glyph_index = pwch[i - FirstChar]; + glyph_index = Safepwch[i - FirstChar]; else - glyph_index = FT_Get_Char_Index(face, pwch[i - FirstChar]); + glyph_index = FT_Get_Char_Index(face, Safepwch[i - FirstChar]); } else { @@ -4079,13 +4108,18 @@ IntUnLockFreeType; TEXTOBJ_UnlockText(TextObj); Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize); + + ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); + + if(Safepwch) + ExFreePoolWithTag(Safepwch , GDITAG_TEXT); + if (! NT_SUCCESS(Status)) { SetLastNtError(Status); - ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); return FALSE; } - ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); + DPRINT("NtGdiGetCharABCWidths Worked!\n"); return TRUE; } @@ -4099,7 +4133,7 @@ IN HDC hDC, IN UINT FirstChar, IN UINT Count, - IN OPTIONAL PWCHAR pwc, + IN OPTIONAL PWCHAR UnSafepwc, IN FLONG fl, OUT PVOID Buffer) { @@ -4115,14 +4149,22 @@ UINT i, glyph_index, BufferSize; HFONT hFont = 0; PMATRIX pmxWorldToDevice; - - if (pwc) - { + PWCHAR Safepwc = NULL; + + if (UnSafepwc) + { + UINT pwcSize = Count * sizeof(WCHAR); + Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT); + + if(!Safepwc) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } _SEH2_TRY { - ProbeForRead(pwc, - sizeof(PWSTR), - 1); + ProbeForRead(UnSafepwc, pwcSize, 1); + RtlCopyMemory(Safepwc, UnSafepwc, pwcSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -4130,6 +4172,7 @@ } _SEH2_END; } + if (!NT_SUCCESS(Status)) { EngSetLastError(Status); @@ -4141,6 +4184,9 @@ if (!fl) SafeBuffF = (PFLOAT) SafeBuff; if (SafeBuff == NULL) { + if(Safepwc) + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } @@ -4148,6 +4194,9 @@ dc = DC_LockDc(hDC); if (dc == NULL) { + if(Safepwc) + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); + ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; @@ -4161,6 +4210,9 @@
if (TextObj == NULL) { + if(Safepwc) + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); + ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; @@ -4184,7 +4236,11 @@ if (!found) { DPRINT1("WARNING: Could not find desired charmap!\n"); - ExFreePool(SafeBuff); + + if(Safepwc) + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); + + ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -4204,12 +4260,12 @@
for (i = FirstChar; i < FirstChar+Count; i++) { - if (pwc) + if (Safepwc) { if (fl & GCW_INDICES) - glyph_index = pwc[i - FirstChar]; + glyph_index = Safepwc[i - FirstChar]; else - glyph_index = FT_Get_Char_Index(face, pwc[i - FirstChar]); + glyph_index = FT_Get_Char_Index(face, Safepwc[i - FirstChar]); } else { @@ -4227,6 +4283,10 @@ IntUnLockFreeType; TEXTOBJ_UnlockText(TextObj); MmCopyToCaller(Buffer, SafeBuff, BufferSize); + + if(Safepwc) + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); + ExFreePoolWithTag(SafeBuff, GDITAG_TEXT); return TRUE; } @@ -4347,7 +4407,8 @@ FT_Face face; WCHAR DefChar = 0xffff; PWSTR Buffer = NULL; - ULONG Size; + ULONG Size, pwcSize; + PWSTR Safepwc = NULL;
if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
@@ -4392,11 +4453,19 @@ ExFreePoolWithTag(potm, GDITAG_TEXT); }
+ pwcSize = cwc * sizeof(WCHAR); + Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT); + + if (!Safepwc) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return GDI_ERROR; + } + _SEH2_TRY { - ProbeForRead(UnSafepwc, - sizeof(PWSTR), - 1); + ProbeForRead(UnSafepwc, pwcSize, 1); + RtlCopyMemory(Safepwc, UnSafepwc, pwcSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -4417,7 +4486,7 @@
for (i = 0; i < cwc; i++) { - Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); // FIXME: Unsafe! + Buffer[i] = FT_Get_Char_Index(face, Safepwc[i]); if (Buffer[i] == 0) { Buffer[i] = DefChar; @@ -4428,12 +4497,8 @@
_SEH2_TRY { - ProbeForWrite(UnSafepgi, - sizeof(WORD), - 1); - RtlCopyMemory(UnSafepgi, - Buffer, - cwc*sizeof(WORD)); + ProbeForWrite(UnSafepgi, cwc * sizeof(WORD), 1); + RtlCopyMemory(UnSafepgi, Buffer, cwc * sizeof(WORD)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -4443,6 +4508,7 @@
ErrorRet: ExFreePoolWithTag(Buffer, GDITAG_TEXT); + ExFreePoolWithTag(Safepwc, GDITAG_TEXT); if (NT_SUCCESS(Status)) return cwc; EngSetLastError(Status); return GDI_ERROR;