FontCacheNumEntries = 0;
/* Fast Mutexes must be allocated from non paged pool */
FontListLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+ if (FontListLock == NULL)
+ {
+ return FALSE;
+ }
+
ExInitializeFastMutex(FontListLock);
FreeTypeLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_INTERNAL_SYNC);
+ if (FreeTypeLock == NULL)
+ {
+ return FALSE;
+ }
ExInitializeFastMutex(FreeTypeLock);
ulError = FT_Init_FreeType(&library);
InitializeObjectAttributes(
&ObjectAttributes,
&Directory,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Entry->Font = FontGDI;
Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
- RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+ Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(FontGDI->Filename, GDITAG_PFF);
+ EngFreeMem(FontGDI);
+ FT_Done_Face(Face);
+ ExFreePoolWithTag(Entry, TAG_FONT);
+ return 0;
+ }
if (Characteristics & FR_PRIVATE)
{
{
IntLockGlobalFonts;
InsertTailList(&FontListHead, &Entry->ListEntry);
- InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+ InitializeObjectAttributes(&ObjectAttributes, &FontRegPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
FT_WinFNT_HeaderRec Win;
FT_Error Error;
char *Cp;
+ NTSTATUS status;
Needed = sizeof(OUTLINETEXTMETRICW);
RtlInitAnsiString(&FamilyNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&FamilyNameW, &FamilyNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ return 0;
+ }
RtlInitAnsiString(&StyleNameA, FontGDI->face->style_name);
- RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&StyleNameW, &StyleNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ RtlFreeUnicodeString(&FamilyNameW);
+ return 0;
+ }
/* These names should be read from the TT name table */
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
FONTGDI *FontGDI;
+ NTSTATUS status;
Entry = Head->Flink;
while (Entry != Head)
ASSERT(FontGDI);
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
TEXTMETRICW *TM;
NEWTEXTMETRICW *Ntm;
DWORD fs0;
+ NTSTATUS status;
RtlZeroMemory(Info, sizeof(FONTFAMILYINFO));
Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
RtlInitAnsiString(&StyleA, FontGDI->face->style_name);
StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
- RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+ status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
+ if (!NT_SUCCESS(status))
+ {
+ return;
+ }
Info->EnumLogFontEx.elfLogFont.lfCharSet = DEFAULT_CHARSET;
Info->EnumLogFontEx.elfScript[0] = L'\0';
}
if (fs.fsCsb[0] == 0)
{ /* Let's see if we can find any interesting cmaps */
- for (i = 0; i < FontGDI->face->num_charmaps; i++)
+ for (i = 0; i < (UINT)FontGDI->face->num_charmaps; i++)
{
switch (FontGDI->face->charmaps[i]->encoding)
{
ANSI_STRING EntryFaceNameA;
UNICODE_STRING EntryFaceNameW;
FONTGDI *FontGDI;
+ NTSTATUS status;
Entry = Head->Flink;
while (Entry != Head)
ASSERT(FontGDI);
RtlInitAnsiString(&EntryFaceNameA, FontGDI->face->family_name);
- RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
+ if (!NT_SUCCESS(status))
+ {
+ return FALSE;
+ }
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
DWORD Size;
} FONT_FAMILY_INFO_CALLBACK_CONTEXT, *PFONT_FAMILY_INFO_CALLBACK_CONTEXT;
+_Function_class_(RTL_QUERY_REGISTRY_ROUTINE)
static NTSTATUS APIENTRY
FontFamilyInfoQueryRegistryCallback(IN PWSTR ValueName, IN ULONG ValueType,
IN PVOID ValueData, IN ULONG ValueLength,
}
-static
-void
-FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
+static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
{
pt->x.value = vec->x >> 6;
pt->x.fract = (vec->x & 0x3f) << 10;
pt->y.value = vec->y >> 6;
pt->y.fract = (vec->y & 0x3f) << 10;
pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
- return;
}
/*
return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
}
+static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
+{
+ TTPOLYGONHEADER *pph;
+ TTPOLYCURVE *ppc;
+ int needed = 0, point = 0, contour, first_pt;
+ unsigned int pph_start, cpfx;
+ DWORD type;
+
+ for (contour = 0; contour < outline->n_contours; contour++)
+ {
+ /* Ignore contours containing one point */
+ if (point == outline->contours[contour])
+ {
+ point++;
+ continue;
+ }
+
+ pph_start = needed;
+ pph = (TTPOLYGONHEADER *)(buf + needed);
+ first_pt = point;
+ if (buf)
+ {
+ pph->dwType = TT_POLYGON_TYPE;
+ FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
+ }
+ needed += sizeof(*pph);
+ point++;
+ while (point <= outline->contours[contour])
+ {
+ ppc = (TTPOLYCURVE *)(buf + needed);
+ type = outline->tags[point] & FT_Curve_Tag_On ?
+ TT_PRIM_LINE : TT_PRIM_QSPLINE;
+ cpfx = 0;
+ do
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ } while (point <= outline->contours[contour] &&
+ (outline->tags[point] & FT_Curve_Tag_On) ==
+ (outline->tags[point-1] & FT_Curve_Tag_On));
+ /* At the end of a contour Windows adds the start point, but
+ only for Beziers */
+ if (point > outline->contours[contour] &&
+ !(outline->tags[point-1] & FT_Curve_Tag_On))
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
+ cpfx++;
+ }
+ else if (point <= outline->contours[contour] &&
+ outline->tags[point] & FT_Curve_Tag_On)
+ {
+ /* add closing pt for bezier */
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ }
+ if (buf)
+ {
+ ppc->wType = type;
+ ppc->cpfx = cpfx;
+ }
+ needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
+ }
+ if (buf)
+ pph->cb = needed - pph_start;
+ }
+ return needed;
+}
+
+static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
+{
+ /* Convert the quadratic Beziers to cubic Beziers.
+ The parametric eqn for a cubic Bezier is, from PLRM:
+ r(t) = at^3 + bt^2 + ct + r0
+ with the control points:
+ r1 = r0 + c/3
+ r2 = r1 + (c + b)/3
+ r3 = r0 + c + b + a
+
+ A quadratic Bezier has the form:
+ p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
+
+ So equating powers of t leads to:
+ r1 = 2/3 p1 + 1/3 p0
+ r2 = 2/3 p1 + 1/3 p2
+ and of course r0 = p0, r3 = p2
+ */
+ int contour, point = 0, first_pt;
+ TTPOLYGONHEADER *pph;
+ TTPOLYCURVE *ppc;
+ DWORD pph_start, cpfx, type;
+ FT_Vector cubic_control[4];
+ unsigned int needed = 0;
+
+ for (contour = 0; contour < outline->n_contours; contour++)
+ {
+ pph_start = needed;
+ pph = (TTPOLYGONHEADER *)(buf + needed);
+ first_pt = point;
+ if (buf)
+ {
+ pph->dwType = TT_POLYGON_TYPE;
+ FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
+ }
+ needed += sizeof(*pph);
+ point++;
+ while (point <= outline->contours[contour])
+ {
+ ppc = (TTPOLYCURVE *)(buf + needed);
+ type = outline->tags[point] & FT_Curve_Tag_On ?
+ TT_PRIM_LINE : TT_PRIM_CSPLINE;
+ cpfx = 0;
+ do
+ {
+ if (type == TT_PRIM_LINE)
+ {
+ if (buf)
+ FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
+ cpfx++;
+ point++;
+ }
+ else
+ {
+ /* Unlike QSPLINEs, CSPLINEs always have their endpoint
+ so cpfx = 3n */
+
+ /* FIXME: Possible optimization in endpoint calculation
+ if there are two consecutive curves */
+ cubic_control[0] = outline->points[point-1];
+ if (!(outline->tags[point-1] & FT_Curve_Tag_On))
+ {
+ cubic_control[0].x += outline->points[point].x + 1;
+ cubic_control[0].y += outline->points[point].y + 1;
+ cubic_control[0].x >>= 1;
+ cubic_control[0].y >>= 1;
+ }
+ if (point+1 > outline->contours[contour])
+ cubic_control[3] = outline->points[first_pt];
+ else
+ {
+ cubic_control[3] = outline->points[point+1];
+ if (!(outline->tags[point+1] & FT_Curve_Tag_On))
+ {
+ cubic_control[3].x += outline->points[point].x + 1;
+ cubic_control[3].y += outline->points[point].y + 1;
+ cubic_control[3].x >>= 1;
+ cubic_control[3].y >>= 1;
+ }
+ }
+ /* r1 = 1/3 p0 + 2/3 p1
+ r2 = 1/3 p2 + 2/3 p1 */
+ cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
+ cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
+ cubic_control[2] = cubic_control[1];
+ cubic_control[1].x += (cubic_control[0].x + 1) / 3;
+ cubic_control[1].y += (cubic_control[0].y + 1) / 3;
+ cubic_control[2].x += (cubic_control[3].x + 1) / 3;
+ cubic_control[2].y += (cubic_control[3].y + 1) / 3;
+ if (buf)
+ {
+ FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
+ FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
+ FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
+ }
+ cpfx += 3;
+ point++;
+ }
+ } while (point <= outline->contours[contour] &&
+ (outline->tags[point] & FT_Curve_Tag_On) ==
+ (outline->tags[point-1] & FT_Curve_Tag_On));
+ /* At the end of a contour Windows adds the start point,
+ but only for Beziers and we've already done that.
+ */
+ if (point <= outline->contours[contour] &&
+ outline->tags[point] & FT_Curve_Tag_On)
+ {
+ /* This is the closing pt of a bezier, but we've already
+ added it, so just inc point and carry on */
+ point++;
+ }
+ if (buf)
+ {
+ ppc->wType = type;
+ ppc->cpfx = cpfx;
+ }
+ needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
+ }
+ if (buf)
+ pph->cb = needed - pph_start;
+ }
+ return needed;
+}
+
/*
* Based on WineEngGetGlyphOutline
*
for (n = 0; n < ft_face->num_charmaps; n++)
{
charmap = ft_face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
}
}
-// FT_Set_Pixel_Sizes(ft_face,
-// TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
+ FT_Set_Pixel_Sizes(ft_face,
+ abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth),
/* FIXME: Should set character height if neg */
-// (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
-// dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
-// FtSetCoordinateTransform(face, DC_pmxWorldToDevice(dc));
+ (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ?
+ dc->ppdev->devinfo.lfDefaultFont.lfHeight : abs(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)));
+ FtSetCoordinateTransform(ft_face, DC_pmxWorldToDevice(dc));
TEXTOBJ_UnlockText(TextObj);
IntUnLockFreeType;
- if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
if (iFormat == GGO_METRICS)
{
DPRINT("GGO_METRICS Exit!\n");
+ *pgm = gm;
return 1; /* FIXME */
}
needed = pitch * height;
if (!pvBuf || !cjBuf) break;
+ if (!needed) return GDI_ERROR; /* empty glyph */
+ if (needed > cjBuf)
+ return GDI_ERROR;
switch (ft_face->glyph->format)
{
case ft_glyph_format_bitmap:
{
BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
- INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
- INT h = ft_face->glyph->bitmap.rows;
+ INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
+ INT h = min( height, ft_face->glyph->bitmap.rows );
while (h--)
{
RtlCopyMemory(dst, src, w);
needed = pitch * height;
if (!pvBuf || !cjBuf) break;
+ if (!needed) return GDI_ERROR; /* empty glyph */
+ if (needed > cjBuf)
+ return GDI_ERROR;
switch (ft_face->glyph->format)
{
case ft_glyph_format_bitmap:
{
BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
- INT h = ft_face->glyph->bitmap.rows;
+ INT h = min( height, ft_face->glyph->bitmap.rows );
INT x;
while (h--)
{
- for (x = 0; x < pitch; x++)
+ for (x = 0; (UINT)x < pitch; x++)
{
if (x < ft_face->glyph->bitmap.width)
dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
src += ft_face->glyph->bitmap.pitch;
dst += pitch;
}
- return needed;
+ break;
}
case ft_glyph_format_outline:
{
{
return GDI_ERROR;
}
+
+ start = pvBuf;
+ for (row = 0; row < height; row++)
+ {
+ ptr = start;
+ for (col = 0; col < width; col++, ptr++)
+ {
+ *ptr = (((int)*ptr) * mult + 128) / 256;
+ }
+ start += pitch;
+ }
+
+ break;
}
default:
DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
return GDI_ERROR;
}
- start = pvBuf;
- for (row = 0; row < height; row++)
- {
- ptr = start;
- for (col = 0; col < width; col++, ptr++)
- {
- *ptr = (((int)*ptr) * mult + 128) / 256;
- }
- start += pitch;
- }
- break;
}
case GGO_NATIVE:
{
- int contour, point = 0, first_pt;
FT_Outline *outline = &ft_face->glyph->outline;
- TTPOLYGONHEADER *pph;
- TTPOLYCURVE *ppc;
- DWORD pph_start, cpfx, type;
if (cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
IntLockFreeType;
if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
- for (contour = 0; contour < outline->n_contours; contour++)
+ needed = get_native_glyph_outline(outline, cjBuf, NULL);
+
+ if (!pvBuf || !cjBuf)
{
- pph_start = needed;
- pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed);
- first_pt = point;
- if (pvBuf)
- {
- pph->dwType = TT_POLYGON_TYPE;
- FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
- }
- needed += sizeof(*pph);
- point++;
- while (point <= outline->contours[contour])
- {
- ppc = (TTPOLYCURVE *)((char *)pvBuf + needed);
- type = (outline->tags[point] & FT_Curve_Tag_On) ?
- TT_PRIM_LINE : TT_PRIM_QSPLINE;
- cpfx = 0;
- do
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- while (point <= outline->contours[contour] &&
- (outline->tags[point] & FT_Curve_Tag_On) ==
- (outline->tags[point-1] & FT_Curve_Tag_On));
-
- /* At the end of a contour Windows adds the start point, but
- only for Beziers */
- if (point > outline->contours[contour] &&
- !(outline->tags[point-1] & FT_Curve_Tag_On))
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
- cpfx++;
- }
- else if (point <= outline->contours[contour] &&
- outline->tags[point] & FT_Curve_Tag_On)
- {
- /* Add closing pt for bezier */
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- if (pvBuf)
- {
- ppc->wType = type;
- ppc->cpfx = cpfx;
- }
- needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
- }
- if (pvBuf) pph->cb = needed - pph_start;
+ IntUnLockFreeType;
+ break;
}
+ if (needed > cjBuf)
+ {
+ IntUnLockFreeType;
+ return GDI_ERROR;
+ }
+ get_native_glyph_outline(outline, cjBuf, pvBuf);
IntUnLockFreeType;
break;
}
case GGO_BEZIER:
{
- /* Convert the quadratic Beziers to cubic Beziers.
- The parametric eqn for a cubic Bezier is, from PLRM:
- r(t) = at^3 + bt^2 + ct + r0
- with the control points:
- r1 = r0 + c/3
- r2 = r1 + (c + b)/3
- r3 = r0 + c + b + a
-
- A quadratic Beizer has the form:
- p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
-
- So equating powers of t leads to:
- r1 = 2/3 p1 + 1/3 p0
- r2 = 2/3 p1 + 1/3 p2
- and of course r0 = p0, r3 = p2
- */
-
- int contour, point = 0, first_pt;
FT_Outline *outline = &ft_face->glyph->outline;
- TTPOLYGONHEADER *pph;
- TTPOLYCURVE *ppc;
- DWORD pph_start, cpfx, type;
- FT_Vector cubic_control[4];
if (cjBuf == 0) pvBuf = NULL;
if (needsTransform && pvBuf)
FT_Outline_Transform(outline, &transMat);
IntUnLockFreeType;
}
+ needed = get_bezier_glyph_outline(outline, cjBuf, NULL);
- for (contour = 0; contour < outline->n_contours; contour++)
- {
- pph_start = needed;
- pph = (TTPOLYGONHEADER *)((char *)pvBuf + needed);
- first_pt = point;
- if (pvBuf)
- {
- pph->dwType = TT_POLYGON_TYPE;
- FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
- }
- needed += sizeof(*pph);
- point++;
- while (point <= outline->contours[contour])
- {
- ppc = (TTPOLYCURVE *)((char *)pvBuf + needed);
- type = (outline->tags[point] & FT_Curve_Tag_On) ?
- TT_PRIM_LINE : TT_PRIM_CSPLINE;
- cpfx = 0;
- do
- {
- if (type == TT_PRIM_LINE)
- {
- if (pvBuf)
- FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
- cpfx++;
- point++;
- }
- else
- {
- /* Unlike QSPLINEs, CSPLINEs always have their endpoint
- so cpfx = 3n */
+ if (!pvBuf || !cjBuf)
+ break;
+ if (needed > cjBuf)
+ return GDI_ERROR;
- /* FIXME: Possible optimization in endpoint calculation
- if there are two consecutive curves */
- cubic_control[0] = outline->points[point-1];
- if (!(outline->tags[point-1] & FT_Curve_Tag_On))
- {
- cubic_control[0].x += outline->points[point].x + 1;
- cubic_control[0].y += outline->points[point].y + 1;
- cubic_control[0].x >>= 1;
- cubic_control[0].y >>= 1;
- }
- if (point+1 > outline->contours[contour])
- cubic_control[3] = outline->points[first_pt];
- else
- {
- cubic_control[3] = outline->points[point+1];
- if (!(outline->tags[point+1] & FT_Curve_Tag_On))
- {
- cubic_control[3].x += outline->points[point].x + 1;
- cubic_control[3].y += outline->points[point].y + 1;
- cubic_control[3].x >>= 1;
- cubic_control[3].y >>= 1;
- }
- }
- /* r1 = 1/3 p0 + 2/3 p1
- r2 = 1/3 p2 + 2/3 p1 */
- cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
- cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
- cubic_control[2] = cubic_control[1];
- cubic_control[1].x += (cubic_control[0].x + 1) / 3;
- cubic_control[1].y += (cubic_control[0].y + 1) / 3;
- cubic_control[2].x += (cubic_control[3].x + 1) / 3;
- cubic_control[2].y += (cubic_control[3].y + 1) / 3;
- if (pvBuf)
- {
- FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
- FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
- FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
- }
- cpfx += 3;
- point++;
- }
- }
- while (point <= outline->contours[contour] &&
- (outline->tags[point] & FT_Curve_Tag_On) ==
- (outline->tags[point-1] & FT_Curve_Tag_On));
- /* At the end of a contour Windows adds the start point,
- but only for Beziers and we've already done that. */
- if (point <= outline->contours[contour] &&
- outline->tags[point] & FT_Curve_Tag_On)
- {
- /* This is the closing pt of a bezier, but we've already
- added it, so just inc point and carry on */
- point++;
- }
- if (pvBuf)
- {
- ppc->wType = type;
- ppc->cpfx = cpfx;
- }
- needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
- }
- if (pvBuf) pph->cb = needed - pph_start;
- }
+ get_bezier_glyph_outline(outline, cjBuf, pvBuf);
break;
}
}
DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
+ *pgm = gm;
return needed;
}
for (n = 0; n < face->num_charmaps; n++)
{
charmap = face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
DWORD dwFlags)
{
PDC_ATTR pdcattr;
- UINT Ret = DEFAULT_CHARSET, i;
+ UINT Ret = DEFAULT_CHARSET;
+ INT i;
HFONT hFont;
PTEXTOBJ TextObj;
PFONTGDI FontGdi;
}
}
else
- DPRINT1("Encoding %u not supported\n", face->charmap->encoding);
+ DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
if (glyphset)
{
glyphset->cbThis = size;
glyphset->cRanges = num_ranges;
+ glyphset->flAccel = 0;
}
return size;
}
Status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA, TRUE);
if (NT_SUCCESS(Status))
{
+ static const UNICODE_STRING MarlettFaceNameW = RTL_CONSTANT_STRING(L"Marlett");
+ static const UNICODE_STRING SymbolFaceNameW = RTL_CONSTANT_STRING(L"Symbol");
+ static const UNICODE_STRING VGAFaceNameW = RTL_CONSTANT_STRING(L"VGA");
+
if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
{
EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
}
- if (0 == RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
+
+ if (!RtlCompareUnicodeString(FaceName, &EntryFaceNameW, TRUE))
{
Score += 49;
}
+
+ /* FIXME: this is a work around to counter weird fonts on weird places.
+ A proper fix would be to score fonts on more attributes than
+ the ones in this function */
+ if (!RtlCompareUnicodeString(&MarlettFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&MarlettFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
+ if (!RtlCompareUnicodeString(&SymbolFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&SymbolFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
+ if (!RtlCompareUnicodeString(&VGAFaceNameW, &EntryFaceNameW, TRUE) &&
+ RtlCompareUnicodeString(&VGAFaceNameW, FaceName, TRUE))
+ {
+ Score = 0;
+ }
+
RtlFreeUnicodeString(&EntryFaceNameW);
}
InitializeObjectAttributes(&ObjectAttributes,
FileName,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
- RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
+ RECTL DestRect, MaskRect;
POINTL SourcePoint, BrushOrigin;
HBITMAP HSourceGlyph;
SURFOBJ *SourceGlyphSurf;
Start.y = YStart;
IntLPtoDP(dc, &Start, 1);
- RealXStart = (Start.x + dc->ptlDCOrig.x) << 6;
+ RealXStart = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
YStart = Start.y + dc->ptlDCOrig.y;
SourcePoint.x = 0;
BrushOrigin.x = 0;
BrushOrigin.y = 0;
+ if (!dc->dclevel.pSurface)
+ {
+ goto fail;
+ }
+
if ((fuOptions & ETO_OPAQUE) && lprc)
{
DestRect.left = lprc->left;
DestRect.right += dc->ptlDCOrig.x;
DestRect.bottom += dc->ptlDCOrig.y;
- DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+ DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
DC_vUpdateBackgroundBrush(dc);
+ psurf = dc->dclevel.pSurface;
IntEngBitBlt(
- &dc->dclevel.pSurface->SurfObj,
+ &psurf->SurfObj,
NULL,
NULL,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
NULL,
&DestRect,
&SourcePoint,
for (n = 0; n < face->num_charmaps; n++)
{
charmap = face->charmaps[n];
- DPRINT("Found charmap encoding: %u\n", charmap->encoding);
+ DPRINT("Found charmap encoding: %i\n", charmap->encoding);
if (charmap->encoding != 0)
{
found = charmap;
{
ULONGLONG TextWidth = 0;
LPCWSTR TempText = String;
- int Start;
+ int iStart;
/*
* Calculate width of the text.
if (NULL != Dx)
{
- Start = Count < 2 ? 0 : Count - 2;
+ iStart = Count < 2 ? 0 : Count - 2;
TextWidth = Count < 2 ? 0 : (Dx[(Count-2)<<DxShift] << 6);
}
else
{
- Start = 0;
+ iStart = 0;
}
- TempText = String + Start;
+ TempText = String + iStart;
- for (i = Start; i < Count; i++)
+ for (i = iStart; i < Count; i++)
{
if (fuOptions & ETO_GLYPH_INDEX)
glyph_index = *TempText;
BackgroundLeft = (RealXStart + 32) >> 6;
/* Lock blit with a dummy rect */
- DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
+ DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
- psurf = dc->dclevel.pSurface ;
- if(!psurf) psurf = psurfDefaultBitmap;
+ psurf = dc->dclevel.pSurface;
SurfObj = &psurf->SurfObj ;
EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
- if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND))
+ if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND))
DC_vUpdateBackgroundBrush(dc) ;
if(dc->pdcattr->ulDirty_ & DIRTY_TEXT)
&psurf->SurfObj,
NULL,
NULL,
- dc->rosdc.CombinedClip,
+ &dc->co.ClipObj,
NULL,
&DestRect,
&SourcePoint,
ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
MouseSafetyOnDrawEnd(dc->ppdev);
BackgroundLeft = DestRect.right;
-
}
DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
MaskRect.right = realglyph->bitmap.width;
MaskRect.bottom = realglyph->bitmap.rows;
- /*
- * We should create the bitmap out of the loop at the biggest possible
- * glyph size. Then use memset with 0 to clear it and sourcerect to
- * limit the work of the transbitblt.
- */
-
- HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
- BMF_8BPP, BMF_TOPDOWN,
- realglyph->bitmap.buffer);
- if ( !HSourceGlyph )
+ /* Check if the bitmap has any pixels */
+ if ((bitSize.cx != 0) && (bitSize.cy != 0))
{
- DPRINT1("WARNING: EngLockSurface() failed!\n");
- // FT_Done_Glyph(realglyph);
- IntUnLockFreeType;
- DC_vFinishBlit(dc, NULL);
- goto fail2;
- }
- SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
- if ( !SourceGlyphSurf )
- {
- EngDeleteSurface((HSURF)HSourceGlyph);
- DPRINT1("WARNING: EngLockSurface() failed!\n");
- IntUnLockFreeType;
- DC_vFinishBlit(dc, NULL);
- goto fail2;
- }
+ /*
+ * We should create the bitmap out of the loop at the biggest possible
+ * glyph size. Then use memset with 0 to clear it and sourcerect to
+ * limit the work of the transbitblt.
+ */
+
+ HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
+ BMF_8BPP, BMF_TOPDOWN,
+ realglyph->bitmap.buffer);
+ if ( !HSourceGlyph )
+ {
+ DPRINT1("WARNING: EngCreateBitmap() failed!\n");
+ // FT_Done_Glyph(realglyph);
+ IntUnLockFreeType;
+ DC_vFinishBlit(dc, NULL);
+ goto fail2;
+ }
+ SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
+ if ( !SourceGlyphSurf )
+ {
+ EngDeleteSurface((HSURF)HSourceGlyph);
+ DPRINT1("WARNING: EngLockSurface() failed!\n");
+ IntUnLockFreeType;
+ DC_vFinishBlit(dc, NULL);
+ goto fail2;
+ }
- /*
- * Use the font data as a mask to paint onto the DCs surface using a
- * brush.
- */
+ /*
+ * Use the font data as a mask to paint onto the DCs surface using a
+ * brush.
+ */
- if (lprc && (fuOptions & ETO_CLIPPED) &&
- DestRect.right >= lprc->right + dc->ptlDCOrig.x)
- {
- // We do the check '>=' instead of '>' to possibly save an iteration
- // through this loop, since it's breaking after the drawing is done,
- // and x is always incremented.
- DestRect.right = lprc->right + dc->ptlDCOrig.x;
- DoBreak = TRUE;
- }
- if (lprc && (fuOptions & ETO_CLIPPED) &&
- DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
- {
- DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
- }
- MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
- IntEngMaskBlt(
- SurfObj,
- SourceGlyphSurf,
- dc->rosdc.CombinedClip,
- &exloRGB2Dst.xlo,
- &exloDst2RGB.xlo,
- &DestRect,
- (PPOINTL)&MaskRect,
- &dc->eboText.BrushObject,
- &BrushOrigin);
- MouseSafetyOnDrawEnd(dc->ppdev) ;
+ if (lprc && (fuOptions & ETO_CLIPPED) &&
+ DestRect.right >= lprc->right + dc->ptlDCOrig.x)
+ {
+ // We do the check '>=' instead of '>' to possibly save an iteration
+ // through this loop, since it's breaking after the drawing is done,
+ // and x is always incremented.
+ DestRect.right = lprc->right + dc->ptlDCOrig.x;
+ DoBreak = TRUE;
+ }
+ if (lprc && (fuOptions & ETO_CLIPPED) &&
+ DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
+ {
+ DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
+ }
+ MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
+ if (!IntEngMaskBlt(
+ SurfObj,
+ SourceGlyphSurf,
+ &dc->co.ClipObj,
+ &exloRGB2Dst.xlo,
+ &exloDst2RGB.xlo,
+ &DestRect,
+ (PPOINTL)&MaskRect,
+ &dc->eboText.BrushObject,
+ &BrushOrigin))
+ {
+ DPRINT1("Failed to MaskBlt a glyph!\n");
+ }
- EngUnlockSurface(SourceGlyphSurf);
- EngDeleteSurface((HSURF)HSourceGlyph);
+ MouseSafetyOnDrawEnd(dc->ppdev) ;
+
+ EngUnlockSurface(SourceGlyphSurf);
+ EngDeleteSurface((HSURF)HSourceGlyph);
+ }
if (DoBreak)
{
}
else
{
+ // FIXME this should probably be a matrix transform with TextTop as well.
Scale = pdcattr->mxWorldToDevice.efM11;
- if (_FLOATOBJ_Equal0(&Scale))
+ if (FLOATOBJ_Equal0(&Scale))
FLOATOBJ_Set1(&Scale);
-
+
FLOATOBJ_MulLong(&Scale, Dx[i<<DxShift] << 6); // do the shift before multiplying to preserve precision
TextLeft += FLOATOBJ_GetLong(&Scale);
DPRINT("New TextLeft2: %I64d\n", TextLeft);
IN HDC hDC,
IN UINT FirstChar,
IN ULONG Count,
- IN OPTIONAL PWCHAR pwch,
+ IN OPTIONAL PWCHAR UnSafepwch,
IN FLONG fl,
OUT PVOID Buffer)
{
HFONT hFont = 0;
NTSTATUS Status = STATUS_SUCCESS;
PMATRIX pmxWorldToDevice;
+ PWCHAR Safepwch = NULL;
+
+ if (!Buffer)
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
- if (pwch)
+ 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)
{
}
_SEH2_END;
}
+
if (!NT_SUCCESS(Status))
{
- EngSetLastError(Status);
- return FALSE;
- }
+ if(Safepwch)
+ ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
- if (!Buffer)
- {
- EngSetLastError(ERROR_INVALID_PARAMETER);
+ EngSetLastError(Status);
return FALSE;
}
if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
if (SafeBuff == NULL)
{
+
+ if(Safepwch)
+ ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
+
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (dc == NULL)
{
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
+
+ if(Safepwch)
+ ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
+
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (TextObj == NULL)
{
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
+
+ if(Safepwch)
+ ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
+
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
face = FontGDI->face;
if (face->charmap == NULL)
{
- for (i = 0; i < face->num_charmaps; i++)
+ for (i = 0; i < (UINT)face->num_charmaps; i++)
{
charmap = face->charmaps[i];
if (charmap->encoding != 0)
{
DPRINT1("WARNING: Could not find desired charmap!\n");
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
+
+ if(Safepwch)
+ ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
+
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
{
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
{
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;
}
IN HDC hDC,
IN UINT FirstChar,
IN UINT Count,
- IN OPTIONAL PWCHAR pwc,
+ IN OPTIONAL PWCHAR UnSafepwc,
IN FLONG fl,
OUT PVOID Buffer)
{
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
PMATRIX pmxWorldToDevice;
+ PWCHAR Safepwc = NULL;
- if (pwc)
+ 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)
{
}
_SEH2_END;
}
+
if (!NT_SUCCESS(Status))
{
EngSetLastError(Status);
if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
if (SafeBuff == NULL)
{
+ if(Safepwc)
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
dc = DC_LockDc(hDC);
if (dc == NULL)
{
+ if(Safepwc)
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
if (TextObj == NULL)
{
+ if(Safepwc)
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
face = FontGDI->face;
if (face->charmap == NULL)
{
- for (i = 0; i < face->num_charmaps; i++)
+ for (i = 0; i < (UINT)face->num_charmaps; i++)
{
charmap = face->charmaps[i];
if (charmap->encoding != 0)
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;
}
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
{
IntUnLockFreeType;
TEXTOBJ_UnlockText(TextObj);
MmCopyToCaller(Buffer, SafeBuff, BufferSize);
+
+ if(Safepwc)
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+
ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
return TRUE;
}
+#if 0
DWORD
FASTCALL
GreGetGlyphIndicesW(
- HDC hdc,
- LPWSTR pwc,
- INT cwc,
- LPWORD pgi,
- DWORD iMode,
- DWORD Unknown)
+ _In_ HDC hdc,
+ _In_reads_(cwc) LPWSTR pwc,
+ _In_ INT cwc,
+ _Out_writes_opt_(cwc) LPWORD pgi,
+ _In_ DWORD iMode,
+ _In_ DWORD dwUnknown)
{
PDC dc;
PDC_ATTR pdcattr;
IntUnLockFreeType;
- RtlCopyMemory( pgi, Buffer, cwc*sizeof(WORD));
+ if (pgi != NULL)
+ {
+ RtlCopyMemory(pgi, Buffer, cwc * sizeof(WORD));
+ }
ErrorRet:
if (Buffer) ExFreePoolWithTag(Buffer, GDITAG_TEXT);
return cwc;
}
-
+#endif // 0
/*
* @implemented
*/
+__kernel_entry
+W32KAPI
DWORD
APIENTRY
NtGdiGetGlyphIndicesW(
- IN HDC hdc,
- IN OPTIONAL LPWSTR UnSafepwc,
- IN INT cwc,
- OUT OPTIONAL LPWORD UnSafepgi,
- IN DWORD iMode)
+ _In_ HDC hdc,
+ _In_reads_opt_(cwc) LPCWSTR pwc,
+ _In_ INT cwc,
+ _Out_writes_opt_(cwc) LPWORD pgi,
+ _In_ DWORD iMode)
{
PDC dc;
PDC_ATTR pdcattr;
FT_Face face;
WCHAR DefChar = 0xffff;
PWSTR Buffer = NULL;
- ULONG Size;
+ ULONG Size, pwcSize;
+ PWSTR Safepwc = NULL;
+ LPCWSTR UnSafepwc = pwc;
+ LPWORD UnSafepgi = pgi;
if ((!UnSafepwc) && (!UnSafepgi)) return cwc;
+ if ((UnSafepwc == NULL) || (UnSafepgi == NULL))
+ {
+ DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
+ return -1;
+ }
+
dc = DC_LockDc(hdc);
if (!dc)
{
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)
{
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;
_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)
{
ErrorRet:
ExFreePoolWithTag(Buffer, GDITAG_TEXT);
+ if (Safepwc != NULL)
+ {
+ ExFreePoolWithTag(Safepwc, GDITAG_TEXT);
+ }
if (NT_SUCCESS(Status)) return cwc;
EngSetLastError(Status);
return GDI_ERROR;