summaryrefslogtreecommitdiffstats
path: root/src/libuemf
diff options
context:
space:
mode:
authorTomasz Boczkowski <penginsbacon@gmail.com>2015-05-02 09:43:24 +0000
committerTomasz Boczkowski <penginsbacon@gmail.com>2015-05-02 09:43:24 +0000
commit4ae263b8d394775ff631efaacc835346af1ffdae (patch)
tree8c54527cb2698ade852a3286e84692fc29b74ad8 /src/libuemf
parentmerged gtk3 compile fix (diff)
parentsp-text: Whitespace cleanup (diff)
downloadinkscape-4ae263b8d394775ff631efaacc835346af1ffdae.tar.gz
inkscape-4ae263b8d394775ff631efaacc835346af1ffdae.zip
merge with trunk
(bzr r14059.1.12)
Diffstat (limited to 'src/libuemf')
-rw-r--r--src/libuemf/CMakeLists.txt1
-rw-r--r--src/libuemf/Makefile_insert2
-rw-r--r--src/libuemf/README100
-rw-r--r--src/libuemf/uemf.c273
-rw-r--r--src/libuemf/uemf.h180
-rw-r--r--src/libuemf/uemf_endian.c1673
-rw-r--r--src/libuemf/uemf_endian.h7
-rw-r--r--src/libuemf/uemf_print.c652
-rw-r--r--src/libuemf/uemf_print.h14
-rw-r--r--src/libuemf/uemf_safe.c1202
-rw-r--r--src/libuemf/uemf_safe.h32
-rw-r--r--src/libuemf/upmf.c1282
-rw-r--r--src/libuemf/upmf.h146
-rw-r--r--src/libuemf/upmf_print.c818
-rw-r--r--src/libuemf/upmf_print.h137
-rw-r--r--src/libuemf/uwmf.c100
-rw-r--r--src/libuemf/uwmf.h5
-rw-r--r--src/libuemf/uwmf_print.c14
-rw-r--r--src/libuemf/uwmf_print.h2
19 files changed, 4853 insertions, 1787 deletions
diff --git a/src/libuemf/CMakeLists.txt b/src/libuemf/CMakeLists.txt
index f5a97f212..922d404a6 100644
--- a/src/libuemf/CMakeLists.txt
+++ b/src/libuemf/CMakeLists.txt
@@ -4,6 +4,7 @@ set(libuemf_SRC
uemf.c
uemf_endian.c
uemf_print.c
+ uemf_safe.c
uemf_utf.c
uwmf.c
uwmf_endian.c
diff --git a/src/libuemf/Makefile_insert b/src/libuemf/Makefile_insert
index 004c56dfc..427a0e80e 100644
--- a/src/libuemf/Makefile_insert
+++ b/src/libuemf/Makefile_insert
@@ -12,6 +12,8 @@ libuemf_libuemf_a_SOURCES = \
libuemf/uemf_endian.h \
libuemf/uemf_print.c \
libuemf/uemf_print.h \
+ libuemf/uemf_safe.c \
+ libuemf/uemf_safe.h \
libuemf/uemf_utf.c \
libuemf/uemf_utf.h \
libuemf/uwmf.c \
diff --git a/src/libuemf/README b/src/libuemf/README
index cfa322178..a3dff9b4c 100644
--- a/src/libuemf/README
+++ b/src/libuemf/README
@@ -1,22 +1,25 @@
Overview:
-libUEMF is a portable C99 implementation for reading/writing Enhanced Metafile (EMF)
-and Windows Metafile (WMF) files. libUEMF avoids collisions with with Microsoft defined
-functions and values, so portable programs which use it, and have a Windows version, do
-not require any conditional logic to separate the native GDI support from the WMF/EMF support
-proviced by libUEMF. To accomplish this libUEMF does not implement GDI calls. Instead,
-for each WMR/EMR record type, and each object type incorporated into such a record, it provides
-corresponding *_set, *_print, and *_swap functions. (For WMF there are also *_get functions, see below.)
-For example, for the U_EMRBITBLT record there are corresponding functions:
-U_EMRBITBLT_set, U_EMRBITBLT_print, and U_EMRBITBLT_swap. A few additional functions are provided for
-assembling the EMF in memory, debugging, and converting the EMF file to/from Little Endian representation.
-(EMF files' internal data representation is always Little Endian.)
-
-This code has been tested on 32 bit Ubuntu (LE), 32 bit Mingw, 64 bit Manriva, and 64 bit Solaris (BE).
+libUEMF is a portable C99 implementation for reading/writing Enhanced Metafile (EMF),
+Enhanced Metafile Format Plus (PMF), and Windows Metafile (WMF) files. libUEMF
+avoids collisions with Microsoft defined functions and values, so portable programs
+which use it and have a Windows version, do not require any conditional logic to
+separate the native GDI support from the WMF/EMF/PMF support proviced by libUEMF. To
+accomplish this libUEMF does not implement GDI calls. Instead, for each WMR/EMR/PMR
+record type, and each object type incorporated into such a record, it provides
+corresponding *_set, *_print, and *_swap functions. For PMF and WMF there are also
+*_get functions, see below. For example, for the U_EMRBITBLT record there are
+corresponding functions: U_EMRBITBLT_set, U_EMRBITBLT_print, and U_EMRBITBLT_swap. A
+few additional functions are provided for assembling the EMF in memory, debugging, and
+converting the EMF file to/from Little Endian representation. (EMF files' internal
+data representation is always Little Endian.)
+
+This code has been tested on 32 bit Ubuntu (LE), 32 bit Mingw, 64 bit Mageia, and 64
+bit Solaris (BE).
libUEMF is released under the GPL 2 license, read the file 'COPYING' for more information
-Version 0.1.10, released January 15, 2014.
+Version 0.2.1, released April 23, 2015.
To report bugs or provide feedback send email to David Mathog, mathog@caltech.edu.
@@ -76,7 +79,14 @@ uemf_endian.c Contains the *_swap functions needed to rearrange bytes betwee
uemf_endian.h Prototype for U_emf_endian() and definitions for Endian type of the local machine.
-
+uemf_safe.c Contains the *_safe functions for EMF records, which verify that all
+ offsets and counts stay within the declared size of a record. Also checks that
+ core record sizes are sane. U_emf_record_safe() is the only _safe function which
+ user code should call directly, and then ONLY after a previous call to
+ U_emf_record_sizeok(), which is in the endian file.
+
+uemf_safe.h Prototype for U_emf_record_safe().
+ .
upmf.c Contains the *_set and *_get functions needed to construct or read an EMF+ file.
Also contains auxilliary functions for debugging and constructing
EMF+ files in memory.
@@ -366,9 +376,69 @@ History
(Note, version numbers in files represent the libUEMF release where it was last modified, so not
all files will show the same version numbers in each release.)
+0.2.1.2015_04_23
+ Bug in safety check on EMREXTCREATEFONTINDIRECTW because it had alternative "standard" record sizes.
+ Changed warnings on unimplemented EMF record types encounterd in swap or safe from stdout to stderr.
+ Added memory checking for WMF polyline and polygon records, for the variable part and some others.
+ Note: U_WMRCREATEREGION_get does not check that the variable part stays within the record. Current
+ implementation seems to be broken since it does not show up in XP preview.
+0.2.0 2015_03_20
+ Added UEMF _safe functions to better handle corrupt records, where variable sizes fields might
+ have been specified to read past the end of memory. These are records with offsets, arrays
+ with counts, and bitmaps. Also any record which specifies a size smaller than the minimum
+ for that record type.
+ Added similar code for EMF+.
+ These changed the API so the minor version number was bumped by 1.
+
+0.1.18 2015_01_15
+ Pierre-Francois Carpentier sent some EMF examples which used U_EMR_EXTSELECTCLIPRGN, which had
+ not previously been encountered and showed that the handling of regions was broken.
+ Added tests for U_EMRFILLRGN, U_EMRFRAMERGN, U_EMRFRAMERGN, U_EMREXTSELECTCLIPRGN to testbed_emf.
+
+0.1.18 2014_04_28
+ Fixed typo in testbed_wmf.c. "include,include" in one place should have been
+ "exclude,exclude".
+
+0.1.17 2014_04_25
+ Added text clipping tests to testbed_emf.c, testbed_wmf.c, and testbed_pmf.c.
+ Added option to omit clipping tests in testbed's.
+
+0.1.16 2014_04_14
+ Fixed bug in U_WMRRESTOREDC_set.
+ Added clipping tests to testbed_wmf.c.
+
+0.1.15 2014_04_04
+ Changed record flags for U_EMRSELECTCLIPPATH record, it consumes a path but does not ALTER (which
+ forced a premature draw.)
+ Added U_EMROFFSETCLIPRGN test to testbed_emf.c.
+ Changed location on dist drawing where clipping appears.
+
+0.1.14 2014_03_27
+ Fixed bug, in U_PMF_RECTN_set() in upmf.c. Never tested.
+ Fixed a few potential bugs in upmf.c if a null pointer was passed for
+ certain function arguments. (Previously unhandled cases.)
+ Fixed bug, operations setting variables that are never read along those
+ execution paths: upmf_print.c, uemf.c, uwmf.c, uemf_endian.cm upmf.c.
+ Fixed potential (but very unlikely) memory leaks in upmf.c and uemf_utf.c.
+ Added test of U_PMF_RECTN_set to testbed_pmf.c.
+ Changed U_wmr_names() and U_wmr_escnames() to const char* (from char*).
+ Changed method for suppressing unused parameter warnings.
+
+
+0.1.13 2014-03-21
+ Fixed bug, cutemf was messing up the object count (pens, brushes, etc.).
+ Added cutemf can now take ranges of lines.
+ Added testbed_emf generates clipping records for rect and path (but not region).
+
+0.1.12 2014-02-14
+ Documentation change, U_WMRCREATEPATTERNBRUSH is obsolete.
+ Changed wmf_finish() so that it accurately reflects the largest number of objects used,
+ previously it showed the number of appends, which was much larger.
+
0.1.11 2014-01-29
Fixed bug in uwmf.c (wrong minimum record size on U_WMRTEXTOUT)
Fixed bug in uwmf.c (U_WMRCREATEPATTERNBRUSH not right)
+ Fixed bug in uwmf_print.c (U_WMRTEXTOUT_print, x,y were reversed)
Added error handling to uemf_utf.c for cases where src is a null pointer.
Added a test of createpatternbrush to testlib_wmf
diff --git a/src/libuemf/uemf.c b/src/libuemf/uemf.c
index 1d417dece..3180c757c 100644
--- a/src/libuemf/uemf.c
+++ b/src/libuemf/uemf.c
@@ -16,11 +16,11 @@
/*
File: uemf.c
-Version: 0.0.28
-Date: 04-APR-2014
+Version: 0.0.30
+Date: 20-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
@@ -199,7 +199,7 @@ definitions are not needed in end user code, so they are here rather than in uem
// this one may also be used A=Msk,B=MskBmi and F=cbMsk
#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \
if(A){\
- if(!B)return(NULL); /* size is derived from U_BIMAPINFO, but NOT from its size field, go figure*/ \
+ if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \
C = F;\
D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \
E = sizeof(U_BITMAPINFOHEADER) + 4 * get_real_color_count((const char *) &(B->bmiHeader)); /* bmiheader + colortable*/ \
@@ -851,7 +851,7 @@ int get_real_color_icount(
\brief Get the DIB parameters from the BMI of the record for use by DBI_to_RGBA()
\return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid.
- \param pEmr pointer to EMR record that has a U_BITMAPINFO and bitmap
+ \param record pointer to EMR record that has a U_BITMAPINFO and bitmap
\param offBitsSrc Offset to the bitmap
\param offBmiSrc Offset to the U_BITMAPINFO
\param px pointer to DIB pixel array in pEmr
@@ -863,7 +863,7 @@ int get_real_color_icount(
\param invert If DIB rows are in opposite order from RGBA rows
*/
int get_DIB_params(
- void *pEmr,
+ const char *record,
uint32_t offBitsSrc,
uint32_t offBmiSrc,
const char **px,
@@ -875,7 +875,7 @@ int get_DIB_params(
uint32_t *invert
){
uint32_t bic;
- PU_BITMAPINFO Bmi = (PU_BITMAPINFO)((char *)pEmr + offBmiSrc);
+ PU_BITMAPINFO Bmi = (PU_BITMAPINFO)(record + offBmiSrc);
PU_BITMAPINFOHEADER Bmih = &(Bmi->bmiHeader);
/* if biCompression is not U_BI_RGB some or all of the following might not hold real values */
bic = Bmih->biCompression;
@@ -903,7 +903,7 @@ int get_DIB_params(
*numCt = Bmih->biSizeImage;
*ct = NULL;
}
- *px = (char *)((char *)pEmr + offBitsSrc);
+ *px = record + offBitsSrc;
return(bic);
}
@@ -1611,6 +1611,26 @@ U_RECTL rectl_set(
}
/**
+ \brief Set rect and rectl objects from Upper Left and Lower Right corner points.
+ \param array array of rectangles
+ \param index array entry to fill, numbered from 0
+ \param ul upper left corner of rectangle
+ \param lr lower right corner of rectangle
+*/
+void rectli_set(
+ PU_RECTL array,
+ int index,
+ U_POINTL ul,
+ U_POINTL lr
+ ){
+ PU_RECTL rct = &(array[index]);
+ rct->left = ul.x;
+ rct->top = ul.y;
+ rct->right = lr.x;
+ rct->bottom = lr.y;
+}
+
+/**
\brief Set sizel objects with X,Y values.
\param x X coordinate
\param y Y coordinate
@@ -2192,7 +2212,7 @@ U_RGNDATAHEADER rgndataheader_set(
rdh.dwSize = U_RDH_OBJSIZE;
rdh.iType = U_RDH_RECTANGLES;
rdh.nCount = nCount;
- rdh.nRgnSize = nCount * sizeof(U_RECTL); // Size in bytes of retangle array
+ rdh.nRgnSize = nCount * sizeof(U_RECTL); // Size in bytes of rectangle array
rdh.rclBounds = rclBounds;
return(rdh);
}
@@ -2857,7 +2877,7 @@ by end user code and to further that end prototypes are NOT provided and they ar
// Functions with the same form starting with U_EMRPOLYBEZIER_set
-char *U_EMR_CORE1(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
+char *U_EMR_CORE1_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
char *record;
int cbPoints;
int irecsize;
@@ -2876,7 +2896,7 @@ char *U_EMR_CORE1(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const
}
// Functions with the same form starting with U_EMR_POLYPOLYLINE
-char *U_EMR_CORE2(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
+char *U_EMR_CORE2_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
char *record;
int cbPolys,cbPoints,off;
int irecsize;
@@ -2899,7 +2919,7 @@ char *U_EMR_CORE2(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, cons
}
// Functions with the same form starting with U_EMR_SETMAPMODE_set
-char *U_EMR_CORE3(uint32_t iType, uint32_t iMode){
+char *U_EMR_CORE3_set(uint32_t iType, uint32_t iMode){
char *record;
int irecsize;
@@ -2914,7 +2934,7 @@ char *U_EMR_CORE3(uint32_t iType, uint32_t iMode){
}
// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_set, also U_EMRFILLPATH,
-char *U_EMR_CORE4(uint32_t iType, U_RECTL rclBox){
+char *U_EMR_CORE4_set(uint32_t iType, U_RECTL rclBox){
char *record;
int irecsize;
@@ -2930,7 +2950,7 @@ char *U_EMR_CORE4(uint32_t iType, U_RECTL rclBox){
}
// Functions with the same form starting with U_EMRSETMETARGN_set
-char *U_EMR_CORE5(uint32_t iType){
+char *U_EMR_CORE5_set(uint32_t iType){
char *record;
int irecsize = 8;
@@ -2943,7 +2963,7 @@ char *U_EMR_CORE5(uint32_t iType){
}
// Functions with the same form starting with U_EMRPOLYBEZIER16_set
-char *U_EMR_CORE6(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){
+char *U_EMR_CORE6_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){
char *record;
int cbPoints,cbPoints4,off;
int irecsize;
@@ -2970,7 +2990,7 @@ char *U_EMR_CORE6(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const
// Functions that take a single struct argument which contains two uint32_t, starting with U_EMRSETWINDOWEXTEX_set
// these all pass two 32 bit ints and are cast by the caller to U_PAIR
-char *U_EMR_CORE7(uint32_t iType, U_PAIR pair){
+char *U_EMR_CORE7_set(uint32_t iType, U_PAIR pair){
char *record;
int irecsize = sizeof(U_EMRGENERICPAIR);
@@ -2984,7 +3004,7 @@ char *U_EMR_CORE7(uint32_t iType, U_PAIR pair){
}
// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW
-char *U_EMR_CORE8(
+char *U_EMR_CORE8_set(
uint32_t iType,
U_RECTL rclBounds, // Bounding rectangle in device units
uint32_t iGraphicsMode, // Graphics mode Enumeration
@@ -3033,7 +3053,7 @@ char *U_EMR_CORE8(
}
// Functions that take a rect and a pair of points, starting with U_EMRARC_set
-char *U_EMR_CORE9(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
+char *U_EMR_CORE9_set(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
char *record;
int irecsize = sizeof(U_EMRARC);
@@ -3049,7 +3069,7 @@ char *U_EMR_CORE9(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL pt
}
// Functions with the same form starting with U_EMR_POLYPOLYLINE16
-char *U_EMR_CORE10(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){
+char *U_EMR_CORE10_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){
char *record;
int cbPoints,cbPolys,off;
int irecsize;
@@ -3072,25 +3092,27 @@ char *U_EMR_CORE10(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, con
}
// common code for U_EMRINVERTRGN and U_EMRPAINTRGN,
-char *U_EMR_CORE11(uint32_t iType, PU_RGNDATA RgnData){
+char *U_EMR_CORE11_set(uint32_t iType, PU_RGNDATA RgnData){
char *record;
int irecsize;
- int cbRgns,cbRgns4,off;
+ int cbRgns,cbRgns4,rds,rds4,off;
if(!RgnData)return(NULL);
cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
cbRgns4 = UP4(cbRgns);
- irecsize = sizeof(U_EMRINVERTRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
- record = malloc(irecsize);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRINVERTRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
+ record = malloc(irecsize);
if(record){
((PU_EMR) record)->iType = iType;
((PU_EMR) record)->nSize = irecsize;
((PU_EMRINVERTRGN) record)->rclBounds = ((PU_RGNDATAHEADER) RgnData)->rclBounds;
- ((PU_EMRINVERTRGN) record)->cbRgnData = cbRgns;
- off = irecsize - cbRgns4;
- memcpy(record + off, RgnData, cbRgns);
- off += cbRgns;
- if(cbRgns < cbRgns4){ memset(record + off,0, cbRgns4 - cbRgns); } // clear any unused bytes
+ ((PU_EMRINVERTRGN) record)->cbRgnData = rds;
+ off = sizeof(U_EMRINVERTRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
}
return(record);
}
@@ -3274,7 +3296,7 @@ char *U_EMRPOLYBEZIER_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE1(U_EMR_POLYBEZIER, rclBounds, cptl, points));
+ return(U_EMR_CORE1_set(U_EMR_POLYBEZIER, rclBounds, cptl, points));
}
// U_EMRPOLYGON_set 3
@@ -3290,7 +3312,7 @@ char *U_EMRPOLYGON_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE1(U_EMR_POLYGON, rclBounds, cptl, points));
+ return(U_EMR_CORE1_set(U_EMR_POLYGON, rclBounds, cptl, points));
}
// U_EMRPOLYLINE_set 4
@@ -3306,7 +3328,7 @@ char *U_EMRPOLYLINE_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE1(U_EMR_POLYLINE, rclBounds, cptl, points));
+ return(U_EMR_CORE1_set(U_EMR_POLYLINE, rclBounds, cptl, points));
}
// U_EMRPOLYBEZIERTO_set 5
@@ -3322,7 +3344,7 @@ char *U_EMRPOLYBEZIERTO_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE1(U_EMR_POLYBEZIERTO, rclBounds, cptl, points));
+ return(U_EMR_CORE1_set(U_EMR_POLYBEZIERTO, rclBounds, cptl, points));
}
// U_EMRPOLYLINETO_set 6
@@ -3338,7 +3360,7 @@ char *U_EMRPOLYLINETO_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE1(U_EMR_POLYLINETO, rclBounds, cptl, points));
+ return(U_EMR_CORE1_set(U_EMR_POLYLINETO, rclBounds, cptl, points));
}
// U_EMRPOLYPOLYLINE_set 7
@@ -3358,7 +3380,7 @@ char *U_EMRPOLYPOLYLINE_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE2(U_EMR_POLYPOLYLINE, rclBounds, nPolys, aPolyCounts,cptl, points));
+ return(U_EMR_CORE2_set(U_EMR_POLYPOLYLINE, rclBounds, nPolys, aPolyCounts,cptl, points));
}
// U_EMRPOLYPOLYGON_set 8
@@ -3378,7 +3400,7 @@ char *U_EMRPOLYPOLYGON_set(
const uint32_t cptl,
const U_POINTL *points
){
- return(U_EMR_CORE2(U_EMR_POLYPOLYGON, rclBounds, nPolys, aPolyCounts,cptl, points));
+ return(U_EMR_CORE2_set(U_EMR_POLYPOLYGON, rclBounds, nPolys, aPolyCounts,cptl, points));
}
// U_EMRSETWINDOWEXTEX_set 9
@@ -3393,7 +3415,7 @@ char *U_EMRSETWINDOWEXTEX_set(
U_PAIR temp;
temp.x = szlExtent.cx;
temp.y = szlExtent.cy;
- return(U_EMR_CORE7(U_EMR_SETWINDOWEXTEX, temp));
+ return(U_EMR_CORE7_set(U_EMR_SETWINDOWEXTEX, temp));
}
// U_EMRSETWINDOWORGEX_set 10
@@ -3405,7 +3427,7 @@ char *U_EMRSETWINDOWEXTEX_set(
char *U_EMRSETWINDOWORGEX_set(
const U_POINTL ptlOrigin
){
- return(U_EMR_CORE7(U_EMR_SETWINDOWORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
+ return(U_EMR_CORE7_set(U_EMR_SETWINDOWORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
}
// U_EMRSETVIEWPORTEXTEX_set 11
@@ -3420,7 +3442,7 @@ char *U_EMRSETVIEWPORTEXTEX_set(
U_PAIR temp;
temp.x = szlExtent.cx;
temp.y = szlExtent.cy;
- return(U_EMR_CORE7(U_EMR_SETVIEWPORTEXTEX, temp));
+ return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTEXTEX, temp));
}
// U_EMRSETVIEWPORTORGEX_set 12
@@ -3432,7 +3454,7 @@ char *U_EMRSETVIEWPORTEXTEX_set(
char *U_EMRSETVIEWPORTORGEX_set(
const U_POINTL ptlOrigin
){
- return(U_EMR_CORE7(U_EMR_SETVIEWPORTORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
+ return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
}
// U_EMRSETBRUSHORGEX_set 13
@@ -3444,7 +3466,7 @@ char *U_EMRSETVIEWPORTORGEX_set(
char *U_EMRSETBRUSHORGEX_set(
const U_POINTL ptlOrigin
){
- return(U_EMR_CORE7(U_EMR_SETBRUSHORGEX, *((PU_PAIR) & ptlOrigin)));
+ return(U_EMR_CORE7_set(U_EMR_SETBRUSHORGEX, *((PU_PAIR) & ptlOrigin)));
}
// U_EMREOF_set 14
@@ -3544,7 +3566,7 @@ char *U_EMRSETMAPPERFLAGS_set(void){
char *U_EMRSETMAPMODE_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETMAPMODE, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETMAPMODE, iMode));
}
// U_EMRSETBKMODE_set 18
@@ -3556,7 +3578,7 @@ char *U_EMRSETMAPMODE_set(
char *U_EMRSETBKMODE_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETBKMODE, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETBKMODE, iMode));
}
// U_EMRSETPOLYFILLMODE_set 19
@@ -3568,7 +3590,7 @@ char *U_EMRSETBKMODE_set(
char *U_EMRSETPOLYFILLMODE_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETPOLYFILLMODE, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETPOLYFILLMODE, iMode));
}
// U_EMRSETROP2_set 20
@@ -3580,7 +3602,7 @@ char *U_EMRSETPOLYFILLMODE_set(
char *U_EMRSETROP2_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETROP2, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETROP2, iMode));
}
// U_EMRSETSTRETCHBLTMODE_set 21
@@ -3592,7 +3614,7 @@ char *U_EMRSETROP2_set(
char *U_EMRSETSTRETCHBLTMODE_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETSTRETCHBLTMODE, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETSTRETCHBLTMODE, iMode));
}
// U_EMRSETTEXTALIGN_set 22
@@ -3604,7 +3626,7 @@ char *U_EMRSETSTRETCHBLTMODE_set(
char *U_EMRSETTEXTALIGN_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETTEXTALIGN, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETTEXTALIGN, iMode));
}
// U_EMRSETCOLORADJUSTMENT_set 23
@@ -3638,7 +3660,7 @@ char *U_EMRSETCOLORADJUSTMENT_set(
char *U_EMRSETTEXTCOLOR_set(
const U_COLORREF crColor
){
- return(U_EMR_CORE3(U_EMR_SETTEXTCOLOR, *(uint32_t *) &crColor));
+ return(U_EMR_CORE3_set(U_EMR_SETTEXTCOLOR, *(uint32_t *) &crColor));
}
// U_EMRSETBKCOLOR_set 25
@@ -3650,7 +3672,7 @@ char *U_EMRSETTEXTCOLOR_set(
char *U_EMRSETBKCOLOR_set(
const U_COLORREF crColor
){
- return(U_EMR_CORE3(U_EMR_SETBKCOLOR, *(uint32_t *) &crColor));
+ return(U_EMR_CORE3_set(U_EMR_SETBKCOLOR, *(uint32_t *) &crColor));
}
// U_EMROFFSETCLIPRGN_set 26
@@ -3662,7 +3684,7 @@ char *U_EMRSETBKCOLOR_set(
char *U_EMROFFSETCLIPRGN_set(
const U_POINTL ptl
){
- return(U_EMR_CORE7(U_EMR_OFFSETCLIPRGN, ptl));
+ return(U_EMR_CORE7_set(U_EMR_OFFSETCLIPRGN, ptl));
}
// U_EMRMOVETOEX_set 27
@@ -3674,7 +3696,7 @@ char *U_EMROFFSETCLIPRGN_set(
char *U_EMRMOVETOEX_set(
const U_POINTL ptl
){
- return(U_EMR_CORE7(U_EMR_MOVETOEX, ptl));
+ return(U_EMR_CORE7_set(U_EMR_MOVETOEX, ptl));
}
// U_EMRSETMETARGN_set 28
@@ -3683,7 +3705,7 @@ char *U_EMRMOVETOEX_set(
\return pointer to U_EMR_SETMETARGN record, or NULL on error.
*/
char *U_EMRSETMETARGN_set(void){
- return(U_EMR_CORE5(U_EMR_SETMETARGN));
+ return(U_EMR_CORE5_set(U_EMR_SETMETARGN));
}
// U_EMREXCLUDECLIPRECT_set 29
@@ -3695,7 +3717,7 @@ char *U_EMRSETMETARGN_set(void){
char *U_EMREXCLUDECLIPRECT_set(
const U_RECTL rclClip
){
- return(U_EMR_CORE4(U_EMR_EXCLUDECLIPRECT,rclClip));
+ return(U_EMR_CORE4_set(U_EMR_EXCLUDECLIPRECT,rclClip));
}
// U_EMRINTERSECTCLIPRECT_set 30
@@ -3707,7 +3729,7 @@ char *U_EMREXCLUDECLIPRECT_set(
char *U_EMRINTERSECTCLIPRECT_set(
const U_RECTL rclClip
){
- return(U_EMR_CORE4(U_EMR_INTERSECTCLIPRECT,rclClip));
+ return(U_EMR_CORE4_set(U_EMR_INTERSECTCLIPRECT,rclClip));
}
// U_EMRSCALEVIEWPORTEXTEX_set 31
@@ -3725,7 +3747,7 @@ char *U_EMRSCALEVIEWPORTEXTEX_set(
const int32_t yNum,
const int32_t yDenom
){
- return(U_EMR_CORE4(U_EMR_SCALEVIEWPORTEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
+ return(U_EMR_CORE4_set(U_EMR_SCALEVIEWPORTEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
}
@@ -3744,7 +3766,7 @@ char *U_EMRSCALEWINDOWEXTEX_set(
const int32_t yNum,
const int32_t yDenom
){
- return(U_EMR_CORE4(U_EMR_SCALEWINDOWEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
+ return(U_EMR_CORE4_set(U_EMR_SCALEWINDOWEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
}
// U_EMRSAVEDC_set 33
@@ -3753,7 +3775,7 @@ char *U_EMRSCALEWINDOWEXTEX_set(
\return pointer to U_EMR_SAVEDC record, or NULL on error.
*/
char *U_EMRSAVEDC_set(void){
- return(U_EMR_CORE5(U_EMR_SAVEDC));
+ return(U_EMR_CORE5_set(U_EMR_SAVEDC));
}
// U_EMRRESTOREDC_set 34
@@ -3765,7 +3787,7 @@ char *U_EMRSAVEDC_set(void){
char *U_EMRRESTOREDC_set(
const int32_t iRelative
){
- return(U_EMR_CORE3(U_EMR_RESTOREDC, (uint32_t) iRelative));
+ return(U_EMR_CORE3_set(U_EMR_RESTOREDC, (uint32_t) iRelative));
}
// U_EMRSETWORLDTRANSFORM_set 35
@@ -3952,7 +3974,7 @@ char *U_EMRANGLEARC_set(
char *U_EMRELLIPSE_set(
const U_RECTL rclBox
){
- return(U_EMR_CORE4(U_EMR_ELLIPSE,rclBox));
+ return(U_EMR_CORE4_set(U_EMR_ELLIPSE,rclBox));
}
// U_EMRRECTANGLE_set 43
@@ -3964,7 +3986,7 @@ char *U_EMRELLIPSE_set(
char *U_EMRRECTANGLE_set(
const U_RECTL rclBox
){
- return(U_EMR_CORE4(U_EMR_RECTANGLE,rclBox));
+ return(U_EMR_CORE4_set(U_EMR_RECTANGLE,rclBox));
}
// U_EMRROUNDRECT_set 44
@@ -4005,7 +4027,7 @@ char *U_EMRARC_set(
const U_POINTL ptlStart,
const U_POINTL ptlEnd
){
- return(U_EMR_CORE9(U_EMR_ARC,rclBox, ptlStart, ptlEnd));
+ return(U_EMR_CORE9_set(U_EMR_ARC,rclBox, ptlStart, ptlEnd));
}
// U_EMRCHORD_set 46
@@ -4021,7 +4043,7 @@ char *U_EMRCHORD_set(
const U_POINTL ptlStart,
const U_POINTL ptlEnd
){
- return(U_EMR_CORE9(U_EMR_CHORD,rclBox, ptlStart, ptlEnd));
+ return(U_EMR_CORE9_set(U_EMR_CHORD,rclBox, ptlStart, ptlEnd));
}
// U_EMRPIE_set 47
@@ -4037,7 +4059,7 @@ char *U_EMRPIE_set(
const U_POINTL ptlStart,
const U_POINTL ptlEnd
){
- return(U_EMR_CORE9(U_EMR_PIE,rclBox, ptlStart, ptlEnd));
+ return(U_EMR_CORE9_set(U_EMR_PIE,rclBox, ptlStart, ptlEnd));
}
// U_EMRSELECTPALETTE_set 48
@@ -4049,7 +4071,7 @@ char *U_EMRPIE_set(
char *U_EMRSELECTPALETTE_set(
const uint32_t ihPal
){
- return(U_EMR_CORE3(U_EMR_SELECTPALETTE, ihPal));
+ return(U_EMR_CORE3_set(U_EMR_SELECTPALETTE, ihPal));
}
// U_EMRCREATEPALETTE_set 49
@@ -4124,7 +4146,7 @@ char *U_EMRRESIZEPALETTE_set(
const uint32_t ihPal,
const uint32_t cEntries
){
- return(U_EMR_CORE7(U_EMR_RESIZEPALETTE, (U_PAIR){ihPal,cEntries}));
+ return(U_EMR_CORE7_set(U_EMR_RESIZEPALETTE, (U_PAIR){ihPal,cEntries}));
}
// U_EMRREALIZEPALETTE_set 52
@@ -4133,7 +4155,7 @@ char *U_EMRRESIZEPALETTE_set(
\return pointer to U_EMR_REALIZEPALETTE record, or NULL on error.
*/
char *U_EMRREALIZEPALETTE_set(void){
- return(U_EMR_CORE5(U_EMR_REALIZEPALETTE));
+ return(U_EMR_CORE5_set(U_EMR_REALIZEPALETTE));
}
// U_EMREXTFLOODFILL_set 53
@@ -4173,7 +4195,7 @@ char *U_EMREXTFLOODFILL_set(
char *U_EMRLINETO_set(
const U_POINTL ptl
){
- return(U_EMR_CORE7(U_EMR_LINETO, ptl));
+ return(U_EMR_CORE7_set(U_EMR_LINETO, ptl));
}
// U_EMRARCTO_set 55
@@ -4192,7 +4214,7 @@ char *U_EMRARCTO_set(
U_POINTL ptlStart,
U_POINTL ptlEnd
){
- return(U_EMR_CORE9(U_EMR_ARCTO,rclBox, ptlStart, ptlEnd));
+ return(U_EMR_CORE9_set(U_EMR_ARCTO,rclBox, ptlStart, ptlEnd));
}
// U_EMRPOLYDRAW_set 56
@@ -4216,7 +4238,7 @@ char *U_EMRPOLYDRAW_set(
if(!cptl || !aptl || !abTypes)return(NULL);
cbPoints = cptl * sizeof(U_POINTL); // space for aptl
- cbAbTypes = cptl; // number of abTypes (also size, 1 byte each)
+ cbAbTypes = cptl; // number of abTypes (same array size, 1 byte each)
cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
irecsize = sizeof(U_EMRPOLYDRAW) + cbPoints + cbAbTypes4 - sizeof(U_POINTL) - 1;
record = malloc(irecsize);
@@ -4244,7 +4266,7 @@ char *U_EMRPOLYDRAW_set(
char *U_EMRSETARCDIRECTION_set(
const uint32_t iArcDirection
){
- return(U_EMR_CORE3(U_EMR_SETARCDIRECTION, iArcDirection));
+ return(U_EMR_CORE3_set(U_EMR_SETARCDIRECTION, iArcDirection));
}
// U_EMRSETMITERLIMIT_set 58
@@ -4256,7 +4278,7 @@ char *U_EMRSETARCDIRECTION_set(
char *U_EMRSETMITERLIMIT_set(
const uint32_t eMiterLimit
){
- return(U_EMR_CORE3(U_EMR_SETMITERLIMIT, eMiterLimit));
+ return(U_EMR_CORE3_set(U_EMR_SETMITERLIMIT, eMiterLimit));
}
@@ -4266,7 +4288,7 @@ char *U_EMRSETMITERLIMIT_set(
\return pointer to U_EMR_BEGINPATH record, or NULL on error.
*/
char *U_EMRBEGINPATH_set(void){
- return(U_EMR_CORE5(U_EMR_BEGINPATH));
+ return(U_EMR_CORE5_set(U_EMR_BEGINPATH));
}
// U_EMRENDPATH_set 60
@@ -4275,7 +4297,7 @@ char *U_EMRBEGINPATH_set(void){
\return pointer to U_EMR_ENDPATH record, or NULL on error.
*/
char *U_EMRENDPATH_set(void){
- return(U_EMR_CORE5(U_EMR_ENDPATH));
+ return(U_EMR_CORE5_set(U_EMR_ENDPATH));
}
// U_EMRCLOSEFIGURE_set 61
@@ -4284,7 +4306,7 @@ char *U_EMRENDPATH_set(void){
\return pointer to U_EMR_CLOSEFIGURE record, or NULL on error.
*/
char *U_EMRCLOSEFIGURE_set(void){
- return(U_EMR_CORE5(U_EMR_CLOSEFIGURE));
+ return(U_EMR_CORE5_set(U_EMR_CLOSEFIGURE));
}
// U_EMRFILLPATH_set 62
@@ -4298,7 +4320,7 @@ char *U_EMRCLOSEFIGURE_set(void){
char *U_EMRFILLPATH_set(
const U_RECTL rclBox
){
- return(U_EMR_CORE4(U_EMR_FILLPATH,rclBox));
+ return(U_EMR_CORE4_set(U_EMR_FILLPATH,rclBox));
}
// U_EMRSTROKEANDFILLPATH_set 63
@@ -4314,7 +4336,7 @@ char *U_EMRFILLPATH_set(
char *U_EMRSTROKEANDFILLPATH_set(
const U_RECTL rclBox
){
- return(U_EMR_CORE4(U_EMR_STROKEANDFILLPATH,rclBox));
+ return(U_EMR_CORE4_set(U_EMR_STROKEANDFILLPATH,rclBox));
}
// U_EMRSTROKEPATH_set 64
@@ -4328,7 +4350,7 @@ char *U_EMRSTROKEANDFILLPATH_set(
char *U_EMRSTROKEPATH_set(
const U_RECTL rclBox
){
- return(U_EMR_CORE4(U_EMR_STROKEPATH,rclBox));
+ return(U_EMR_CORE4_set(U_EMR_STROKEPATH,rclBox));
}
// U_EMRFLATTENPATH_set 65
@@ -4337,7 +4359,7 @@ char *U_EMRSTROKEPATH_set(
\return pointer to U_EMR_FLATTENPATH record, or NULL on error.
*/
char *U_EMRFLATTENPATH_set(void){
- return(U_EMR_CORE5(U_EMR_FLATTENPATH));
+ return(U_EMR_CORE5_set(U_EMR_FLATTENPATH));
}
// U_EMRWIDENPATH_set 66
@@ -4346,7 +4368,7 @@ char *U_EMRFLATTENPATH_set(void){
\return pointer to U_EMR_WIDENPATH record, or NULL on error.
*/
char *U_EMRWIDENPATH_set(void){
- return(U_EMR_CORE5(U_EMR_WIDENPATH));
+ return(U_EMR_CORE5_set(U_EMR_WIDENPATH));
}
// U_EMRSELECTCLIPPATH_set 67
@@ -4358,7 +4380,7 @@ char *U_EMRWIDENPATH_set(void){
char *U_EMRSELECTCLIPPATH_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SELECTCLIPPATH, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SELECTCLIPPATH, iMode));
}
// U_EMRABORTPATH_set 68
@@ -4367,7 +4389,7 @@ char *U_EMRSELECTCLIPPATH_set(
\return pointer to U_EMR_ABORTPATH record, or NULL on error.
*/
char *U_EMRABORTPATH_set(void){
- return(U_EMR_CORE5(U_EMR_ABORTPATH));
+ return(U_EMR_CORE5_set(U_EMR_ABORTPATH));
}
// U_EMRUNDEF69 69
@@ -4416,23 +4438,25 @@ char *U_EMRFILLRGN_set(
){
char *record;
int irecsize;
- int cbRgns,cbRgns4,off;
+ int cbRgns,cbRgns4,rds,rds4,off;
if(!RgnData)return(NULL);
cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
- cbRgns4 = UP4(cbRgns);
- irecsize = sizeof(U_EMRFILLRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRFILLRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
record = malloc(irecsize);
if(record){
((PU_EMR) record)->iType = U_EMR_FILLRGN;
((PU_EMR) record)->nSize = irecsize;
- ((PU_EMRFILLRGN) record)->rclBounds = rclBounds; // or ??? ((PU_RGNDATAHEADER) RgnData)->rclBounds;
- ((PU_EMRFILLRGN) record)->cbRgnData = cbRgns;
+ ((PU_EMRFILLRGN) record)->rclBounds = rclBounds;
+ ((PU_EMRFILLRGN) record)->cbRgnData = rds;
((PU_EMRFILLRGN) record)->ihBrush = ihBrush;
- off = irecsize - cbRgns4;
- memcpy(record + off, RgnData, cbRgns);
- off += cbRgns;
- if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // clear any unused bytes
+ off = sizeof(U_EMRFILLRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
}
return(record);
}
@@ -4455,24 +4479,26 @@ char *U_EMRFRAMERGN_set(
){
char *record;
int irecsize;
- int cbRgns,cbRgns4,off;
+ int cbRgns,cbRgns4,rds,rds4,off;
if(!RgnData)return(NULL);
cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
- cbRgns4 = UP4(cbRgns);
- irecsize = sizeof(U_EMRFRAMERGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRFRAMERGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
record = malloc(irecsize);
if(record){
((PU_EMR) record)->iType = U_EMR_FRAMERGN;
((PU_EMR) record)->nSize = irecsize;
- ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds; // or ??? ((PU_RGNDATAHEADER) RgnData)->rclBounds;
- ((PU_EMRFRAMERGN) record)->cbRgnData = cbRgns;
+ ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds;
+ ((PU_EMRFRAMERGN) record)->cbRgnData = rds;
((PU_EMRFRAMERGN) record)->ihBrush = ihBrush;
((PU_EMRFRAMERGN) record)->szlStroke = szlStroke;
- off = irecsize - cbRgns4;
- memcpy(record + off, RgnData, cbRgns);
- off += cbRgns;
- if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // clear any unused bytes
+ off = sizeof(U_EMRFRAMERGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
}
return(record);
}
@@ -4486,7 +4512,7 @@ char *U_EMRFRAMERGN_set(
char *U_EMRINVERTRGN_set(
const PU_RGNDATA RgnData
){
- return(U_EMR_CORE11(U_EMR_INVERTRGN, RgnData));
+ return(U_EMR_CORE11_set(U_EMR_INVERTRGN, RgnData));
}
// U_EMRPAINTRGN_set 74
@@ -4498,7 +4524,7 @@ char *U_EMRINVERTRGN_set(
char *U_EMRPAINTRGN_set(
const PU_RGNDATA RgnData
){
- return(U_EMR_CORE11(U_EMR_PAINTRGN, RgnData));
+ return(U_EMR_CORE11_set(U_EMR_PAINTRGN, RgnData));
}
// U_EMREXTSELECTCLIPRGN_set 75
@@ -4514,22 +4540,24 @@ char *U_EMREXTSELECTCLIPRGN_set(
){
char *record;
int irecsize;
- int cbRgns,cbRgns4,off;
+ int cbRgns,cbRgns4,rds,rds4,off;
if(!RgnData)return(NULL);
cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
- cbRgns4 = UP4(cbRgns);
- irecsize = sizeof(U_EMREXTSELECTCLIPRGN) + cbRgns4 - sizeof(U_RGNDATAHEADER); // core + array - overlap
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
record = malloc(irecsize);
if(record){
((PU_EMR) record)->iType = U_EMR_EXTSELECTCLIPRGN;
((PU_EMR) record)->nSize = irecsize;
- ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = cbRgns;
+ ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = rds;
((PU_EMREXTSELECTCLIPRGN) record)->iMode = iMode;
- off = irecsize - cbRgns4;
- memcpy(record + off, RgnData, cbRgns);
- off += cbRgns;
- if(cbRgns4 > cbRgns){ memset(record + off,0,cbRgns4-cbRgns); } // clear any unused bytes
+ off = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
}
return(record);
}
@@ -4568,7 +4596,6 @@ char *U_EMRBITBLT_set(
int cbImage,cbImage4,cbBmi,off;
SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
-
irecsize = sizeof(U_EMRBITBLT) + cbBmi + cbImage4;
record = malloc(irecsize);
if(record){
@@ -4933,7 +4960,7 @@ char *U_EMREXTTEXTOUTA_set(
const U_FLOAT eyScale,
const PU_EMRTEXT emrtext
){
- return(U_EMR_CORE8(U_EMR_EXTTEXTOUTA,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
+ return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTA,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
}
// U_EMREXTTEXTOUTW_set 84
@@ -4953,7 +4980,7 @@ char *U_EMREXTTEXTOUTW_set(
const U_FLOAT eyScale,
const PU_EMRTEXT emrtext
){
- return(U_EMR_CORE8(U_EMR_EXTTEXTOUTW,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
+ return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTW,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
}
// U_EMRPOLYBEZIER16_set 85
@@ -4969,7 +4996,7 @@ char *U_EMRPOLYBEZIER16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE6(U_EMR_POLYBEZIER16, rclBounds, cpts, points));
+ return(U_EMR_CORE6_set(U_EMR_POLYBEZIER16, rclBounds, cpts, points));
}
// U_EMRPOLYGON16_set 86
@@ -4985,7 +5012,7 @@ char *U_EMRPOLYGON16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE6(U_EMR_POLYGON16, rclBounds, cpts, points));
+ return(U_EMR_CORE6_set(U_EMR_POLYGON16, rclBounds, cpts, points));
}
// U_EMRPOLYLINE16_set 87
@@ -5001,7 +5028,7 @@ char *U_EMRPOLYLINE16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE6(U_EMR_POLYLINE16, rclBounds, cpts, points));
+ return(U_EMR_CORE6_set(U_EMR_POLYLINE16, rclBounds, cpts, points));
}
// U_EMRPOLYBEZIERTO16_set 88
@@ -5017,7 +5044,7 @@ char *U_EMRPOLYBEZIERTO16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE6(U_EMR_POLYBEZIERTO16, rclBounds, cpts, points));
+ return(U_EMR_CORE6_set(U_EMR_POLYBEZIERTO16, rclBounds, cpts, points));
}
// U_EMRPOLYLINETO16_set 89
@@ -5033,7 +5060,7 @@ char *U_EMRPOLYLINETO16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE6(U_EMR_POLYLINETO16, rclBounds, cpts, points));
+ return(U_EMR_CORE6_set(U_EMR_POLYLINETO16, rclBounds, cpts, points));
}
// U_EMRPOLYPOLYLINE16_set 90
@@ -5053,7 +5080,7 @@ char *U_EMRPOLYPOLYLINE16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE10(U_EMR_POLYPOLYLINE16, rclBounds, nPolys, aPolyCounts,cpts, points));
+ return(U_EMR_CORE10_set(U_EMR_POLYPOLYLINE16, rclBounds, nPolys, aPolyCounts,cpts, points));
}
// U_EMRPOLYPOLYGON16_set 91
@@ -5073,7 +5100,7 @@ char *U_EMRPOLYPOLYGON16_set(
const uint32_t cpts,
const U_POINT16 *points
){
- return(U_EMR_CORE10(U_EMR_POLYPOLYGON16, rclBounds, nPolys, aPolyCounts,cpts, points));
+ return(U_EMR_CORE10_set(U_EMR_POLYPOLYGON16, rclBounds, nPolys, aPolyCounts,cpts, points));
}
@@ -5098,7 +5125,7 @@ char *U_EMRPOLYDRAW16_set(
if(!cpts || !aptl || !abTypes)return(NULL);
cbPoints = cpts * sizeof(U_POINT16); // space for aptl
- cbAbTypes = cpts; // number of abTypes (also size, 1 byte each)
+ cbAbTypes = cpts; // number of abTypes (same array size, 1 byte each)
cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
irecsize = sizeof(U_EMRPOLYDRAW16) + cbPoints + cbAbTypes4 - sizeof(U_POINT16) - 1;
record = malloc(irecsize);
@@ -5242,7 +5269,7 @@ char *U_EMREXTCREATEPEN_set(
char *U_EMRSETICMMODE_set(
const uint32_t iMode
){
- return(U_EMR_CORE3(U_EMR_SETICMMODE, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETICMMODE, iMode));
}
// U_EMRCREATECOLORSPACE_set 99
@@ -5280,7 +5307,7 @@ char *U_EMRCREATECOLORSPACE_set(
char *U_EMRSETCOLORSPACE_set(
const uint32_t ihCS
){
- return(U_EMR_CORE3(U_EMR_SETCOLORSPACE, ihCS));
+ return(U_EMR_CORE3_set(U_EMR_SETCOLORSPACE, ihCS));
}
// U_EMRDELETECOLORSPACE_set 101
@@ -5292,7 +5319,7 @@ char *U_EMRSETCOLORSPACE_set(
char *U_EMRDELETECOLORSPACE_set(
const uint32_t ihCS
){
- return(U_EMR_CORE3(U_EMR_DELETECOLORSPACE, ihCS));
+ return(U_EMR_CORE3_set(U_EMR_DELETECOLORSPACE, ihCS));
}
// U_EMRGLSRECORD_set 102 Not implemented
@@ -5428,7 +5455,7 @@ char *U_EMRALPHABLEND_set(
\param iMode Mirroring Enumeration
*/
char *U_EMRSETLAYOUT_set(uint32_t iMode){
- return(U_EMR_CORE3(U_EMR_SETLAYOUT, iMode));
+ return(U_EMR_CORE3_set(U_EMR_SETLAYOUT, iMode));
}
// U_EMRTRANSPARENTBLT_set 116
diff --git a/src/libuemf/uemf.h b/src/libuemf/uemf.h
index a792a65de..53426cb55 100644
--- a/src/libuemf/uemf.h
+++ b/src/libuemf/uemf.h
@@ -95,11 +95,11 @@ these WMF enumerations is by referencing the following table:
/*
File: uemf.h
-Version: 0.0.27
-Date: 28-MAR-2014
+Version: 0.0.31
+Date: 23-APR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifndef _UEMF_
@@ -167,6 +167,9 @@ extern "C" {
/** Solaris 8 has problems with round/roundf, just use this everywhere */
#define U_ROUND(A) ( (A) > 0 ? floor((A)+0.5) : ( (A) < 0 ? -floor(-(A)+0.5) : (A) ) )
+#define MAKE_MIN_PTR(A,B) ( A < B ? A : B)
+#define IS_MEM_UNSAFE(A,B,C) ( (int8_t *)(A) > (int8_t *)(C) ? 1 : ((int8_t *)(C) - (int8_t *)(A) >= (int)(B) ? 0 : 1 )) //!< Return 1 when a region of memory starting at A of B bytes extends beyond pointer C
+
/** @} */
@@ -1799,7 +1802,7 @@ typedef struct { //!< In MS documentation this is Log
*PU_PATTERN; //!< EMF manual 2.2.12
/**
- \brief For U_LOGFONT_PANOSE elfLogFont field
+ \brief For U_LOGFONT elfLogFont field
EMF manual 2.2.13, Microsoft name: LogFont Object
*/
@@ -2075,6 +2078,9 @@ typedef struct {
// ***********************************************************************************
// The following have U_EMR_# records. They are ordered by their record index, not by EMF manual position.
+// records which are documented but not implemented
+#define U_SIZE_EMRNOTIMPLEMENTED 2048
+
/* Index 1 */
/**
\brief The first U_ENHMETARECORD record in the metafile.
@@ -2117,6 +2123,8 @@ typedef struct {
U_SIZEL szlMicrometers; //!< Size of the display device in micrometer
} U_EMRHEADER,
*PU_EMRHEADER; //!< EMF manual 2.2.9
+#define U_SIZE_EMRHEADER sizeof(U_EMRHEADER) // modern EMF files, for _really_ old ones the _MIN size applies
+#define U_SIZE_EMRHEADER_MIN (U_SIZE_EMRHEADER - sizeof(U_CBPXLFMT) - sizeof(U_OFFPXLFMT) - sizeof(uint32_t) - sizeof(U_SIZEL))
/* Index 2,3,4,5,6 */
/** EMF manual 2.3.5.16
@@ -2137,6 +2145,11 @@ typedef struct {
*PU_EMRPOLYBEZIERTO, //!< EMF manual 2.3.5.18
*PU_EMRPOLYLINETO; //!< EMF manual 2.3.5.26
+#define U_SIZE_EMRPOLYBEZIER (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL) )
+#define U_SIZE_EMRPOLYGON U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYLINE U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYBEZIERTO U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYLINETO U_SIZE_EMRPOLYBEZIER
/* Index 7,8 */
/** EMF manual 2.3.5.30
@@ -2153,6 +2166,8 @@ typedef struct {
U_EMRPOLYPOLYGON, //!< EMF manual 2.3.5.28
*PU_EMRPOLYPOLYLINE, //!< EMF manual 2.3.5.30
*PU_EMRPOLYPOLYGON; //!< EMF manual 2.3.5.28
+#define U_SIZE_EMRPOLYPOLYLINE (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_POLYCOUNTS))
+#define U_SIZE_EMRPOLYPOLYGON U_SIZE_EMRPOLYPOLYLINE
/* Index 9,11 (numbers interleave with next one) */
/** EMF manual 2.3.11.30
@@ -2164,6 +2179,8 @@ typedef struct {
U_EMRSETVIEWPORTEXTEX, //!< EMF manual manual 2.3.11.28
*PU_EMRSETWINDOWEXTEX, //!< EMF manual manual 2.3.11.30
*PU_EMRSETVIEWPORTEXTEX; //!< EMF manual manual 2.3.11.28
+#define U_SIZE_EMRSETWINDOWEXTEX (sizeof(U_EMRSETWINDOWEXTEX ))
+#define U_SIZE_EMRSETVIEWPORTEXTEX (sizeof(U_EMRSETVIEWPORTEXTEX))
/* Index 10,12,13 */
/** EMF manual 2.3.11.31
@@ -2177,7 +2194,9 @@ typedef struct {
*PU_EMRSETWINDOWORGEX, //!< EMF manual 2.3.11.31
*PU_EMRSETVIEWPORTORGEX, //!< EMF manual 2.3.11.29
*PU_EMRSETBRUSHORGEX; //!< EMF manual 2.3.11.12
-
+#define U_SIZE_EMRSETWINDOWORGEX (sizeof(U_EMRSETWINDOWORGEX ))
+#define U_SIZE_EMRSETVIEWPORTORGEX (sizeof(U_EMRSETVIEWPORTORGEX))
+#define U_SIZE_EMRSETBRUSHORGEX (sizeof(U_EMRSETBRUSHORGEX ))
/* Index 14 */
/** EMF manual 3.2.4.1
@@ -2197,6 +2216,7 @@ typedef struct {
U_OFFPLENTRIES offPalEntries; //!< Offset in bytes to array of palette entries
} U_EMREOF,
*PU_EMREOF; //!< EMF manual 3.2.4.1
+#define U_SIZE_EMREOF (sizeof(U_EMREOF))
/* Index 15 */
/** EMF manual 2.3.5.36
@@ -2207,6 +2227,7 @@ typedef struct {
U_COLORREF crColor; //!< Pixel color
} U_EMRSETPIXELV,
*PU_EMRSETPIXELV; //!< EMF manual 2.3.5.36
+#define U_SIZE_EMRSETPIXELV (sizeof(U_EMRSETPIXELV))
/* Index 16 */
/** EMF manual 2.3.11.20
@@ -2216,6 +2237,7 @@ typedef struct {
uint32_t dwFlags; //!< must be 1
} U_EMRSETMAPPERFLAGS,
*PU_EMRSETMAPPERFLAGS; //!< EMF manual 2.3.11.20
+#define U_SIZE_EMRSETMAPPERFLAGS (sizeof(U_EMRSETMAPPERFLAGS))
/* Index 17,18,19,20,21,22,67,98,115
*/
@@ -2243,6 +2265,16 @@ typedef struct {
*PU_EMRSETICMMODE, //!< EMF manual 2.3.11.14 ICMMode Enumeration
*PU_EMRSETLAYOUT; //!< EMF manual 2.3.11.17 Mirroring Enumeration
+#define U_SIZE_EMRSETMAPMODE (sizeof(U_EMRSETMAPMODE ))
+#define U_SIZE_EMRSETBKMODE (sizeof(U_EMRSETBKMODE ))
+#define U_SIZE_EMRSETPOLYFILLMODE (sizeof(U_EMRSETPOLYFILLMODE ))
+#define U_SIZE_EMRSETROP2 (sizeof(U_EMRSETROP2 ))
+#define U_SIZE_EMRSETSTRETCHBLTMODE (sizeof(U_EMRSETSTRETCHBLTMODE))
+#define U_SIZE_EMRSETTEXTALIGN (sizeof(U_EMRSETTEXTALIGN ))
+#define U_SIZE_EMRSELECTCLIPPATH (sizeof(U_EMRSELECTCLIPPATH ))
+#define U_SIZE_EMRSETICMMODE (sizeof(U_EMRSETICMMODE ))
+#define U_SIZE_EMRSETLAYOUT (sizeof(U_EMRSETLAYOUT ))
+
/* Index 23 */
/** EMF manual 2.3.11.13
*/
@@ -2251,6 +2283,7 @@ typedef struct {
U_COLORADJUSTMENT ColorAdjustment; //!< Color Adjustment
} U_EMRSETCOLORADJUSTMENT,
*PU_EMRSETCOLORADJUSTMENT; //!< EMF manual 2.3.11.13
+#define U_SIZE_EMRSETCOLORADJUSTMENT (sizeof(U_EMRSETCOLORADJUSTMENT))
/* Index 24, 25 */
/** EMF manual 2.3.11.26
@@ -2262,6 +2295,8 @@ typedef struct {
U_EMRSETBKCOLOR, //!< EMF manual 2.3.11.10
*PU_EMRSETTEXTCOLOR, //!< EMF manual 2.3.11.26
*PU_EMRSETBKCOLOR; //!< EMF manual 2.3.11.10
+#define U_SIZE_EMRSETTEXTCOLOR (sizeof(U_EMRSETTEXTCOLOR))
+#define U_SIZE_EMRSETBKCOLOR (sizeof(U_EMRSETBKCOLOR ))
/* Index 26 */
/** EMF manual 2.3.2.4
@@ -2271,6 +2306,7 @@ typedef struct {
U_POINTL ptlOffset; //!< Clipping region
} U_EMROFFSETCLIPRGN,
*PU_EMROFFSETCLIPRGN; //!< EMF manual 2.3.2.4
+#define U_SIZE_EMROFFSETCLIPRGN (sizeof(U_EMROFFSETCLIPRGN))
/* Index 27, 54 */
/**
@@ -2284,6 +2320,8 @@ typedef struct {
U_EMRLINETO, //!< EMF manual 2.3.5.13
*PU_EMRMOVETOEX, //!< EMF manual 2.3.11.4
*PU_EMRLINETO; //!< EMF manual 2.3.5.13
+#define U_SIZE_EMRMOVETOEX (sizeof(U_EMRMOVETOEX))
+#define U_SIZE_EMRLINETO (sizeof(U_EMRLINETO ))
/* Index 28,33,52,59,60,61,65,66,68 */
/** EMF manual 2.3.2
@@ -2309,6 +2347,15 @@ typedef struct {
*PU_EMRFLATTENPATH, //!< EMF manual 2.3.10
*PU_EMRWIDENPATH, //!< EMF manual 2.3.10
*PU_EMRABORTPATH; //!< EMF manual 2.3.10
+#define U_SIZE_EMRSETMETARGN (sizeof(U_EMRSETMETARGN ))
+#define U_SIZE_EMRSAVEDC (sizeof(U_EMRSAVEDC ))
+#define U_SIZE_EMRREALIZEPALETTE (sizeof(U_EMRREALIZEPALETTE))
+#define U_SIZE_EMRBEGINPATH (sizeof(U_EMRBEGINPATH ))
+#define U_SIZE_EMRENDPATH (sizeof(U_EMRENDPATH ))
+#define U_SIZE_EMRCLOSEFIGURE (sizeof(U_EMRCLOSEFIGURE ))
+#define U_SIZE_EMRFLATTENPATH (sizeof(U_EMRFLATTENPATH ))
+#define U_SIZE_EMRWIDENPATH (sizeof(U_EMRWIDENPATH ))
+#define U_SIZE_EMRABORTPATH (sizeof(U_EMRABORTPATH ))
/* Index 29,30 */
/** EMF manual 2.3.2.1
@@ -2320,6 +2367,8 @@ typedef struct {
U_EMRINTERSECTCLIPRECT, //!< EMF manual 2.3.2.3
*PU_EMREXCLUDECLIPRECT, //!< EMF manual 2.3.2.1
*PU_EMRINTERSECTCLIPRECT; //!< EMF manual 2.3.2.3
+#define U_SIZE_EMREXCLUDECLIPRECT (sizeof(U_EMREXCLUDECLIPRECT ))
+#define U_SIZE_EMRINTERSECTCLIPRECT (sizeof(U_EMRINTERSECTCLIPRECT ))
/* Index 31,32 */
/** EMF manual 2.3.11.7
@@ -2334,6 +2383,8 @@ typedef struct {
U_EMRSCALEWINDOWEXTEX, //!< EMF manual 2.3.11.8
*PU_EMRSCALEVIEWPORTEXTEX, //!< EMF manual 2.3.11.7
*PU_EMRSCALEWINDOWEXTEX; //!< EMF manual 2.3.11.8
+#define U_SIZE_EMRSCALEVIEWPORTEXTEX (sizeof(U_EMRSCALEVIEWPORTEXTEX))
+#define U_SIZE_EMRSCALEWINDOWEXTEX (sizeof(U_EMRSCALEWINDOWEXTEX ))
/* Index 33 (see 28) */
@@ -2345,6 +2396,7 @@ typedef struct {
int32_t iRelative; //!< DC to restore. -1 is preceding
} U_EMRRESTOREDC,
*PU_EMRRESTOREDC; //!< EMF manual 2.3.11.6
+#define U_SIZE_EMRRESTOREDC (sizeof(U_EMRRESTOREDC))
/* Index 35 */
/** EMF manual 2.3.12.2
@@ -2354,6 +2406,7 @@ typedef struct {
U_XFORM xform; //!< Transform
} U_EMRSETWORLDTRANSFORM,
*PU_EMRSETWORLDTRANSFORM; //!< EMF manual 2.3.12.2
+#define U_SIZE_EMRSETWORLDTRANSFORM (sizeof(U_EMRSETWORLDTRANSFORM))
/* Index 36 */
/** EMF manual 2.3.12.1
@@ -2364,6 +2417,7 @@ typedef struct {
uint32_t iMode; //!< ModifyWorldTransformMode Enumeration
} U_EMRMODIFYWORLDTRANSFORM,
*PU_EMRMODIFYWORLDTRANSFORM; //!< EMF manual 2.3.12.1
+#define U_SIZE_EMRMODIFYWORLDTRANSFORM (sizeof(U_EMRMODIFYWORLDTRANSFORM))
/* Index 37,40 */
/** EMF manual 2.3.8.3
@@ -2375,6 +2429,8 @@ typedef struct {
U_EMRSELECTOBJECT, //!< EMF manual 2.3.8.5
*PU_EMRDELETEOBJECT, //!< EMF manual 2.3.8.3
*PU_EMRSELECTOBJECT; //!< EMF manual 2.3.8.5
+#define U_SIZE_EMRDELETEOBJECT (sizeof(U_EMRDELETEOBJECT))
+#define U_SIZE_EMRSELECTOBJECT (sizeof(U_EMRSELECTOBJECT))
/* Index 38 */
/** EMF manual 2.3.7.7
@@ -2385,6 +2441,7 @@ typedef struct {
U_LOGPEN lopn; //!< Pen properties
} U_EMRCREATEPEN,
*PU_EMRCREATEPEN; //!< EMF manual 2.3.7.7
+#define U_SIZE_EMRCREATEPEN (sizeof(U_EMRCREATEPEN))
/* Index 39 */
/** EMF manual 2.3.7.1
@@ -2395,6 +2452,7 @@ typedef struct {
U_LOGBRUSH lb; //!< Brush properties
} U_EMRCREATEBRUSHINDIRECT,
*PU_EMRCREATEBRUSHINDIRECT; //!< EMF manual 2.3.7.1
+#define U_SIZE_EMRCREATEBRUSHINDIRECT (sizeof(U_EMRCREATEBRUSHINDIRECT))
/* Index 40 see 37 */
@@ -2409,6 +2467,7 @@ typedef struct {
U_FLOAT eSweepAngle; //!< Sweep angle in degrees
} U_EMRANGLEARC,
*PU_EMRANGLEARC; //!< EMF manual 2.3.5.1
+#define U_SIZE_EMRANGLEARC (sizeof(U_EMRANGLEARC))
/* Index 42,43 */
/** EMF manual 2.3.5.5
@@ -2420,6 +2479,8 @@ typedef struct {
U_EMRRECTANGLE, //!< EMF manual 2.3.5.5
*PU_EMRELLIPSE, //!< EMF manual 2.3.5.5
*PU_EMRRECTANGLE; //!< EMF manual 2.3.5.34
+#define U_SIZE_EMRELLIPSE (sizeof(U_EMRELLIPSE ))
+#define U_SIZE_EMRRECTANGLE (sizeof(U_EMRRECTANGLE))
/* Index 44 */
/** EMF manual 2.3.5.35
@@ -2430,6 +2491,7 @@ typedef struct {
U_SIZEL szlCorner; //!< W & H in logical units of ellipse used to round corner
} U_EMRROUNDRECT,
*PU_EMRROUNDRECT; //!< EMF manual 2.3.5.35
+#define U_SIZE_EMRROUNDRECT (sizeof(U_EMRROUNDRECT))
/* Index 45, 46 ,47, 55 */
/** EMF manual 2.3.5.2
@@ -2447,6 +2509,10 @@ typedef struct {
*PU_EMRCHORD, //!< EMF manual 2.3.5.4
*PU_EMRPIE, //!< EMF manual 2.3.5.15
*PU_EMRARCTO; //!< EMF manual 2.3.5.3
+#define U_SIZE_EMRARC (sizeof(U_EMRARC ))
+#define U_SIZE_EMRCHORD (sizeof(U_EMRCHORD))
+#define U_SIZE_EMRPIE (sizeof(U_EMRPIE ))
+#define U_SIZE_EMRARCTO (sizeof(U_EMRARCTO))
/* Index 48 */
/** EMF manual 2.3.8.6
@@ -2456,6 +2522,7 @@ typedef struct {
uint32_t ihPal; //!< Index of a Palette object in the EMF object table
} U_EMRSELECTPALETTE,
*PU_EMRSELECTPALETTE; //!< EMF manual 2.3.8.6
+#define U_SIZE_EMRSELECTPALETTE (sizeof(U_EMRSELECTPALETTE))
/* Index 49 */
/** EMF manual 2.3.7.6
@@ -2466,6 +2533,7 @@ typedef struct {
U_LOGPALETTE lgpl; //!< Palette properties
} U_EMRCREATEPALETTE,
*PU_EMRCREATEPALETTE; //!< EMF manual 2.3.7.6
+#define U_SIZE_EMRCREATEPALETTE (sizeof(U_EMRCREATEPALETTE))
/* Index 50 */
/** EMF manual 2.3.8.8
@@ -2478,6 +2546,7 @@ typedef struct {
U_LOGPLTNTRY aPalEntries[1]; //!< Values to set with
} U_EMRSETPALETTEENTRIES,
*PU_EMRSETPALETTEENTRIES; //!< EMF manual 2.3.8.8
+#define U_SIZE_EMRSETPALETTEENTRIES (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_NUM_LOGPLTNTRY))
/* Index 51 */
/** EMF manual 2.3.8.4
@@ -2488,6 +2557,7 @@ typedef struct {
uint32_t cEntries; //!< Number to expand or truncate the Palette entry list to.
} U_EMRRESIZEPALETTE,
*PU_EMRRESIZEPALETTE; //!< EMF manual 2.3.8.4
+#define U_SIZE_EMRRESIZEPALETTE (sizeof(U_EMRRESIZEPALETTE))
/* Index 52 (see 28) */
@@ -2501,22 +2571,26 @@ typedef struct {
uint32_t iMode; //!< FloodFill Enumeration
} U_EMREXTFLOODFILL,
*PU_EMREXTFLOODFILL; //!< EMF manual 2.3.5.6
+#define U_SIZE_EMREXTFLOODFILL (sizeof(U_EMREXTFLOODFILL))
/* Index 54 (see 27) */
/* Index 55 (see 45) */
/* Index 56 */
-/** EMF manual 2.3.5.20
+/** EMF manual 2.3.5.20
+
+ followed by
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
*/
typedef struct {
U_EMR emr; //!< U_EMR
U_RECTL rclBounds; //!< Bounding rectangle in device units
U_NUM_POINTL cptl; //!< Number of U_POINTL objects
U_POINTL aptl[1]; //!< Array of U_POINTL objects
- uint8_t abTypes[1]; //!< Array of Point Enumeration
} U_EMRPOLYDRAW,
*PU_EMRPOLYDRAW; //!< EMF manual 2.3.5.20
+#define U_SIZE_EMRPOLYDRAW (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL))
/* Index 57 */
/** EMF manual 2.3.11.9
@@ -2526,6 +2600,7 @@ typedef struct {
uint32_t iArcDirection; //!< ArcDirection Enumeration
} U_EMRSETARCDIRECTION,
*PU_EMRSETARCDIRECTION; //!< EMF manual 2.3.11.9
+#define U_SIZE_EMRSETARCDIRECTION (sizeof(U_EMRSETARCDIRECTION))
/* Index 58 */
/** EMF manual 2.3.11.21
@@ -2538,6 +2613,7 @@ typedef struct {
uint32_t eMiterLimit; //!< Miter limit (max value of mitered length / line width)
} U_EMRSETMITERLIMIT,
*PU_EMRSETMITERLIMIT; //!< EMF manual 2.3.11.21
+#define U_SIZE_EMRSETMITERLIMIT (sizeof(U_EMRSETMITERLIMIT))
/* Index 59,60,61 (see 28) */
@@ -2553,6 +2629,9 @@ typedef struct {
*PU_EMRFILLPATH, //!< EMF manual 2.3.5.9
*PU_EMRSTROKEANDFILLPATH, //!< EMF manual 2.3.5.38
*PU_EMRSTROKEPATH; //!< EMF manual 2.3.5.39
+#define U_SIZE_EMRFILLPATH (sizeof(U_EMRFILLPATH ))
+#define U_SIZE_EMRSTROKEANDFILLPATH (sizeof(U_EMRSTROKEANDFILLPATH))
+#define U_SIZE_EMRSTROKEPATH (sizeof(U_EMRSTROKEPATH ))
/* Index 65,66 (see 28) */
/* Index 67 (see 17) */
@@ -2569,6 +2648,7 @@ typedef struct {
uint8_t Data[1]; //!< Comment (any binary data, interpretation is program specific)
} U_EMRCOMMENT,
*PU_EMRCOMMENT; //!< EMF manual 2.3.3.1, AKA GDICOMMENT
+#define U_SIZE_EMRCOMMENT (sizeof(U_EMR) + sizeof(U_CBDATA))
/* variant comment types */
/** EMF manual 2.3.3.2
@@ -2580,6 +2660,7 @@ typedef struct {
uint8_t Data[1]; //!< EMF Plus record
} U_EMRCOMMENT_EMFPLUS,
*PU_EMRCOMMENT_EMFPLUS; //!< EMF manual 2.3.3.2, EMF Plus comment
+#define U_SIZE_EMRCOMMENT_EMFPLUS (sizeof(U_EMR) + sizeof(U_CBDATA) + sizeof(uint32_t))
/** EMF manual 2.3.3.3
*/
@@ -2591,6 +2672,7 @@ typedef struct {
uint8_t Data[1]; //!< EMF Spool records
} U_EMRCOMMENT_SPOOL,
*PU_EMRCOMMENT_SPOOL; //!< EMF manual 2.3.3.3, EMF Spool comment
+#define U_SIZE_EMRCOMMENT_SPOOL (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t))
/** EMF manual 2.3.3.4
*/
@@ -2602,9 +2684,11 @@ typedef struct {
uint8_t Data[1]; //!< Public comment data
} U_EMRCOMMENT_PUBLIC,
*PU_EMRCOMMENT_PUBLIC; //!< EMF manual 2.3.3.4, EMF Public comment
+#define U_SIZE_EMRCOMMENT_PUBLIC (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t))
/* Index 71 */
-/** EMF manual 2.3.5.10
+/** EMF manual 2.3.5.10
+ followed by a variable number of U_RECTLs
*/
typedef struct {
U_EMR emr; //!< U_EMR
@@ -2614,6 +2698,7 @@ typedef struct {
U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
} U_EMRFILLRGN,
*PU_EMRFILLRGN; //!< EMF manual 2.3.5.10
+#define U_SIZE_EMRFILLRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t))
/* Index 72 */
/** EMF manual 2.3.5.11
@@ -2627,6 +2712,7 @@ typedef struct {
U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
} U_EMRFRAMERGN,
*PU_EMRFRAMERGN; //!< EMF manual 2.3.5.11
+#define U_SIZE_EMRFRAMERGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t) + sizeof(U_SIZEL))
/* Index 73,74 */
/** EMF manual 2.3.11.3
@@ -2640,6 +2726,8 @@ typedef struct {
U_EMRPAINTRGN, //!< EMF manual 2.3.5.14
*PU_EMRINVERTRGN, //!< EMF manual 2.3.11.3
*PU_EMRPAINTRGN; //!< EMF manual 2.3.5.14
+#define U_SIZE_EMRINVERTRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA))
+#define U_SIZE_EMRPAINTRGN U_SIZE_EMRINVERTRGN
/* Index 75 */
/** EMF manual 2.3.2.2
@@ -2651,6 +2739,7 @@ typedef struct {
U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
} U_EMREXTSELECTCLIPRGN,
*PU_EMREXTSELECTCLIPRGN; //!< EMF manual 2.3.2.2
+#define U_SIZE_EMREXTSELECTCLIPRGN (sizeof(U_EMR) + sizeof(U_CBRGNDATA) + sizeof(uint32_t))
/* Index 76 */
/** EMF manual 2.3.1.2
@@ -2672,6 +2761,7 @@ typedef struct {
//!< Record may include optional bitmapbuffer
} U_EMRBITBLT,
*PU_EMRBITBLT; //!< EMF manual 2.3.1.2
+#define U_SIZE_EMRBITBLT (sizeof(U_EMRBITBLT))
/* Index 77 */
/** EMF manual 2.3.1.6
@@ -2694,6 +2784,7 @@ typedef struct {
//!< Record may include optional bitmapbuffer
} U_EMRSTRETCHBLT,
*PU_EMRSTRETCHBLT; //!< EMF manual 2.3.1.6
+#define U_SIZE_EMRSTRETCHBLT (sizeof(U_EMRSTRETCHBLT))
/* Index 78 */
/** EMF manual 2.3.1.3
@@ -2721,6 +2812,7 @@ typedef struct {
//!< Record may include optional Source and mask bitmapbuffers
} U_EMRMASKBLT,
*PU_EMRMASKBLT; //!< EMF manual 2.3.1.3
+#define U_SIZE_EMRMASKBLT (sizeof(U_EMRMASKBLT))
/* Index 79 */
/** EMF manual 2.3.1.4
@@ -2747,6 +2839,7 @@ typedef struct {
//!< Record may include optional Source and mask bitmapbuffers
} U_EMRPLGBLT,
*PU_EMRPLGBLT; //!< EMF manual 2.3.1.4
+#define U_SIZE_EMRPLGBLT (sizeof(U_EMRPLGBLT))
/* Index 80 */
/** EMF manual 2.3.1.5
@@ -2767,6 +2860,7 @@ typedef struct {
//!< Record may includes optional bitmapbuffer
} U_EMRSETDIBITSTODEVICE,
*PU_EMRSETDIBITSTODEVICE; //!< EMF manual 2.3.1.5
+#define U_SIZE_EMRSETDIBITSTODEVICE (sizeof(U_EMRSETDIBITSTODEVICE))
/* Index 81 */
/** EMF manual 2.3.1.7
@@ -2787,6 +2881,7 @@ typedef struct {
//!< Record may includes optional bitmapbuffer
} U_EMRSTRETCHDIBITS,
*PU_EMRSTRETCHDIBITS; //!< EMF manual 2.3.1.7
+#define U_SIZE_EMRSTRETCHDIBITS (sizeof(U_EMRSTRETCHDIBITS))
/* Index 82 */
/** EMF manual 2.3.7.8
@@ -2797,6 +2892,8 @@ typedef struct {
U_LOGFONT_PANOSE elfw; //!< Font parameters, either U_LOGFONT or U_LOGFONT_PANOSE, the latter is bigger so use that type here
} U_EMREXTCREATEFONTINDIRECTW,
*PU_EMREXTCREATEFONTINDIRECTW; //!< EMF manual 2.3.7.8
+#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT_PANOSE))
+#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT))
/* Index 83,84 */
/** EMF manual 2.3.5.7
@@ -2820,6 +2917,8 @@ typedef struct {
U_EMREXTTEXTOUTW, //!< EMF manual 2.3.5.8
*PU_EMREXTTEXTOUTA, //!< EMF manual 2.3.5.7
*PU_EMREXTTEXTOUTW; //!< EMF manual 2.3.5.8
+#define U_SIZE_EMREXTTEXTOUTA (sizeof(U_EMREXTTEXTOUTA))
+#define U_SIZE_EMREXTTEXTOUTW (sizeof(U_EMREXTTEXTOUTW))
/* Index 85,86,87,88,89 */
/** EMF manual 2.3.5.17
@@ -2839,9 +2938,16 @@ typedef struct {
*PU_EMRPOLYLINE16, //!< EMF manual 2.3.5.25
*PU_EMRPOLYBEZIERTO16, //!< EMF manual 2.3.5.19
*PU_EMRPOLYLINETO16; //!< EMF manual 2.3.5.27
-
+#define U_SIZE_EMRPOLYBEZIER16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16))
+#define U_SIZE_EMRPOLYGON16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYLINE16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYBEZIERTO16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYLINETO16 U_SIZE_EMRPOLYBEZIER16
/* Index 90,91 */
-/** EMF manual 2.3.5.31
+/** EMF manual 2.3.5.31
+
+ followed by
+ U_POINT16 apts[1]; //!< array of point16
*/
typedef struct {
U_EMR emr; //!< U_EMR
@@ -2849,24 +2955,28 @@ typedef struct {
U_NUM_POLYCOUNTS nPolys; //!< Number of elements in aPolyCounts
U_NUM_POINT16 cpts; //!< Total number of points (over all poly)
U_POLYCOUNTS aPolyCounts[1]; //!< Number of points in each poly (sequential)
-// This will appear somewhere but is not really part of the core structure.
-// U_POINT16 apts[1]; //!< array of point16
} U_EMRPOLYPOLYLINE16,
U_EMRPOLYPOLYGON16, //!< EMF manual 2.3.5.29
*PU_EMRPOLYPOLYLINE16, //!< EMF manual 2.3.5.31
*PU_EMRPOLYPOLYGON16; //!< EMF manual 2.3.5.29
+#define U_SIZE_EMRPOLYPOLYLINE16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_NUM_POINT16))
+#define U_SIZE_EMRPOLYPOLYGON16 U_SIZE_EMRPOLYPOLYLINE16
/* Index 92 */
-/** EMF manual 2.3.5.21
+/** EMF manual 2.3.5.21
+
+ followed by
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
+
*/
typedef struct {
U_EMR emr; //!< U_EMR
U_RECTL rclBounds; //!< Bounding rectangle in device units
U_NUM_POINT16 cpts; //!< Total number of points (over all poly)
U_POINT16 apts[1]; //!< array of points
- uint8_t abTypes[1]; //!< Array of Point Enumeration
} U_EMRPOLYDRAW16,
*PU_EMRPOLYDRAW16; //!< EMF manual 2.3.5.21
+#define U_SIZE_EMRPOLYDRAW16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16))
/* Index 93 */
/** EMF manual 2.3.7.5
@@ -2882,6 +2992,7 @@ typedef struct {
//!< Record may include optional DIB bitmapbuffer
} U_EMRCREATEMONOBRUSH,
*PU_EMRCREATEMONOBRUSH; //!< EMF manual 2.3.7.5
+#define U_SIZE_EMRCREATEMONOBRUSH (sizeof(U_EMRCREATEMONOBRUSH))
/* Index 94 */
/** EMF manual 2.3.7.4
@@ -2897,6 +3008,7 @@ typedef struct {
//!< Record may include optional DIB bitmapbuffer
} U_EMRCREATEDIBPATTERNBRUSHPT,
*PU_EMRCREATEDIBPATTERNBRUSHPT; //!< EMF manual 2.3.7.4
+#define U_SIZE_EMRCREATEDIBPATTERNBRUSHPT (sizeof(U_EMRCREATEDIBPATTERNBRUSHPT))
/* Index 95 */
/** EMF manual 2.3.7.9
@@ -2912,6 +3024,7 @@ typedef struct {
//!< Record may include optional DIB bitmap
} U_EMREXTCREATEPEN,
*PU_EMREXTCREATEPEN; //!< EMF manual 2.3.7.9
+#define U_SIZE_EMREXTCREATEPEN (sizeof(U_EMREXTCREATEPEN))
/* Index 96.97 */
/** EMF manual 2.3.5.32
@@ -2928,6 +3041,8 @@ typedef struct {
U_EMRPOLYTEXTOUTW, //!< EMF manual 2.3.5.33
*PU_EMRPOLYTEXTOUTA, //!< EMF manual 2.3.5.32
*PU_EMRPOLYTEXTOUTW; //!< EMF manual 2.3.5.33
+#define U_SIZE_EMRPOLYTEXTOUTA (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t) + 2*sizeof(U_FLOAT) + sizeof(U_NUM_EMRTEXT))
+#define U_SIZE_EMRPOLYTEXTOUTW U_SIZE_EMRPOLYTEXTOUTA
/* Index 98 (see 17) */
@@ -2940,6 +3055,7 @@ typedef struct {
U_LOGCOLORSPACEA lcs; //!< ColorSpace parameters
} U_EMRCREATECOLORSPACE,
*PU_EMRCREATECOLORSPACE; //!< EMF manual 2.3.7.2
+#define U_SIZE_EMRCREATECOLORSPACE (sizeof(U_EMRCREATECOLORSPACE))
/* Index 100,101 */
/** EMF manual 2.3.8.2
@@ -2951,6 +3067,8 @@ typedef struct {
U_EMRSETCOLORSPACE, //!< EMF manual 2.3.8.7
*PU_EMRDELETECOLORSPACE, //!< EMF manual 2.3.8.2
*PU_EMRSETCOLORSPACE; //!< EMF manual 2.3.8.7
+#define U_SIZE_EMRDELETECOLORSPACE (sizeof(U_EMRDELETECOLORSPACE))
+#define U_SIZE_EMRSETCOLORSPACE (sizeof(U_EMRSETCOLORSPACE ))
/* Index 102 */
/** EMF manual 2.3.9.2
@@ -2961,6 +3079,7 @@ typedef struct {
U_DATA Data[1]; //!< OpenGL data
} U_EMRGLSRECORD,
*PU_EMRGLSRECORD; //!< EMF manual 2.3.9.2
+#define U_SIZE_EMRGLSRECORD (sizeof(U_EMRGLSRECORD))
/* Index 103 */
/** EMF manual 2.3.9.1
@@ -2972,6 +3091,7 @@ typedef struct {
U_DATA Data[1]; //!< OpenGL data
} U_EMRGLSBOUNDEDRECORD,
*PU_EMRGLSBOUNDEDRECORD; //!< EMF manual 2.3.9.1
+#define U_SIZE_EMRGLSBOUNDEDRECORD (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBDATA))
/* Index 104 */
/** EMF manual 2.3.11.5
@@ -2981,6 +3101,7 @@ typedef struct {
U_PIXELFORMATDESCRIPTOR pfd; //!< PixelFormatDescriptor
} U_EMRPIXELFORMAT,
*PU_EMRPIXELFORMAT; //!< EMF manual 2.3.11.5
+#define U_SIZE_EMRPIXELFORMAT (sizeof(U_EMRPIXELFORMAT))
/* Index 105 */
/** EMF manual 2.3.6.1
@@ -2991,6 +3112,7 @@ typedef struct {
U_DATA Data[1]; //!< Data to send
} U_EMRDRAWESCAPE,
*PU_EMRDRAWESCAPE; //!< EMF manual 2.3.6.1
+#define U_SIZE_EMRDRAWESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA))
/* Index 106 */
/** EMF manual 2.3.6.2
@@ -3001,6 +3123,7 @@ typedef struct {
U_DATA Data[1]; //!< Data to send
} U_EMREXTESCAPE,
*PU_EMREXTESCAPE; //!< EMF manual 2.3.6.2
+#define U_SIZE_EMREXTESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA))
/* Index 107 (not implemented ) */
@@ -3020,22 +3143,26 @@ typedef struct {
//!< uint32_t TextString; text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit)
} U_EMRSMALLTEXTOUT,
*PU_EMRSMALLTEXTOUT; //!< EMF manual 2.3.5.37
+#define U_SIZE_EMRSMALLTEXTOUT (sizeof(U_EMRSMALLTEXTOUT))
/* Index 109 (not implemented )
EMF manual 2.3.11.2
*/
/* Index 110 */
-/** EMF manual 2.3.6.3
+/** EMF manual 2.3.6.3
+
+ followed by
+ uint8_t Data[1]; //!< Data for printer driver
*/
typedef struct {
U_EMR emr; //!< U_EMR
U_CBDATA cbDriver; //!< Number of bytes in driver name (note, BYTES, not CHARACTERS)
U_CBDATA cbData; //!< Number of bytes in data
uint16_t Driver[1]; //!< Driver name in uint16_t characters, null terminated
- uint8_t Data[1]; //!< Data for printer driver
} U_EMRNAMEDESCAPE,
*PU_EMRNAMEDESCAPE; //!< EMF manual 2.3.6.3
+#define U_SIZE_EMRNAMEDESCAPE (sizeof(U_EMRNAMEDESCAPE))
/* Index 111-113 (not implemented )
EMF manual 2.3.8.1
@@ -3064,6 +3191,7 @@ typedef struct {
//!< Record may include optional DIB bitmap
} U_EMRALPHABLEND,
*PU_EMRALPHABLEND; //!< EMF manual 2.3.1.1
+#define U_SIZE_EMRALPHABLEND (sizeof(U_EMRALPHABLEND))
/* Index 115 (see 17) */
@@ -3088,11 +3216,16 @@ typedef struct {
//!< Record may includes optional bitmapbuffer
} U_EMRTRANSPARENTBLT,
*PU_EMRTRANSPARENTBLT; //!< EMF manual 2.3.1.8
+#define U_SIZE_EMRTRANSPARENTBLT (sizeof(U_EMRTRANSPARENTBLT))
/* Index 117 (not a defined U_EMR record type ) */
/* Index 118 */
-/** EMF manual 2.3.5.12
+/** EMF manual 2.3.5.12
+
+ followed by
+ U_TRIVERTEX TriVert[1]; Array of TriVertex objects
+ uint32_t GradObj[1]; Array of gradient objects (each has 2 or 3 indices into TriVert array)
*/
typedef struct {
U_EMR emr; //!< U_EMR
@@ -3100,11 +3233,9 @@ typedef struct {
U_NUM_TRIVERTEX nTriVert; //!< Number of TriVertex objects
U_NUM_GRADOBJ nGradObj; //!< Number of gradient triangle/rectangle objects
uint32_t ulMode; //!< Gradientfill Enumeration (determines Triangle/Rectangle)
-//parts that are required but which are not included in the core structure
-// U_TRIVERTEX TriVert[1]; Array of TriVertex objects
-// uint32_t GradObj[1]; Array of gradient objects (each has 2 or 3 indices into TriVert array)
} U_EMRGRADIENTFILL,
*PU_EMRGRADIENTFILL; //!< EMF manual 2.3.5.12
+#define U_SIZE_EMRGRADIENTFILL (sizeof(U_EMRGRADIENTFILL))
/* Index 119,120 (not implemented )
EMF manual 2.3.11.18
@@ -3123,6 +3254,7 @@ typedef struct {
uint8_t Data[1]; //!< Data of size cbName+cbData: Name in UTF16 then color profile data
} U_EMRCOLORMATCHTOTARGETW,
*PU_EMRCOLORMATCHTOTARGETW; //!< EMF manual 2.3.11.1
+#define U_SIZE_EMRCOLORMATCHTOTARGETW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_CBNAME) + sizeof(U_CBDATA))
/* Index 122 */
/** EMF manual 2.3.7.3
@@ -3136,6 +3268,10 @@ typedef struct {
uint8_t Data[1]; //!< (Optional, dwFlags & 1) color profile data
} U_EMRCREATECOLORSPACEW,
*PU_EMRCREATECOLORSPACEW; //!< EMF manual 2.3.7.3
+#define U_SIZE_EMRCREATECOLORSPACEW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(U_CBDATA))
+
+// records which are not documented, so we have no idea what to do with them
+#define U_SIZE_EMRUNDEFINED 2048
// ************************************************************************************************
// Utility function structures
@@ -3207,7 +3343,7 @@ int get_real_color_count(const char *Bmih);
int get_real_color_icount(int Colors, int BitCount, int Width, int Height);
int RGBA_to_DIB(char **px, uint32_t *cbPx, PU_RGBQUAD *ct, int *numCt,
const char *rgba_px, int w, int h, int stride, uint32_t colortype, int use_ct, int invert);
-int get_DIB_params( void *pEmr, uint32_t offBitsSrc, uint32_t offBmiSrc,
+int get_DIB_params( const char *record, uint32_t offBitsSrc, uint32_t offBmiSrc,
const char **px, const U_RGBQUAD **ct, uint32_t *numCt,
uint32_t *width, uint32_t *height, uint32_t *colortype, uint32_t *invert );
int DIB_to_RGBA(const char *px, const U_RGBQUAD *ct, int numCt,
@@ -3237,6 +3373,7 @@ int emf_htable_free(EMFHANDLES **eht);
#define htable_free emf_htable_free
U_RECTL rectl_set(U_POINTL ul, U_POINTL lr);
+void rectli_set(PU_RECTL array, int index, U_POINTL ul, U_POINTL lr);
U_SIZEL sizel_set(int32_t x, int32_t y);
U_POINTL point32_set(int32_t x, int32_t y);
#define point_set point32_set
@@ -3463,6 +3600,7 @@ char *U_EMRSMALLTEXTOUT_set(const U_POINTL Dest, const U_NUM_STR cChars, const u
// U_EMRSETICMPROFILEA_set 112 Not implemented
// U_EMRSETICMPROFILEW_set 113 Not implemented
+
char *U_EMRALPHABLEND_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest,
const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc,
const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc,
diff --git a/src/libuemf/uemf_endian.c b/src/libuemf/uemf_endian.c
index 2d19361e1..f746553f1 100644
--- a/src/libuemf/uemf_endian.c
+++ b/src/libuemf/uemf_endian.c
@@ -19,11 +19,11 @@
/*
File: uemf_endian.c
-Version: 0.0.16
-Date: 27-MAR-2014
+Version: 0.0.21
+Date: 23-APR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
@@ -266,18 +266,91 @@ void bitmapinfoheader_swap(
\param Bmi Pointer to a U_BITMAPINFO object
*/
void bitmapinfo_swap(
- PU_BITMAPINFO Bmi
+ const char *Bmi
){
- bitmapinfoheader_swap(&(Bmi->bmiHeader)); // bmIHeader
+ PU_BITMAPINFO pBmi = (PU_BITMAPINFO)Bmi;
+ bitmapinfoheader_swap(&(pBmi->bmiHeader)); // bmIHeader
// ordered bytes: bmiColors
}
/**
+ \brief Swap the ordered bytes in a DIB and verify that the sizes are OK
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param iUsage DIBcolors Enumeration
+ \param offBmi offset from the start of the record to the start of the bitmapinfo structure
+ \param cbBmi declared space for the bitmapinfo structure in the record
+ \param offBits offset from the start of the record to the start of the bitmap
+ \param cbBits declared space for the bitmap in the record (amount used may be less than this)
+ \param blimit one byte past the end of the record.
+ \param torev 1 for native to reversed, 0 for reversed to native
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+*/
+int DIB_swap(
+ const char *record,
+ uint32_t iUsage,
+ uint32_t offBmi,
+ uint32_t cbBmi,
+ uint32_t offBits,
+ uint32_t cbBits,
+ const char *blimit,
+ int torev
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!cbBmi)return(1); // No DIB in a record where it is optional
+ if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0);
+ if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0);
+ if(iUsage == U_DIB_RGB_COLORS){
+ uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ if(torev){
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+ }
+ bitmapinfo_swap(record + offBmi); // byte ordered fields in bitmapinfo
+ if(!torev){
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+ }
+
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the EMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0);
+ }
+ }
+ else {
+ bitmapinfo_swap(record + offBmi);
+ }
+ return(1);
+}
+
+/**
\brief Convert a pointer to a U_EXTLOGPEN object.
- \param elp PU_EXTLOGPEN object
+ \param elp PU_EXTLOGPEN object
+ \param blimit one byte past the end of the record
*/
-void extlogpen_swap(
+int extlogpen_swap(
PU_EXTLOGPEN elp,
+ const char *blimit,
int torev
){
int count=0;
@@ -290,7 +363,9 @@ void extlogpen_swap(
if(!torev){
count = elp->elpNumEntries;
}
+ if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0);
U_swap4(&(elp->elpStyleEntry),count); // elpStyleEntry[]
+ return(1);
}
/**
@@ -330,15 +405,27 @@ void rgndataheader_swap(
}
/**
+ \return 1 on success, 0 on failure
\brief Convert a pointer to a U_RGNDATA object.
- \param rgd pointer to a U_RGNDATA object.
+ \param rd pointer to a U_RGNDATA object.
+ \param cbRgnData size of the U_RGNDATA object.
*/
-void rgndata_swap(
- PU_RGNDATA rd
+int rgndata_swap(
+ PU_RGNDATA rd,
+ int cbRgnData,
+ int torev
){
- int count = rd->rdh.nCount;
+ int count = 0;
+ if(torev){
+ count = rd->rdh.nCount;
+ }
rgndataheader_swap(&(rd->rdh));
+ if(!torev){
+ count = rd->rdh.nCount;
+ }
+ if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0);
U_swap4(rd->Buffer,4*count);
+ return(1);
}
/**
@@ -368,12 +455,14 @@ void pixelformatdescriptor_swap(
\brief Convert a Pointer to a U_EMRTEXT record
\param pemt Pointer to a U_EMRTEXT record
\param record Pointer to the start of the record which contains this U_EMRTEXT
+ \param blimit one byte past the end of the record.
\param torev 1 for native to reversed, 0 for reversed to native
*/
-void emrtext_swap(
- PU_EMRTEXT pemt,
- char *record,
- int torev
+int emrtext_swap(
+ PU_EMRTEXT pemt,
+ char *record,
+ const char *blimit,
+ int torev
){
int off;
uint32_t count=0;
@@ -391,6 +480,7 @@ void emrtext_swap(
}
off = sizeof(U_EMRTEXT);
if(!(fOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0);
rectl_swap((PU_RECTL)((char *)pemt + off),1); // optional rectangle
off+=sizeof(U_RECTL);
}
@@ -398,11 +488,14 @@ void emrtext_swap(
offDx = *(uint32_t *)((char *)pemt +off);
}
// ordered bytes OR UTF16-LE: the string at offString
+ if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0);
U_swap4(((char *)pemt+off),1); // offDx
if(!torev){
offDx = *(uint32_t *)((char *)pemt +off);
}
- U_swap4((record+offDx),count); // Dx[], offset with respect to the Record, NOT the object
+ if(IS_MEM_UNSAFE(record, count*4, blimit))return(0);
+ U_swap4((record + offDx),count); // Dx[], offset with respect to the Record, NOT the object
+ return(1);
}
@@ -424,182 +517,236 @@ by end user code and to further that end prototypes are NOT provided and they ar
// all core*_swap call this, U_EMRSETMARGN_swap and some others all it directly
// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype
-void core5_swap(char *record, int torev){
+int core5_swap(char *record, int torev){
UNUSED_PARAMETER(torev);
- PU_ENHMETARECORD pEMR = (PU_ENHMETARECORD)(record);
- U_swap4(pEMR,2); // iType nSize
+ if(!record)return(0);
+ PU_EMR pEmr = (PU_EMR)(record);
+ U_swap4(pEmr,2); // iType nSize
+ return(1);
}
// Functions with the same form starting with U_EMRPOLYBEZIER_swap
-void core1_swap(char *record, int torev){
+int core1_swap(char *record, int torev){
int count=0;
+ const char *blimit = NULL;
PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record);
if(torev){
count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
}
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1 ); // rclBounds
U_swap4(&(pEmr->cptl),1); // cptl
if(!torev){
count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0);
pointl_swap((pEmr->aptl),count); // aptl[]
+ return(1);
}
// Functions with the same form starting with U_EMRPOLYPOLYLINE_swap
-void core2_swap(char *record, int torev){
+int core2_swap(char *record, int torev){
int count=0;
int nPolys=0;
+ const char *blimit = NULL;
PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record);
if(torev){
count = pEmr->cptl;
nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
}
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->nPolys),2); // nPolys cptl
if(!torev){
count = pEmr->cptl;
nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0);
U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
- pointl_swap((PU_POINT)(record + sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys), count); // paptl[]
+ record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0);
+ pointl_swap((PU_POINT)(record), count); // paptl[]
+ return(1);
}
// Functions with the same form starting with U_EMRSETMAPMODE_swap
-void core3_swap(char *record, int torev){
+int core3_swap(char *record, int torev){
PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(record);
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
}
// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_swap, also U_EMRFILLPATH_swap,
-void core4_swap(char *record, int torev){
+int core4_swap(char *record, int torev){
PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( record);
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBox),1); // rclBox
+ return(1);
}
// Functions with the same form starting with U_EMRPOLYBEZIER16_swap
-void core6_swap(char *record, int torev){
+int core6_swap(char *record, int torev){
int count=0;
+ const char *blimit = NULL;
PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record);
if(torev){
count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
}
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cpts),1); // cpts
if(!torev){
count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0);
point16_swap((pEmr->apts),count); // apts[]
+ return(1);
}
// Records with the same form starting with U_EMRSETWINDOWEXTEX_swap, that is, all with two uint32_t values after the emr
-void core7_swap(char *record, int torev){
+int core7_swap(char *record, int torev){
PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (record);
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->pair),2);
+ return(1);
}
// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
-void core8_swap(char *record, int torev){
+int core8_swap(char *record, int torev){
+ const char *blimit = NULL;
PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record);
- emrtext_swap(&(pEmr->emrtext),record,torev);
- core5_swap(record, torev);
+ if(torev){
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->iGraphicsMode),1); // iGraphicsMode
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->exScale),2); // exScale eyScale
+ if(!torev){
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!emrtext_swap(&(pEmr->emrtext),record,blimit,torev))return(0);
+ return(1);
}
// Functions that take a rect and a pair of points, starting with U_EMRARC_swap
-void core9_swap(char *record, int torev){
+int core9_swap(char *record, int torev){
PU_EMRARC pEmr = (PU_EMRARC) (record);
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBox),1); // rclBox
U_swap4(&(pEmr->ptlStart),4); // ptlStart ptlEnd
+ return(1);
}
// Functions with the same form starting with U_EMRPOLYPOLYLINE16_swap
-void core10_swap(char *record, int torev){
+int core10_swap(char *record, int torev){
int count=0;
int nPolys=0;
+ const char *blimit = NULL;
PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record);
if(torev){
count = pEmr->cpts;
nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
}
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->nPolys),2); // nPolys cpts
if(!torev){
count = pEmr->cpts;
nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0);
U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
- point16_swap((PU_POINT16)(record + sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys), count); // apts[]
+ record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0);
+ point16_swap((PU_POINT16)(record), count); // apts[]
+ return(1);
}
// Functions with the same form starting with U_EMRINVERTRGN_swap and U_EMRPAINTRGN_swap,
-void core11_swap(char *record, int torev){
- int roff=0;
- int nextroff=0;
- int limit=0;
- PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (record);
- roff = 0;
+int core11_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record);
if(torev){
- limit = pEmr->emr.nSize;
- nextroff = 0;
- }
- core5_swap(record, torev);
- if(!torev){
- limit = pEmr->emr.nSize;
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cbRgnData),1); // cbRgnData
if(!torev){
- limit = pEmr->emr.nSize;
- }
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + 28 < limit){ // up to the end of the record
- if(torev){
- nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff = nextroff;
- }
- else {
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
}
// common code for U_EMRCREATEMONOBRUSH_swap and U_EMRCREATEDIBPATTERNBRUSHPT_swap,
-void core12_swap(char *record, int torev){
+int core12_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMI offBmi = 0;
+ U_CBBMI cbBmi = 0;
+ U_OFFBITS offBits = 0;
+ U_CBBITS cbBits = 0;
+ uint32_t iUsage = 0;
PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record);
- if(torev && pEmr->cbBmi){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi)); // Bmi
- }
- core5_swap(record, torev);
+ if(torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ iUsage = pEmr->iUsage;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->ihBrush),6); // ihBrush iUsage offBmi cbBmi offBits cbBits
- // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
- if(!torev && pEmr->cbBmi){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi)); // Bmi
+ if(!torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ iUsage = pEmr->iUsage;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
}
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
}
// common code for U_EMRALPHABLEND_swap and U_EMRTRANSPARENTBLT_swap,
-void core13_swap(char *record, int torev){
+int core13_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
- core5_swap(record, torev);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),2); // Dest cDest
pointl_swap(&(pEmr->Dest),2); // Dest cDest
@@ -608,15 +755,25 @@ void core13_swap(char *record, int torev){
xform_swap( &(pEmr->xformSrc)); // xformSrc
// ordered bytes: crBkColorSrc
U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
- // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
}
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
}
/* **********************************************************************************************
-These are the core EMR functions, each creates a particular type of record.
-All return these records via a char* pointer, which is NULL if the call failed.
+These are the core EMR_swap functions, each converts a particular type of record.
+All operate in place on the chunk of memory holding that record.
+Some of these have offsets or counts which, if corrupt or evil would result in access outside
+ the record. These cases return a status value of 0 if that happens, 1 on success. Other
+ records which do not have these issues do not return a status value.
They are listed in order by the corresponding U_EMR_* index number.
*********************************************************************************************** */
@@ -626,37 +783,31 @@ They are listed in order by the corresponding U_EMR_* index number.
\param record pointer to a buffer holding the EMR record
\param torev 1 for native to reversed, 0 for reversed to native
*/
-void U_EMRNOTIMPLEMENTED_swap(char *record, int torev){
- core5_swap(record, torev);
- printf("WARNING: could not convert data in record type that has not been implemented!\n");
+int U_EMRNOTIMPLEMENTED_swap(char *record, int torev){
+ fprintf(stderr,"EMF WARNING: could not swap data bytes on record because that type has not been implemented!\n");
+ return(core5_swap(record, torev));
}
// U_EMRHEADER 1
-void U_EMRHEADER_swap(char *record, int torev){
+int U_EMRHEADER_swap(char *record, int torev){
int nDesc,offDesc,nSize,cbPix,offPix;
+ nDesc = offDesc = nSize = cbPix = offPix = 0;
PU_EMRHEADER pEmr = (PU_EMRHEADER)(record);
if(torev){
nSize = pEmr->emr.nSize;
- core5_swap(record, torev);
- }
- else {
- core5_swap(record, torev);
- nSize = pEmr->emr.nSize;
+ nDesc = pEmr->nDescription;
+ offDesc = pEmr->offDescription;
}
-
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),2); // rclBounds rclFrame
U_swap4(&(pEmr->dSignature), 4); // dSignature nVersion nBytes nRecords
U_swap2(&(pEmr->nHandles), 2); // nHandlessReserved
- if(torev){
- nDesc = pEmr->nDescription;
- offDesc = pEmr->offDescription;
- U_swap4(&(pEmr->nDescription), 3); // nDescription offDescription nPalEntries
- }
- else {
- U_swap4(&(pEmr->nDescription), 3); // nDescription offDescription nPalEntries
- nDesc = pEmr->nDescription;
- offDesc = pEmr->offDescription;
- }
+ U_swap4(&(pEmr->nDescription), 3); // nDescription offDescription nPalEntries
+ if(!torev){
+ nSize = pEmr->emr.nSize;
+ nDesc = pEmr->nDescription;
+ offDesc = pEmr->offDescription;
+ }
// UTF16-LE Description
sizel_swap(&(pEmr->szlDevice), 2); // szlDevice szlMillimeters
if((nDesc && (offDesc >= 100)) ||
@@ -665,16 +816,14 @@ void U_EMRHEADER_swap(char *record, int torev){
if(torev){
cbPix = pEmr->cbPixelFormat;
offPix = pEmr->offPixelFormat;
- if(cbPix)pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
- U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat
}
- else {
- U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat
+ U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat
+ U_swap4(&(pEmr->bOpenGL), 1); // bOpenGL
+ if(!torev){
cbPix = pEmr->cbPixelFormat;
offPix = pEmr->offPixelFormat;
- if(cbPix)pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
}
- U_swap4(&(pEmr->bOpenGL), 1); // bOpenGL
+ if(cbPix)pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
if((nDesc && (offDesc >= 108)) ||
(cbPix && (offPix >=108)) ||
(!offDesc && !cbPix && nSize >= 108)
@@ -682,543 +831,557 @@ void U_EMRHEADER_swap(char *record, int torev){
sizel_swap(&(pEmr->szlMicrometers), 1); // szlMicrometers
}
}
+ return(1);
}
// U_EMRPOLYBEZIER 2
-void U_EMRPOLYBEZIER_swap(char *record, int torev){
- core1_swap(record, torev);
+int U_EMRPOLYBEZIER_swap(char *record, int torev){
+ return(core1_swap(record, torev));
}
// U_EMRPOLYGON 3
-void U_EMRPOLYGON_swap(char *record, int torev){
- core1_swap(record, torev);
+int U_EMRPOLYGON_swap(char *record, int torev){
+ return(core1_swap(record, torev));
}
// U_EMRPOLYLINE 4
-void U_EMRPOLYLINE_swap(char *record, int torev){
- core1_swap(record, torev);
+int U_EMRPOLYLINE_swap(char *record, int torev){
+ return(core1_swap(record, torev));
}
// U_EMRPOLYBEZIERTO 5
-void U_EMRPOLYBEZIERTO_swap(char *record, int torev){
- core1_swap(record, torev);
+int U_EMRPOLYBEZIERTO_swap(char *record, int torev){
+ return(core1_swap(record, torev));
}
// U_EMRPOLYLINETO 6
-void U_EMRPOLYLINETO_swap(char *record, int torev){
- core1_swap(record, torev);
+int U_EMRPOLYLINETO_swap(char *record, int torev){
+ return(core1_swap(record, torev));
}
// U_EMRPOLYPOLYLINE 7
-void U_EMRPOLYPOLYLINE_swap(char *record, int torev){
- core2_swap(record, torev);
+int U_EMRPOLYPOLYLINE_swap(char *record, int torev){
+ return(core2_swap(record, torev));
}
// U_EMRPOLYPOLYGON 8
-void U_EMRPOLYPOLYGON_swap(char *record, int torev){
- core2_swap(record, torev);
+int U_EMRPOLYPOLYGON_swap(char *record, int torev){
+ return(core2_swap(record, torev));
}
// U_EMRSETWINDOWEXTEX 9
-void U_EMRSETWINDOWEXTEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRSETWINDOWEXTEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRSETWINDOWORGEX 10
-void U_EMRSETWINDOWORGEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRSETWINDOWORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRSETVIEWPORTEXTEX 11
-void U_EMRSETVIEWPORTEXTEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRSETVIEWPORTEXTEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRSETVIEWPORTORGEX 12
-void U_EMRSETVIEWPORTORGEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRSETVIEWPORTORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRSETBRUSHORGEX 13
-void U_EMRSETBRUSHORGEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRSETBRUSHORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMREOF 14
-void U_EMREOF_swap(char *record, int torev){
+int U_EMREOF_swap(char *record, int torev){
int off=0;
int cbPalEntries=0;
- core5_swap(record, torev);
+ const char *blimit = NULL;
PU_EMREOF pEmr = (PU_EMREOF)(record);
if(torev){
+ blimit = record + pEmr->emr.nSize;
cbPalEntries = pEmr->cbPalEntries;
- if(cbPalEntries){
- logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
- }
}
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->cbPalEntries),2); // cbPalEntries offPalEntries
if(!torev){
+ blimit = record + pEmr->emr.nSize;
cbPalEntries = pEmr->cbPalEntries;
- if(cbPalEntries){
- logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
- }
+ }
+ if(cbPalEntries){
+ if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0); // 2 16 bit values in U_LOGPALLETE
+ logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
+ // U_LOGPLTNTRY values in pallette are ordered data
}
off = sizeof(U_EMREOF) + 4 * cbPalEntries;
+ if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0);
U_swap4(record + off,1); // nSizeLast
+ return(1);
}
// U_EMRSETPIXELV 15
-void U_EMRSETPIXELV_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETPIXELV_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(record);
pointl_swap(&(pEmr->ptlPixel),1); // ptlPixel
// ordered bytes: crColor
+ return(1);
}
// U_EMRSETMAPPERFLAGS 16
-void U_EMRSETMAPPERFLAGS_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETMAPPERFLAGS_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(record);
U_swap4(&(pEmr->dwFlags),1); // dwFlags
+ return(1);
}
// U_EMRSETMAPMODE 17
-void U_EMRSETMAPMODE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETMAPMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETBKMODE 18
-void U_EMRSETBKMODE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETBKMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETPOLYFILLMODE 19
-void U_EMRSETPOLYFILLMODE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETPOLYFILLMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETROP2 20
-void U_EMRSETROP2_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETROP2_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETSTRETCHBLTMODE 21
-void U_EMRSETSTRETCHBLTMODE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETSTRETCHBLTMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETTEXTALIGN 22
-void U_EMRSETTEXTALIGN_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETTEXTALIGN_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETCOLORADJUSTMENT 23
-void U_EMRSETCOLORADJUSTMENT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETCOLORADJUSTMENT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(record);
coloradjustment_swap(&(pEmr->ColorAdjustment));
+ return(1);
}
// U_EMRSETTEXTCOLOR 24
-void U_EMRSETTEXTCOLOR_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETTEXTCOLOR_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
// ordered bytes: crColor
+ return(1);
}
// U_EMRSETBKCOLOR 25
-void U_EMRSETBKCOLOR_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETBKCOLOR_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
// ordered bytes: crColor
+ return(1);
}
// U_EMROFFSETCLIPRGN 26
-void U_EMROFFSETCLIPRGN_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMROFFSETCLIPRGN_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRMOVETOEX 27
-void U_EMRMOVETOEX_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRMOVETOEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRSETMETARGN 28
-void U_EMRSETMETARGN_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETMETARGN_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMREXCLUDECLIPRECT 29
-void U_EMREXCLUDECLIPRECT_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMREXCLUDECLIPRECT_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRINTERSECTCLIPRECT 30
-void U_EMRINTERSECTCLIPRECT_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRINTERSECTCLIPRECT_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRSCALEVIEWPORTEXTEX 31
-void U_EMRSCALEVIEWPORTEXTEX_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRSCALEVIEWPORTEXTEX_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
-
// U_EMRSCALEWINDOWEXTEX 32
-void U_EMRSCALEWINDOWEXTEX_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRSCALEWINDOWEXTEX_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRSAVEDC 33
-void U_EMRSAVEDC_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSAVEDC_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRRESTOREDC 34
-void U_EMRRESTOREDC_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRRESTOREDC_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETWORLDTRANSFORM 35
-void U_EMRSETWORLDTRANSFORM_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETWORLDTRANSFORM_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(record);
xform_swap(&(pEmr->xform));
+ return(1);
}
// U_EMRMODIFYWORLDTRANSFORM 36
-void U_EMRMODIFYWORLDTRANSFORM_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRMODIFYWORLDTRANSFORM_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(record);
xform_swap(&(pEmr->xform)); // xform
U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
}
// U_EMRSELECTOBJECT 37
-void U_EMRSELECTOBJECT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSELECTOBJECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(record);
U_swap4(&(pEmr->ihObject),1); // ihObject
+ return(1);
}
// U_EMRCREATEPEN 38
-void U_EMRCREATEPEN_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCREATEPEN_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(record);
U_swap4(&(pEmr->ihPen),1); // ihPen
logpen_swap(&(pEmr->lopn)); // lopn
+ return(1);
}
// U_EMRCREATEBRUSHINDIRECT 39
-void U_EMRCREATEBRUSHINDIRECT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCREATEBRUSHINDIRECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(record);
U_swap4(&(pEmr->ihBrush),1); // ihBrush
logbrush_swap(&(pEmr->lb)); // lb
+ return(1);
}
// U_EMRDELETEOBJECT 40
-void U_EMRDELETEOBJECT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRDELETEOBJECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(record);
U_swap4(&(pEmr->ihObject),1); // ihObject
+ return(1);
}
// U_EMRANGLEARC 41
-void U_EMRANGLEARC_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRANGLEARC_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(record);
pointl_swap(&(pEmr->ptlCenter),1); // ptlCenter
U_swap4(&(pEmr->nRadius),3); // nRadius eStartAngle eSweepAngle
+ return(1);
}
// U_EMRELLIPSE 42
-void U_EMRELLIPSE_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRELLIPSE_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRRECTANGLE 43
-void U_EMRRECTANGLE_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRRECTANGLE_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRROUNDRECT 44
-void U_EMRROUNDRECT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRROUNDRECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(record);
rectl_swap(&(pEmr->rclBox),1); // rclBox
sizel_swap(&(pEmr->szlCorner), 1); // szlCorner
+ return(1);
}
// U_EMRARC 45
-void U_EMRARC_swap(char *record, int torev){
- core9_swap(record, torev);
+int U_EMRARC_swap(char *record, int torev){
+ return(core9_swap(record, torev));
}
// U_EMRCHORD 46
-void U_EMRCHORD_swap(char *record, int torev){
- core9_swap(record, torev);
+int U_EMRCHORD_swap(char *record, int torev){
+ return(core9_swap(record, torev));
}
// U_EMRPIE 47
-void U_EMRPIE_swap(char *record, int torev){
- core9_swap(record, torev);
+int U_EMRPIE_swap(char *record, int torev){
+ return(core9_swap(record, torev));
}
// U_EMRSELECTPALETTE 48
-void U_EMRSELECTPALETTE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSELECTPALETTE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRCREATEPALETTE 49
-void U_EMRCREATEPALETTE_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCREATEPALETTE_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(record);
U_swap4(&(pEmr->ihPal),1); // ihPal
logpalette_swap( (PU_LOGPALETTE)&(pEmr->lgpl) ); // lgpl
+ return(1);
}
// U_EMRSETPALETTEENTRIES 50
-void U_EMRSETPALETTEENTRIES_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRSETPALETTEENTRIES_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(record);
U_swap4(&(pEmr->ihPal),3); // ihPal iStart cEntries
// ordered bytes: aPalEntries[]
+ return(1);
}
// U_EMRRESIZEPALETTE 51
-void U_EMRRESIZEPALETTE_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRRESIZEPALETTE_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRREALIZEPALETTE 52
-void U_EMRREALIZEPALETTE_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRREALIZEPALETTE_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMREXTFLOODFILL 53
-void U_EMREXTFLOODFILL_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMREXTFLOODFILL_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(record);
pointl_swap(&(pEmr->ptlStart),1); // ptlStart
// ordered bytes: crColor
U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
}
// U_EMRLINETO 54
-void U_EMRLINETO_swap(char *record, int torev){
- core7_swap(record, torev);
+int U_EMRLINETO_swap(char *record, int torev){
+ return(core7_swap(record, torev));
}
// U_EMRARCTO 55
-void U_EMRARCTO_swap(char *record, int torev){
- core9_swap(record, torev);
+int U_EMRARCTO_swap(char *record, int torev){
+ return(core9_swap(record, torev));
}
// U_EMRPOLYDRAW 56
-void U_EMRPOLYDRAW_swap(char *record, int torev){
+int U_EMRPOLYDRAW_swap(char *record, int torev){
int count=0;
- core5_swap(record, torev);
+ const char *blimit = NULL;
PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record);
if(torev){
count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cptl),1); // cptl
if(!torev){
count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0);
pointl_swap(pEmr->aptl,count); // aptl[]
- U_swap4(pEmr->abTypes,count); // abTypes[]
+ // single byte data abTypes
+ return(1);
}
// U_EMRSETARCDIRECTION 57
-void U_EMRSETARCDIRECTION_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETARCDIRECTION_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRSETMITERLIMIT 58
-void U_EMRSETMITERLIMIT_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETMITERLIMIT_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRBEGINPATH 59
-void U_EMRBEGINPATH_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRBEGINPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRENDPATH 60
-void U_EMRENDPATH_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRENDPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRCLOSEFIGURE 61
-void U_EMRCLOSEFIGURE_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCLOSEFIGURE_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRFILLPATH 62
-void U_EMRFILLPATH_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRFILLPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRSTROKEANDFILLPATH 63
-void U_EMRSTROKEANDFILLPATH_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRSTROKEANDFILLPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRSTROKEPATH 64
-void U_EMRSTROKEPATH_swap(char *record, int torev){
- core4_swap(record, torev);
+int U_EMRSTROKEPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
}
// U_EMRFLATTENPATH 65
-void U_EMRFLATTENPATH_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRFLATTENPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRWIDENPATH 66
-void U_EMRWIDENPATH_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRWIDENPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRSELECTCLIPPATH 67
-void U_EMRSELECTCLIPPATH_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSELECTCLIPPATH_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRABORTPATH 68
-void U_EMRABORTPATH_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRABORTPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
}
// U_EMRUNDEF69 69
#define U_EMRUNDEF69_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
-void U_EMRCOMMENT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCOMMENT_swap(char *record, int torev){
+ int cbData = 0;
+ const char *blimit = NULL;
PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record);
+ if(torev){
+ cbData = pEmr->cbData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->cbData),1); // cbData
+ if(!torev){
+ cbData = pEmr->cbData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0);
// program specific data, presumably byte ordered, otherwise, not portable
+ return(1);
}
// U_EMRFILLRGN 71
-void U_EMRFILLRGN_swap(char *record, int torev){
- int roff=0;
- int nextroff=0;
- int limit=0;
- roff=0;
+int U_EMRFILLRGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record);
if(torev){
- limit = pEmr->emr.nSize;
- nextroff = 0;
- }
- core5_swap(record, torev);
- if(!torev){
- limit = pEmr->emr.nSize;
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + 28 < limit){ // up to the end of the record
- if(torev){
- nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff = nextroff;
- }
- else {
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
}
// U_EMRFRAMERGN 72
-void U_EMRFRAMERGN_swap(char *record, int torev){
- int roff=0;
- int nextroff=0;
- int limit=0;
+int U_EMRFRAMERGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record);
- roff = 0;
if(torev){
- limit = pEmr->emr.nSize;
- nextroff = 0;
- }
- core5_swap(record, torev);
- if(!torev){
- limit = pEmr->emr.nSize;
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
- sizel_swap(&(pEmr->szlStroke), 2); // szlStroke
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + 28 < limit){ // up to the end of the record
- if(torev){
- nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff = nextroff;
- }
- else {
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ sizel_swap(&(pEmr->szlStroke), 1); // szlStroke
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
}
// U_EMRINVERTRGN 73
-void U_EMRINVERTRGN_swap(char *record, int torev){
- core11_swap(record, torev);
+int U_EMRINVERTRGN_swap(char *record, int torev){
+ return(core11_swap(record, torev));
}
// U_EMRPAINTRGN 74
-void U_EMRPAINTRGN_swap(char *record, int torev){
- core11_swap(record, torev);
+int U_EMRPAINTRGN_swap(char *record, int torev){
+ return(core11_swap(record, torev));
}
// U_EMREXTSELECTCLIPRGN 75
-void U_EMREXTSELECTCLIPRGN_swap(char *record, int torev){
- int roff=0;
- int nextroff=0;
- int limit=0;
- PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (record);
+int U_EMREXTSELECTCLIPRGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record);
if(torev){
- limit = pEmr->emr.nSize;
- }
- core5_swap(record, torev);
- if(!torev){
- limit = pEmr->emr.nSize;
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->cbRgnData),2); // cbRgnData iMode
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- char *prd = (char *) &(pEmr->RgnData);
- nextroff = roff = 0;
- while(roff + 16 < limit){ // up to the end of the record
- if(torev){
- nextroff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff = nextroff;
- }
- else {
- rgndata_swap((PU_RGNDATA) (prd + roff));
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
}
// U_EMRBITBLT 76
-void U_EMRBITBLT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRBITBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),2); // Dest cDest
U_swap4(&(pEmr->dwRop),1); // dwRop
@@ -1226,42 +1389,89 @@ void U_EMRBITBLT_swap(char *record, int torev){
xform_swap(&(pEmr->xformSrc)); // xformSrc
// ordered bytes: crBkColorSrc
U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
- // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
}
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
}
// U_EMRSTRETCHBLT 77
-void U_EMRSTRETCHBLT_swap(char *record, int torev){
+int U_EMRSTRETCHBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (record);
- core5_swap(record, torev);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),2); // Dest cDest
U_swap4(&(pEmr->dwRop),1); // dwRop
pointl_swap(&(pEmr->Src),1); // Src
xform_swap(&(pEmr->xformSrc)); // xformSrc
// ordered bytes: crBkColorSrc
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
pointl_swap(&(pEmr->cSrc),1); // cSrc
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
}
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
}
// U_EMRMASKBLT 78
-void U_EMRMASKBLT_swap(char *record, int torev){
+int U_EMRMASKBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ U_OFFBMIMSK offBmiMask = 0;
+ U_CBBMIMSK cbBmiMask = 0;
+ U_OFFBITSMSK offBitsMask = 0;
+ U_CBBITSMSK cbBitsMask = 0;
+ uint32_t iUsageMask = 0;
PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record);
- core5_swap(record, torev);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
- if(torev && pEmr->cbBmiMask){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
- }
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),2); // Dest cDest
U_swap4(&(pEmr->dwRop),1); // dwRop
@@ -1271,24 +1481,54 @@ void U_EMRMASKBLT_swap(char *record, int torev){
U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
pointl_swap(&(pEmr->Mask),1); // Mask
U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
- if(!torev && pEmr->cbBmiMask){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
- }
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ return(1);
}
// U_EMRPLGBLT 79
-void U_EMRPLGBLT_swap(char *record, int torev){
+int U_EMRPLGBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ U_OFFBMIMSK offBmiMask = 0;
+ U_CBBMIMSK cbBmiMask = 0;
+ U_OFFBITSMSK offBitsMask = 0;
+ U_CBBITSMSK cbBitsMask = 0;
+ uint32_t iUsageMask = 0;
PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record);
- core5_swap(record, torev);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
- if(torev && pEmr->cbBmiMask){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
- }
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(pEmr->aptlDst,3); // aptlDst[]
pointl_swap(&(pEmr->Src),2); // Src cSrc
@@ -1297,78 +1537,124 @@ void U_EMRPLGBLT_swap(char *record, int torev){
U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
pointl_swap(&(pEmr->Mask),1); // Mask
U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
- if(!torev && pEmr->cbBmiMask){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiMask));
- }
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ return(1);
}
// U_EMRSETDIBITSTODEVICE 80
-void U_EMRSETDIBITSTODEVICE_swap(char *record, int torev){
+int U_EMRSETDIBITSTODEVICE_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record);
- core5_swap(record, torev);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),1); // Dest
pointl_swap(&(pEmr->Src),2); // Src cSrc
U_swap4(&(pEmr->offBmiSrc),7); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc iStartScan cScans
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
}
+ return(1);
}
// U_EMRSTRETCHDIBITS 81
-void U_EMRSTRETCHDIBITS_swap(char *record, int torev){
+int U_EMRSTRETCHDIBITS_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record);
- core5_swap(record, torev);
- if(torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
- }
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
pointl_swap(&(pEmr->Dest),1); // Dest
pointl_swap(&(pEmr->Src),2); // Src cSrc
U_swap4(&(pEmr->offBmiSrc),6); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc dwRop
pointl_swap(&(pEmr->cDest),1); // cDest
- if(!torev && pEmr->cbBmiSrc){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmiSrc));
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
}
+ return(1);
}
-// U_EMREXTCREATEFONTINDIRECTW_swap 82
-void U_EMREXTCREATEFONTINDIRECTW_swap(char *record, int torev){
+// U_EMREXTCREATEFONTINDIRECTW 82
+int U_EMREXTCREATEFONTINDIRECTW_swap(char *record, int torev){
+ int nSize = 0;
PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (record);
if(torev){
- if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){
- logfont_panose_swap(&(pEmr->elfw));
- }
- else {
- logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
- }
+ nSize = pEmr->emr.nSize;
}
- core5_swap(record, torev);
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->ihFont),1); // ihFont
if(!torev){
- if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){
- logfont_panose_swap(&(pEmr->elfw));
- }
- else {
- logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
- }
+ nSize = pEmr->emr.nSize;
}
- U_swap4(&(pEmr->ihFont),1); // ihFont
+ if(nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){
+ logfont_panose_swap(&(pEmr->elfw));
+ }
+ else { // logfont or logfontExDv (which starts with logfont, which can be swapped, and the rest is already in byte order
+ logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
+ }
+ return(1);
}
// U_EMREXTTEXTOUTA 83
-void U_EMREXTTEXTOUTA_swap(char *record, int torev){
- core8_swap(record, torev);
+int U_EMREXTTEXTOUTA_swap(char *record, int torev){
+ return(core8_swap(record, torev));
}
// U_EMREXTTEXTOUTW 84
-void U_EMREXTTEXTOUTW_swap(char *record, int torev){
- core8_swap(record, torev);
+int U_EMREXTTEXTOUTW_swap(char *record, int torev){
+ return(core8_swap(record, torev));
}
// U_EMRPOLYBEZIER16 85
@@ -1376,23 +1662,23 @@ void U_EMREXTTEXTOUTW_swap(char *record, int torev){
\brief Convert a pointer to a U_EMR_POLYBEZIER16 record.
\param record pointer to a buffer holding the EMR record
*/
-void U_EMRPOLYBEZIER16_swap(char *record, int torev){
- core6_swap(record, torev);
+int U_EMRPOLYBEZIER16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
}
// U_EMRPOLYGON16 86
-void U_EMRPOLYGON16_swap(char *record, int torev){
- core6_swap(record, torev);
+int U_EMRPOLYGON16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
}
// U_EMRPOLYLINE16 87
-void U_EMRPOLYLINE16_swap(char *record, int torev){
- core6_swap(record, torev);
+int U_EMRPOLYLINE16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
}
// U_EMRPOLYBEZIERTO16 88
-void U_EMRPOLYBEZIERTO16_swap(char *record, int torev){
- core6_swap(record, torev);
+int U_EMRPOLYBEZIERTO16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
}
// U_EMRPOLYLINETO16 89
@@ -1400,61 +1686,81 @@ void U_EMRPOLYBEZIERTO16_swap(char *record, int torev){
\brief Convert a pointer to a U_EMR_POLYLINETO16 record.
\param record pointer to a buffer holding the EMR record
*/
-void U_EMRPOLYLINETO16_swap(char *record, int torev){
- core6_swap(record, torev);
+int U_EMRPOLYLINETO16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
}
// U_EMRPOLYPOLYLINE16 90
-void U_EMRPOLYPOLYLINE16_swap(char *record, int torev){
- core10_swap(record, torev);
+int U_EMRPOLYPOLYLINE16_swap(char *record, int torev){
+ return(core10_swap(record, torev));
}
// U_EMRPOLYPOLYGON16 91
-void U_EMRPOLYPOLYGON16_swap(char *record, int torev){
- core10_swap(record, torev);
+int U_EMRPOLYPOLYGON16_swap(char *record, int torev){
+ return(core10_swap(record, torev));
}
// U_EMRPOLYDRAW16 92
-void U_EMRPOLYDRAW16_swap(char *record, int torev){
+int U_EMRPOLYDRAW16_swap(char *record, int torev){
int count=0;
- core5_swap(record, torev);
+ const char *blimit = NULL;
PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record);
if(torev){
count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->cpts),1); // cpts
if(!torev){
count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
}
+ if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0);
point16_swap(pEmr->apts,count); // apts[]
- U_swap4(pEmr->abTypes,count); // abTypes[]
+ // single byte data abTypes
+ return(1);
}
// U_EMRCREATEMONOBRUSH 93
-void U_EMRCREATEMONOBRUSH_swap(char *record, int torev){
- core12_swap(record, torev);
+int U_EMRCREATEMONOBRUSH_swap(char *record, int torev){
+ return(core12_swap(record, torev));
}
// U_EMRCREATEDIBPATTERNBRUSHPT_swap 94
-void U_EMRCREATEDIBPATTERNBRUSHPT_swap(char *record, int torev){
- core12_swap(record, torev);
+int U_EMRCREATEDIBPATTERNBRUSHPT_swap(char *record, int torev){
+ return(core12_swap(record, torev));
}
// U_EMREXTCREATEPEN 95
-void U_EMREXTCREATEPEN_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMREXTCREATEPEN_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMI offBmi = 0;
+ U_CBBMI cbBmi = 0;
+ U_OFFBITS offBits = 0;
+ U_CBBITS cbBits = 0;
PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record);
- if(torev && pEmr->cbBmi){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi));
- }
+ if(torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->ihPen),5); // ihPen offBmi cbBmi offBits cbBits
- if(!torev && pEmr->cbBmi){
- bitmapinfo_swap((PU_BITMAPINFO)(record + pEmr->offBmi));
+ if(!torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
}
- extlogpen_swap((PU_EXTLOGPEN) &(pEmr->elp), torev);
+ return(extlogpen_swap((PU_EXTLOGPEN) &(pEmr->elp), blimit, torev));
}
// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
@@ -1463,26 +1769,27 @@ void U_EMREXTCREATEPEN_swap(char *record, int torev){
#define U_EMRPOLYTEXTOUTW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRSETICMMODE 98
-void U_EMRSETICMMODE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETICMMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRCREATECOLORSPACE 99
-void U_EMRCREATECOLORSPACE_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCREATECOLORSPACE_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(record);
U_swap4(&(pEmr->ihCS),1); // ihCS
logcolorspacea_swap(&(pEmr->lcs)); // lcs
+ return(1);
}
// U_EMRSETCOLORSPACE 100
-void U_EMRSETCOLORSPACE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETCOLORSPACE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRDELETECOLORSPACE 101
-void U_EMRDELETECOLORSPACE_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRDELETECOLORSPACE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRGLSRECORD 102 Not implemented
@@ -1491,10 +1798,11 @@ void U_EMRDELETECOLORSPACE_swap(char *record, int torev){
#define U_EMRGLSBOUNDEDRECORD_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRPIXELFORMAT 104
-void U_EMRPIXELFORMAT_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRPIXELFORMAT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(record);
pixelformatdescriptor_swap(&(pEmr->pfd)); // pfd
+ return(1);
}
// U_EMRDRAWESCAPE 105 Not implemented
@@ -1505,24 +1813,32 @@ void U_EMRPIXELFORMAT_swap(char *record, int torev){
#define U_EMRUNDEF107_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRSMALLTEXTOUT 108
-void U_EMRSMALLTEXTOUT_swap(char *record, int torev){
- int roff=0;
- int fuOptions=0;
- core5_swap(record, torev);
+int U_EMRSMALLTEXTOUT_swap(char *record, int torev){
+ int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
+ int fuOptions = 0;
+ int cChars = 0;
+ const char *blimit = NULL;
PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record);
if(torev){
fuOptions = pEmr->fuOptions;
+ cChars = pEmr->cChars;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
pointl_swap(&(pEmr->Dest),1); // Dest
U_swap4(&(pEmr->cChars),5); // cChars fuOptions iGraphicsMode exScale eyScale
if(!torev){
fuOptions = pEmr->fuOptions;
+ cChars = pEmr->cChars;
+ blimit = record + pEmr->emr.nSize;
}
- roff = sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
if(!(fuOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0);
rectl_swap( (PU_RECTL) (record + roff),1); // rclBounds
}
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0);
// ordered bytes or UTF16-LE TextString
+ return(1);
}
// U_EMRFORCEUFIMAPPING 109 Not implemented
@@ -1537,55 +1853,62 @@ void U_EMRSMALLTEXTOUT_swap(char *record, int torev){
#define U_EMRSETICMPROFILEW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRALPHABLEND 114
-void U_EMRALPHABLEND_swap(char *record, int torev){
- core13_swap(record, torev);
+int U_EMRALPHABLEND_swap(char *record, int torev){
+ return(core13_swap(record, torev));
}
// U_EMRSETLAYOUT 115
-void U_EMRSETLAYOUT_swap(char *record, int torev){
- core3_swap(record, torev);
+int U_EMRSETLAYOUT_swap(char *record, int torev){
+ return(core3_swap(record, torev));
}
// U_EMRTRANSPARENTBLT 116
-void U_EMRTRANSPARENTBLT_swap(char *record, int torev){
- core13_swap(record, torev);
+int U_EMRTRANSPARENTBLT_swap(char *record, int torev){
+ return(core13_swap(record, torev));
}
// U_EMRUNDEF117 117 Not implemented
#define U_EMRUNDEF117_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRGRADIENTFILL 118
-void U_EMRGRADIENTFILL_swap(char *record, int torev){
+int U_EMRGRADIENTFILL_swap(char *record, int torev){
int nTriVert=0;
int nGradObj=0;
int ulMode=0;
- core5_swap(record, torev);
+ const char *blimit = NULL;
PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record);
if(torev){
nTriVert = pEmr->nTriVert;
nGradObj = pEmr->nGradObj;
ulMode = pEmr->ulMode;
+ blimit = record + pEmr->emr.nSize;
}
+ if(!core5_swap(record, torev))return(0);
rectl_swap(&(pEmr->rclBounds),1); // rclBounds
U_swap4(&(pEmr->nTriVert),3); // nTriVert nGradObj ulMode
if(!torev){
nTriVert = pEmr->nTriVert;
nGradObj = pEmr->nGradObj;
ulMode = pEmr->ulMode;
+ blimit = record + pEmr->emr.nSize;
}
record += sizeof(U_EMRGRADIENTFILL);
+ if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0);
if(nTriVert){
trivertex_swap((PU_TRIVERTEX)(record),nTriVert); // TriVert[]
}
record += nTriVert * sizeof(U_TRIVERTEX);
if(nGradObj){
if( ulMode == U_GRADIENT_FILL_TRIANGLE){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0);
gradient3_swap((PU_GRADIENT3)(record), nGradObj); // GradObj[]
}
else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0);
gradient4_swap((PU_GRADIENT4)(record), nGradObj); // GradObj[]
}
}
+ return(1);
}
// U_EMRSETLINKEDUFIS 119 Not implemented
@@ -1596,17 +1919,185 @@ void U_EMRGRADIENTFILL_swap(char *record, int torev){
#define U_EMRCOLORMATCHTOTARGETW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
// U_EMRCREATECOLORSPACEW 122
-void U_EMRCREATECOLORSPACEW_swap(char *record, int torev){
- core5_swap(record, torev);
+int U_EMRCREATECOLORSPACEW_swap(char *record, int torev){
PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(record);
+ if(!core5_swap(record, torev))return(0);
U_swap4(&(pEmr->ihCS),1); // ihCS
logcolorspacew_swap(&(pEmr->lcs)); // lcs
U_swap4(&(pEmr->dwFlags),2); // dwFlags cbData
// ordered bytes: Data
+ return(1);
}
//! \endcond
+/**
+ \brief Checks the declared size of a record for consistency
+ \return 0 on failure, 1 on success
+ \param record pointer to the start of the EMF record in memory
+ \param blimit pointer to one byte after the EMF record in memory
+ \param nSize number of bytes in the record, read from the record
+ \param iType type of the record, read from the record
+ \param torev 1 for native to reversed, 0 for reversed to native
+
+ Normally this would be called immediately after reading the data from a file.
+ Verifies that the declared size is consistent with this type of record.
+*/
+int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev){
+ uint32_t rsize=0;
+ if(!nSize || !iType)return(0); // programming error
+
+ /* Check that COMMON data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range, and fail any indications of such a wrap.
+ */
+ if(IS_MEM_UNSAFE(record, sizeof(U_EMR), blimit))return(0);
+
+ PU_ENHMETARECORD pEmr = (PU_ENHMETARECORD)(record);
+ *iType = pEmr->iType;
+ *nSize = pEmr->nSize;
+ if(!torev){
+ U_swap4(iType,1);
+ U_swap4(nSize,1);
+ }
+
+ /* Check that the FULL record size is OK, abort if not. */
+ if(IS_MEM_UNSAFE(record, *nSize, blimit))return(0);
+
+ switch (*iType)
+ {
+ // next line, ancient EMF files used a smaller header, to be safe, test for that
+ case U_EMR_HEADER: rsize = U_SIZE_EMRHEADER_MIN; break;
+ case U_EMR_POLYBEZIER: rsize = U_SIZE_EMRPOLYBEZIER; break;
+ case U_EMR_POLYGON: rsize = U_SIZE_EMRPOLYGON; break;
+ case U_EMR_POLYLINE: rsize = U_SIZE_EMRPOLYLINE; break;
+ case U_EMR_POLYBEZIERTO: rsize = U_SIZE_EMRPOLYBEZIERTO; break;
+ case U_EMR_POLYLINETO: rsize = U_SIZE_EMRPOLYLINETO; break;
+ case U_EMR_POLYPOLYLINE: rsize = U_SIZE_EMRPOLYPOLYLINE; break;
+ case U_EMR_POLYPOLYGON: rsize = U_SIZE_EMRPOLYPOLYGON; break;
+ case U_EMR_SETWINDOWEXTEX: rsize = U_SIZE_EMRSETWINDOWEXTEX; break;
+ case U_EMR_SETWINDOWORGEX: rsize = U_SIZE_EMRSETWINDOWORGEX; break;
+ case U_EMR_SETVIEWPORTEXTEX: rsize = U_SIZE_EMRSETVIEWPORTEXTEX; break;
+ case U_EMR_SETVIEWPORTORGEX: rsize = U_SIZE_EMRSETVIEWPORTORGEX; break;
+ case U_EMR_SETBRUSHORGEX: rsize = U_SIZE_EMRSETBRUSHORGEX; break;
+ case U_EMR_EOF: rsize = U_SIZE_EMREOF; break;
+ case U_EMR_SETPIXELV: rsize = U_SIZE_EMRSETPIXELV; break;
+ case U_EMR_SETMAPPERFLAGS: rsize = U_SIZE_EMRSETMAPPERFLAGS; break;
+ case U_EMR_SETMAPMODE: rsize = U_SIZE_EMRSETMAPMODE; break;
+ case U_EMR_SETBKMODE: rsize = U_SIZE_EMRSETBKMODE; break;
+ case U_EMR_SETPOLYFILLMODE: rsize = U_SIZE_EMRSETPOLYFILLMODE; break;
+ case U_EMR_SETROP2: rsize = U_SIZE_EMRSETROP2; break;
+ case U_EMR_SETSTRETCHBLTMODE: rsize = U_SIZE_EMRSETSTRETCHBLTMODE; break;
+ case U_EMR_SETTEXTALIGN: rsize = U_SIZE_EMRSETTEXTALIGN; break;
+ case U_EMR_SETCOLORADJUSTMENT: rsize = U_SIZE_EMRSETCOLORADJUSTMENT; break;
+ case U_EMR_SETTEXTCOLOR: rsize = U_SIZE_EMRSETTEXTCOLOR; break;
+ case U_EMR_SETBKCOLOR: rsize = U_SIZE_EMRSETBKCOLOR; break;
+ case U_EMR_OFFSETCLIPRGN: rsize = U_SIZE_EMROFFSETCLIPRGN; break;
+ case U_EMR_MOVETOEX: rsize = U_SIZE_EMRMOVETOEX; break;
+ case U_EMR_SETMETARGN: rsize = U_SIZE_EMRSETMETARGN; break;
+ case U_EMR_EXCLUDECLIPRECT: rsize = U_SIZE_EMREXCLUDECLIPRECT; break;
+ case U_EMR_INTERSECTCLIPRECT: rsize = U_SIZE_EMRINTERSECTCLIPRECT; break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rsize = U_SIZE_EMRSCALEVIEWPORTEXTEX; break;
+ case U_EMR_SCALEWINDOWEXTEX: rsize = U_SIZE_EMRSCALEWINDOWEXTEX; break;
+ case U_EMR_SAVEDC: rsize = U_SIZE_EMRSAVEDC; break;
+ case U_EMR_RESTOREDC: rsize = U_SIZE_EMRRESTOREDC; break;
+ case U_EMR_SETWORLDTRANSFORM: rsize = U_SIZE_EMRSETWORLDTRANSFORM; break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rsize = U_SIZE_EMRMODIFYWORLDTRANSFORM; break;
+ case U_EMR_SELECTOBJECT: rsize = U_SIZE_EMRSELECTOBJECT; break;
+ case U_EMR_CREATEPEN: rsize = U_SIZE_EMRCREATEPEN; break;
+ case U_EMR_CREATEBRUSHINDIRECT: rsize = U_SIZE_EMRCREATEBRUSHINDIRECT; break;
+ case U_EMR_DELETEOBJECT: rsize = U_SIZE_EMRDELETEOBJECT; break;
+ case U_EMR_ANGLEARC: rsize = U_SIZE_EMRANGLEARC; break;
+ case U_EMR_ELLIPSE: rsize = U_SIZE_EMRELLIPSE; break;
+ case U_EMR_RECTANGLE: rsize = U_SIZE_EMRRECTANGLE; break;
+ case U_EMR_ROUNDRECT: rsize = U_SIZE_EMRROUNDRECT; break;
+ case U_EMR_ARC: rsize = U_SIZE_EMRARC; break;
+ case U_EMR_CHORD: rsize = U_SIZE_EMRCHORD; break;
+ case U_EMR_PIE: rsize = U_SIZE_EMRPIE; break;
+ case U_EMR_SELECTPALETTE: rsize = U_SIZE_EMRSELECTPALETTE; break;
+ case U_EMR_CREATEPALETTE: rsize = U_SIZE_EMRCREATEPALETTE; break;
+ case U_EMR_SETPALETTEENTRIES: rsize = U_SIZE_EMRSETPALETTEENTRIES; break;
+ case U_EMR_RESIZEPALETTE: rsize = U_SIZE_EMRRESIZEPALETTE; break;
+ case U_EMR_REALIZEPALETTE: rsize = U_SIZE_EMRREALIZEPALETTE; break;
+ case U_EMR_EXTFLOODFILL: rsize = U_SIZE_EMREXTFLOODFILL; break;
+ case U_EMR_LINETO: rsize = U_SIZE_EMRLINETO; break;
+ case U_EMR_ARCTO: rsize = U_SIZE_EMRARCTO; break;
+ case U_EMR_POLYDRAW: rsize = U_SIZE_EMRPOLYDRAW; break;
+ case U_EMR_SETARCDIRECTION: rsize = U_SIZE_EMRSETARCDIRECTION; break;
+ case U_EMR_SETMITERLIMIT: rsize = U_SIZE_EMRSETMITERLIMIT; break;
+ case U_EMR_BEGINPATH: rsize = U_SIZE_EMRBEGINPATH; break;
+ case U_EMR_ENDPATH: rsize = U_SIZE_EMRENDPATH; break;
+ case U_EMR_CLOSEFIGURE: rsize = U_SIZE_EMRCLOSEFIGURE; break;
+ case U_EMR_FILLPATH: rsize = U_SIZE_EMRFILLPATH; break;
+ case U_EMR_STROKEANDFILLPATH: rsize = U_SIZE_EMRSTROKEANDFILLPATH; break;
+ case U_EMR_STROKEPATH: rsize = U_SIZE_EMRSTROKEPATH; break;
+ case U_EMR_FLATTENPATH: rsize = U_SIZE_EMRFLATTENPATH; break;
+ case U_EMR_WIDENPATH: rsize = U_SIZE_EMRWIDENPATH; break;
+ case U_EMR_SELECTCLIPPATH: rsize = U_SIZE_EMRSELECTCLIPPATH; break;
+ case U_EMR_ABORTPATH: rsize = U_SIZE_EMRABORTPATH; break;
+ case U_EMR_UNDEF69: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_COMMENT: rsize = U_SIZE_EMRCOMMENT; break;
+ case U_EMR_FILLRGN: rsize = U_SIZE_EMRFILLRGN; break;
+ case U_EMR_FRAMERGN: rsize = U_SIZE_EMRFRAMERGN; break;
+ case U_EMR_INVERTRGN: rsize = U_SIZE_EMRINVERTRGN; break;
+ case U_EMR_PAINTRGN: rsize = U_SIZE_EMRPAINTRGN; break;
+ case U_EMR_EXTSELECTCLIPRGN: rsize = U_SIZE_EMREXTSELECTCLIPRGN; break;
+ case U_EMR_BITBLT: rsize = U_SIZE_EMRBITBLT; break;
+ case U_EMR_STRETCHBLT: rsize = U_SIZE_EMRSTRETCHBLT; break;
+ case U_EMR_MASKBLT: rsize = U_SIZE_EMRMASKBLT; break;
+ case U_EMR_PLGBLT: rsize = U_SIZE_EMRPLGBLT; break;
+ case U_EMR_SETDIBITSTODEVICE: rsize = U_SIZE_EMRSETDIBITSTODEVICE; break;
+ case U_EMR_STRETCHDIBITS: rsize = U_SIZE_EMRSTRETCHDIBITS; break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rsize = U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT; break;
+ case U_EMR_EXTTEXTOUTA: rsize = U_SIZE_EMREXTTEXTOUTA; break;
+ case U_EMR_EXTTEXTOUTW: rsize = U_SIZE_EMREXTTEXTOUTW; break;
+ case U_EMR_POLYBEZIER16: rsize = U_SIZE_EMRPOLYBEZIER16; break;
+ case U_EMR_POLYGON16: rsize = U_SIZE_EMRPOLYGON16; break;
+ case U_EMR_POLYLINE16: rsize = U_SIZE_EMRPOLYLINE16; break;
+ case U_EMR_POLYBEZIERTO16: rsize = U_SIZE_EMRPOLYBEZIERTO16; break;
+ case U_EMR_POLYLINETO16: rsize = U_SIZE_EMRPOLYLINETO16; break;
+ case U_EMR_POLYPOLYLINE16: rsize = U_SIZE_EMRPOLYPOLYLINE16; break;
+ case U_EMR_POLYPOLYGON16: rsize = U_SIZE_EMRPOLYPOLYGON16; break;
+ case U_EMR_POLYDRAW16: rsize = U_SIZE_EMRPOLYDRAW16; break;
+ case U_EMR_CREATEMONOBRUSH: rsize = U_SIZE_EMRCREATEMONOBRUSH; break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rsize = U_SIZE_EMRCREATEDIBPATTERNBRUSHPT; break;
+ case U_EMR_EXTCREATEPEN: rsize = U_SIZE_EMREXTCREATEPEN; break;
+ case U_EMR_POLYTEXTOUTA: rsize = U_SIZE_EMRPOLYTEXTOUTA; break;
+ case U_EMR_POLYTEXTOUTW: rsize = U_SIZE_EMRPOLYTEXTOUTW; break;
+ case U_EMR_SETICMMODE: rsize = U_SIZE_EMRSETICMMODE; break;
+ case U_EMR_CREATECOLORSPACE: rsize = U_SIZE_EMRCREATECOLORSPACE; break;
+ case U_EMR_SETCOLORSPACE: rsize = U_SIZE_EMRSETCOLORSPACE; break;
+ case U_EMR_DELETECOLORSPACE: rsize = U_SIZE_EMRDELETECOLORSPACE; break;
+ case U_EMR_GLSRECORD: rsize = U_SIZE_EMRGLSRECORD; break;
+ case U_EMR_GLSBOUNDEDRECORD: rsize = U_SIZE_EMRGLSBOUNDEDRECORD; break;
+ case U_EMR_PIXELFORMAT: rsize = U_SIZE_EMRPIXELFORMAT; break;
+ case U_EMR_DRAWESCAPE: rsize = U_SIZE_EMRDRAWESCAPE; break;
+ case U_EMR_EXTESCAPE: rsize = U_SIZE_EMREXTESCAPE; break;
+ case U_EMR_UNDEF107: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_SMALLTEXTOUT: rsize = U_SIZE_EMRSMALLTEXTOUT; break;
+// case U_EMR_FORCEUFIMAPPING: rsize = U_SIZE_EMRFORCEUFIMAPPING; break;
+ case U_EMR_NAMEDESCAPE: rsize = U_SIZE_EMRNAMEDESCAPE; break;
+// case U_EMR_COLORCORRECTPALETTE: rsize = U_SIZE_EMRCOLORCORRECTPALETTE; break;
+// case U_EMR_SETICMPROFILEA: rsize = U_SIZE_EMRSETICMPROFILEA; break;
+// case U_EMR_SETICMPROFILEW: rsize = U_SIZE_EMRSETICMPROFILEW; break;
+ case U_EMR_ALPHABLEND: rsize = U_SIZE_EMRALPHABLEND; break;
+ case U_EMR_SETLAYOUT: rsize = U_SIZE_EMRSETLAYOUT; break;
+ case U_EMR_TRANSPARENTBLT: rsize = U_SIZE_EMRTRANSPARENTBLT; break;
+ case U_EMR_UNDEF117: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_GRADIENTFILL: rsize = U_SIZE_EMRGRADIENTFILL; break;
+// case U_EMR_SETLINKEDUFIS: rsize = U_SIZE_EMRSETLINKEDUFIS; break;
+// case U_EMR_SETTEXTJUSTIFICATION: rsize = U_SIZE_EMRSETTEXTJUSTIFICATION; break;
+ case U_EMR_COLORMATCHTOTARGETW: rsize = U_SIZE_EMRCOLORMATCHTOTARGETW; break;
+ case U_EMR_CREATECOLORSPACEW: rsize = U_SIZE_EMRCREATECOLORSPACEW; break;
+ default: rsize = U_SIZE_EMRNOTIMPLEMENTED; break;
+ } //end of switch
+ // record's declared size must be more than the minimum size for this type of record
+ if(*nSize < rsize){
+ return(0);
+ }
+ return(1);
+}
+
/**
\brief Convert an entire EMF in memory from Big Endian to Little Endian.
@@ -1622,155 +2113,151 @@ int U_emf_endian(char *contents, size_t length, int torev){
uint32_t off;
uint32_t OK, recnum, iType;
char *record;
- PU_ENHMETARECORD pEmr;
+ const char *blimit = contents + length; /* should never wrap since it describes a structure in memory */
+ int rstatus=1;
record = contents;
OK = 1;
off = 0;
recnum = 0;
while(OK){
- if(record > contents + length){ // this is most likely a corrupt EMF
- return(0);
- }
- pEmr = (PU_ENHMETARECORD)(record);
-
- iType = pEmr->iType;
- off = pEmr->nSize;
- if(!torev){
- U_swap4(&iType,1);
- U_swap4(&off,1);
+ if(!U_emf_record_sizeok(record, blimit, &off, &iType, torev)){
+ return(0);
}
switch (iType)
{
- case U_EMR_HEADER: U_EMRHEADER_swap(record, torev); break;
- case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_swap(record, torev); break;
- case U_EMR_POLYGON: U_EMRPOLYGON_swap(record, torev); break;
- case U_EMR_POLYLINE: U_EMRPOLYLINE_swap(record, torev); break;
- case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_swap(record, torev); break;
- case U_EMR_POLYLINETO: U_EMRPOLYLINETO_swap(record, torev); break;
- case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_swap(record, torev); break;
- case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_swap(record, torev); break;
- case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_swap(record, torev); break;
- case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_swap(record, torev); break;
- case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_swap(record, torev); break;
- case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_swap(record, torev); break;
- case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_swap(record, torev); break;
+ case U_EMR_HEADER: rstatus=U_EMRHEADER_swap(record, torev); break;
+ case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_swap(record, torev); break;
+ case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_swap(record, torev); break;
+ case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_swap(record, torev); break;
+ case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_swap(record, torev); break;
+ case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_swap(record, torev); break;
+ case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_swap(record, torev); break;
case U_EMR_EOF:
- U_EMREOF_swap(record, torev);
+ rstatus=U_EMREOF_swap(record, torev);
OK = 0; /* Exit triggered here */
break;
- case U_EMR_SETPIXELV: U_EMRSETPIXELV_swap(record, torev); break;
- case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_swap(record, torev); break;
- case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_swap(record, torev); break;
- case U_EMR_SETBKMODE: U_EMRSETBKMODE_swap(record, torev); break;
- case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_swap(record, torev); break;
- case U_EMR_SETROP2: U_EMRSETROP2_swap(record, torev); break;
- case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_swap(record, torev); break;
- case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_swap(record, torev); break;
- case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_swap(record, torev); break;
- case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_swap(record, torev); break;
- case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_swap(record, torev); break;
- case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_swap(record, torev); break;
- case U_EMR_MOVETOEX: U_EMRMOVETOEX_swap(record, torev); break;
- case U_EMR_SETMETARGN: U_EMRSETMETARGN_swap(record, torev); break;
- case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_swap(record, torev); break;
- case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_swap(record, torev); break;
- case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_swap(record, torev); break;
- case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_swap(record, torev); break;
- case U_EMR_SAVEDC: U_EMRSAVEDC_swap(record, torev); break;
- case U_EMR_RESTOREDC: U_EMRRESTOREDC_swap(record, torev); break;
- case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_swap(record, torev); break;
- case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_swap(record, torev); break;
- case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_swap(record, torev); break;
- case U_EMR_CREATEPEN: U_EMRCREATEPEN_swap(record, torev); break;
- case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_swap(record, torev); break;
- case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_swap(record, torev); break;
- case U_EMR_ANGLEARC: U_EMRANGLEARC_swap(record, torev); break;
- case U_EMR_ELLIPSE: U_EMRELLIPSE_swap(record, torev); break;
- case U_EMR_RECTANGLE: U_EMRRECTANGLE_swap(record, torev); break;
- case U_EMR_ROUNDRECT: U_EMRROUNDRECT_swap(record, torev); break;
- case U_EMR_ARC: U_EMRARC_swap(record, torev); break;
- case U_EMR_CHORD: U_EMRCHORD_swap(record, torev); break;
- case U_EMR_PIE: U_EMRPIE_swap(record, torev); break;
- case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_swap(record, torev); break;
- case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_swap(record, torev); break;
- case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_swap(record, torev); break;
- case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_swap(record, torev); break;
- case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_swap(record, torev); break;
- case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_swap(record, torev); break;
- case U_EMR_LINETO: U_EMRLINETO_swap(record, torev); break;
- case U_EMR_ARCTO: U_EMRARCTO_swap(record, torev); break;
- case U_EMR_POLYDRAW: U_EMRPOLYDRAW_swap(record, torev); break;
- case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_swap(record, torev); break;
- case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_swap(record, torev); break;
- case U_EMR_BEGINPATH: U_EMRBEGINPATH_swap(record, torev); break;
- case U_EMR_ENDPATH: U_EMRENDPATH_swap(record, torev); break;
- case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_swap(record, torev); break;
- case U_EMR_FILLPATH: U_EMRFILLPATH_swap(record, torev); break;
- case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_swap(record, torev); break;
- case U_EMR_STROKEPATH: U_EMRSTROKEPATH_swap(record, torev); break;
- case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_swap(record, torev); break;
- case U_EMR_WIDENPATH: U_EMRWIDENPATH_swap(record, torev); break;
- case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_swap(record, torev); break;
- case U_EMR_ABORTPATH: U_EMRABORTPATH_swap(record, torev); break;
- case U_EMR_UNDEF69: U_EMRUNDEF69_swap(record, torev); break;
- case U_EMR_COMMENT: U_EMRCOMMENT_swap(record, torev); break;
- case U_EMR_FILLRGN: U_EMRFILLRGN_swap(record, torev); break;
- case U_EMR_FRAMERGN: U_EMRFRAMERGN_swap(record, torev); break;
- case U_EMR_INVERTRGN: U_EMRINVERTRGN_swap(record, torev); break;
- case U_EMR_PAINTRGN: U_EMRPAINTRGN_swap(record, torev); break;
- case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_swap(record, torev); break;
- case U_EMR_BITBLT: U_EMRBITBLT_swap(record, torev); break;
- case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_swap(record, torev); break;
- case U_EMR_MASKBLT: U_EMRMASKBLT_swap(record, torev); break;
- case U_EMR_PLGBLT: U_EMRPLGBLT_swap(record, torev); break;
- case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_swap(record, torev); break;
- case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_swap(record, torev); break;
- case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_swap(record, torev); break;
- case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_swap(record, torev); break;
- case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_swap(record, torev); break;
- case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_swap(record, torev); break;
- case U_EMR_POLYGON16: U_EMRPOLYGON16_swap(record, torev); break;
- case U_EMR_POLYLINE16: U_EMRPOLYLINE16_swap(record, torev); break;
- case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_swap(record, torev); break;
- case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_swap(record, torev); break;
- case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_swap(record, torev); break;
- case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_swap(record, torev); break;
- case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_swap(record, torev); break;
- case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_swap(record, torev); break;
- case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_swap(record, torev); break;
- case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_swap(record, torev); break;
- case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_swap(record, torev); break;
- case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_swap(record, torev); break;
- case U_EMR_SETICMMODE: U_EMRSETICMMODE_swap(record, torev); break;
- case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_swap(record, torev); break;
- case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_swap(record, torev); break;
- case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_swap(record, torev); break;
- case U_EMR_GLSRECORD: U_EMRGLSRECORD_swap(record, torev); break;
- case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_swap(record, torev); break;
- case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_swap(record, torev); break;
- case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_swap(record, torev); break;
- case U_EMR_EXTESCAPE: U_EMREXTESCAPE_swap(record, torev); break;
- case U_EMR_UNDEF107: U_EMRUNDEF107_swap(record, torev); break;
- case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_swap(record, torev); break;
- case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_swap(record, torev); break;
- case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_swap(record, torev); break;
- case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_swap(record, torev); break;
- case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_swap(record, torev); break;
- case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_swap(record, torev); break;
- case U_EMR_ALPHABLEND: U_EMRALPHABLEND_swap(record, torev); break;
- case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_swap(record, torev); break;
- case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_swap(record, torev); break;
- case U_EMR_UNDEF117: U_EMRUNDEF117_swap(record, torev); break;
- case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_swap(record, torev); break;
- case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_swap(record, torev); break;
- case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_swap(record, torev); break;
- case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_swap(record, torev); break;
- case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_swap(record, torev); break;
- default: U_EMRNOTIMPLEMENTED_swap(record, torev); break;
+ case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_swap(record, torev); break;
+ case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_swap(record, torev); break;
+ case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_swap(record, torev); break;
+ case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_swap(record, torev); break;
+ case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_swap(record, torev); break;
+ case U_EMR_SETROP2: rstatus=U_EMRSETROP2_swap(record, torev); break;
+ case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_swap(record, torev); break;
+ case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_swap(record, torev); break;
+ case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_swap(record, torev); break;
+ case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_swap(record, torev); break;
+ case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_swap(record, torev); break;
+ case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_swap(record, torev); break;
+ case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_swap(record, torev); break;
+ case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_swap(record, torev); break;
+ case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_swap(record, torev); break;
+ case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_swap(record, torev); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_swap(record, torev); break;
+ case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_swap(record, torev); break;
+ case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_swap(record, torev); break;
+ case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_swap(record, torev); break;
+ case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_swap(record, torev); break;
+ case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_swap(record, torev); break;
+ case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_swap(record, torev); break;
+ case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_swap(record, torev); break;
+ case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_swap(record, torev); break;
+ case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_swap(record, torev); break;
+ case U_EMR_ARC: rstatus=U_EMRARC_swap(record, torev); break;
+ case U_EMR_CHORD: rstatus=U_EMRCHORD_swap(record, torev); break;
+ case U_EMR_PIE: rstatus=U_EMRPIE_swap(record, torev); break;
+ case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_swap(record, torev); break;
+ case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_swap(record, torev); break;
+ case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_swap(record, torev); break;
+ case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_swap(record, torev); break;
+ case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_swap(record, torev); break;
+ case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_swap(record, torev); break;
+ case U_EMR_LINETO: rstatus=U_EMRLINETO_swap(record, torev); break;
+ case U_EMR_ARCTO: rstatus=U_EMRARCTO_swap(record, torev); break;
+ case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_swap(record, torev); break;
+ case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_swap(record, torev); break;
+ case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_swap(record, torev); break;
+ case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_swap(record, torev); break;
+ case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_swap(record, torev); break;
+ case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_swap(record, torev); break;
+ case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_swap(record, torev); break;
+ case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_swap(record, torev); break;
+ case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_swap(record, torev); break;
+ case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_swap(record, torev); break;
+ case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_swap(record, torev); break;
+ case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_swap(record, torev); break;
+ case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_swap(record, torev); break;
+ case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_swap(record, torev); break;
+ case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_swap(record, torev); break;
+ case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_swap(record, torev); break;
+ case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_swap(record, torev); break;
+ case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_swap(record, torev);break;
+ case U_EMR_BITBLT: rstatus=U_EMRBITBLT_swap(record, torev); break;
+ case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_swap(record, torev); break;
+ case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_swap(record, torev); break;
+ case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_swap(record, torev); break;
+ case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_swap(record, torev); break;
+ case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_swap(record, torev); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_swap(record, torev); break;
+ case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_swap(record, torev); break;
+ case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_swap(record, torev); break;
+ case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_swap(record, torev); break;
+ case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_swap(record, torev); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_swap(record, torev); break;
+ case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_swap(record, torev); break;
+ case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_swap(record, torev); break;
+ case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_swap(record, torev); break;
+ case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_swap(record, torev); break;
+ case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_swap(record, torev); break;
+ case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_swap(record, torev); break;
+ case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_swap(record, torev); break;
+ case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_swap(record, torev); break;
+ case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_swap(record, torev); break;
+ case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_swap(record, torev); break;
+ case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_swap(record, torev); break;
+ case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_swap(record, torev); break;
+ case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_swap(record, torev); break;
+ case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_swap(record, torev); break;
+ case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_swap(record, torev); break;
+ case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_swap(record, torev); break;
+ case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_swap(record, torev); break;
+ case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_swap(record, torev); break;
+ case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_swap(record, torev); break;
+ case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_swap(record, torev); break;
+ case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_swap(record, torev); break;
+ case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_swap(record, torev); break;
+ default: rstatus=U_EMRNOTIMPLEMENTED_swap(record, torev); break;
} //end of switch
+ if(!rstatus){
+ return(rstatus);
+ }
record += off;
recnum++;
} //end of while
diff --git a/src/libuemf/uemf_endian.h b/src/libuemf/uemf_endian.h
index 317968c34..9dbcec455 100644
--- a/src/libuemf/uemf_endian.h
+++ b/src/libuemf/uemf_endian.h
@@ -6,11 +6,11 @@
/*
File: uemf_endian.h
-Version: 0.0.3
-Date: 24-JUL-2012
+Version: 0.0.4
+Date: 24-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifndef _UEMF_ENDIAN_
@@ -49,6 +49,7 @@ extern "C" {
//! \cond
// prototypes
int U_emf_endian(char *contents, size_t length, int torev);
+int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev);
//! \endcond
#ifdef __cplusplus
diff --git a/src/libuemf/uemf_print.c b/src/libuemf/uemf_print.c
index aa574bd73..adcf54c0f 100644
--- a/src/libuemf/uemf_print.c
+++ b/src/libuemf/uemf_print.c
@@ -6,11 +6,11 @@
/*
File: uemf_print.c
-Version: 0.0.15
-Date: 17-OCT-2013
+Version: 0.0.18
+Date: 25-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2013 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
@@ -23,9 +23,12 @@ extern "C" {
#include <string.h>
#include "uemf.h"
#include "upmf_print.h"
+#include "uemf_safe.h"
//! \cond
#define UNUSED(x) (void)(x)
+/* This bit of code is used all over the place, so reduce it to a DEFINITION */
+#define IF_MEM_UNSAFE_PRINT_AND_RETURN(A,B,C) if(IS_MEM_UNSAFE(A,B,C)){printf(" record corruption HERE\n"); return; }
/* one needed prototype */
void U_swap4(void *ul, unsigned int count);
@@ -364,24 +367,28 @@ int bitmapinfoheader_print(
/**
\brief Print a Pointer to a U_BITMAPINFO object.
\param Bmi Pointer to a U_BITMAPINFO object
+ \param blimit Pointer to the first byte after after this record
This may be called from WMF _print routines, where problems could occur
if the data was passed as the struct or a pointer to the struct, as the struct may not
be aligned in memory.
*/
void bitmapinfo_print(
- const char *Bmi
+ const char *Bmi,
+ const char *blimit
){
int i,k;
int ClrUsed;
U_RGBQUAD BmiColor;
printf("BmiHeader: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit);
ClrUsed = bitmapinfoheader_print(Bmi + offsetof(U_BITMAPINFO,bmiHeader));
if(ClrUsed){
- k= offsetof(U_BITMAPINFO,bmiColors);
- for(i=0; i<ClrUsed; i++, k+= sizeof(U_RGBQUAD)){
- memcpy(&BmiColor, Bmi+k, sizeof(U_RGBQUAD));
- printf("%d:",i); rgbquad_print(BmiColor);
- }
+ k= offsetof(U_BITMAPINFO,bmiColors);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit);
+ for(i=0; i<ClrUsed; i++, k+= sizeof(U_RGBQUAD)){
+ memcpy(&BmiColor, Bmi+k, sizeof(U_RGBQUAD));
+ printf("%d:",i); rgbquad_print(BmiColor);
+ }
}
}
@@ -484,15 +491,19 @@ void rgndataheader_print(
/**
\brief Print a pointer to a U_RGNDATA object.
\param rd pointer to a U_RGNDATA object.
+ \param limit pointer that sets upper limit for data examination
*/
void rgndata_print(
- PU_RGNDATA rd
+ PU_RGNDATA rd,
+ const char *blimit
){
unsigned int i;
PU_RECTL rects;
- printf("rdh:"); rgndataheader_print(rd->rdh );
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(rd, sizeof(U_RGNDATAHEADER), blimit);
+ printf("rdh: "); rgndataheader_print(rd->rdh ); printf(" rects: ");
if(rd->rdh.nCount){
rects = (PU_RECTL) &(rd->Buffer);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(rects, rd->rdh.nCount * sizeof(U_RECTL), blimit);
for(i=0;i<rd->rdh.nCount;i++){
printf("%d:",i); rectl_print(rects[i]);
}
@@ -559,11 +570,13 @@ void pixelformatdescriptor_print(
\brief Print a Pointer to a U_EMRTEXT record
\param emt Pointer to a U_EMRTEXT record
\param record Pointer to the start of the record which contains this U_ERMTEXT
+ \param blimit Pointer to the first byte after after this record
\param type 0 for 8 bit character, anything else for 16
*/
void emrtext_print(
const char *emt,
const char *record,
+ const char *blimit,
int type
){
unsigned int i,off;
@@ -575,9 +588,11 @@ void emrtext_print(
printf("offString:%u " ,pemt->offString );
if(pemt->offString){
if(!type){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*sizeof(char), blimit);
printf("string8:<%s> ",record + pemt->offString);
}
else {
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*2*sizeof(char), blimit);
string = U_Utf16leToUtf8((uint16_t *)(record + pemt->offString), pemt->nChars, NULL);
printf("string16:<%s> ",string);
free(string);
@@ -622,9 +637,15 @@ void core1_print(const char *name, const char *contents){
unsigned int i;
UNUSED(name);
PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" cptl: %d\n",pEmr->cptl );
printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit);
for(i=0;i<pEmr->cptl; i++){
printf("[%d]:",i); pointl_print(pEmr->aptl[i]);
}
@@ -636,16 +657,23 @@ void core2_print(const char *name, const char *contents){
unsigned int i;
UNUSED(name);
PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYGON)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" nPolys: %d\n",pEmr->nPolys );
printf(" cptl: %d\n",pEmr->cptl );
printf(" Counts: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aPolyCounts, pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit);
for(i=0;i<pEmr->nPolys; i++){
printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] );
}
printf("\n");
PU_POINTL paptl = (PU_POINTL)((char *)pEmr->aPolyCounts + sizeof(uint32_t)* pEmr->nPolys);
printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(paptl, pEmr->cptl*sizeof(U_POINTL), blimit);
for(i=0;i<pEmr->cptl; i++){
printf(" [%d]:",i); pointl_print(paptl[i]);
}
@@ -656,7 +684,12 @@ void core2_print(const char *name, const char *contents){
// Functions with the same form starting with U_EMRSETMAPMODE_print
void core3_print(const char *name, const char *label, const char *contents){
UNUSED(name);
+ /* access violation is impossible for these because there are no counts or offsets */
PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETMAPMODE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
if(!strcmp(label,"crColor:")){
printf(" %-15s ",label); colorref_print(*(U_COLORREF *)&(pEmr->iMode)); printf("\n");
}
@@ -672,6 +705,10 @@ void core3_print(const char *name, const char *label, const char *contents){
void core4_print(const char *name, const char *contents){
UNUSED(name);
PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRELLIPSE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n");
}
@@ -680,10 +717,16 @@ void core6_print(const char *name, const char *contents){
UNUSED(name);
unsigned int i;
PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" cpts: %d\n",pEmr->cpts );
printf(" Points: ");
PU_POINT16 papts = (PU_POINT16)(&(pEmr->apts));
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit);
for(i=0; i<pEmr->cpts; i++){
printf(" [%d]:",i); point16_print(papts[i]);
}
@@ -698,6 +741,10 @@ void core6_print(const char *name, const char *contents){
void core7_print(const char *name, const char *field1, const char *field2, const char *contents){
UNUSED(name);
PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRGENERICPAIR)){
+ printf(" record corruption HERE\n");
+ return;
+ }
if(*field2){
printf(" %-15s %d\n",field1,pEmr->pair.x);
printf(" %-15s %d\n",field2,pEmr->pair.y);
@@ -711,12 +758,13 @@ void core7_print(const char *name, const char *field1, const char *field2, const
void core8_print(const char *name, const char *contents, int type){
UNUSED(name);
PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents);
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" iGraphicsMode: %u\n",pEmr->iGraphicsMode );
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" exScale: %f\n",pEmr->exScale );
printf(" eyScale: %f\n",pEmr->eyScale );
printf(" emrtext: ");
- emrtext_print(contents + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents,type);
+ emrtext_print(contents + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents,blimit,type);
printf("\n");
}
@@ -724,6 +772,10 @@ void core8_print(const char *name, const char *contents, int type){
void core9_print(const char *name, const char *contents){
UNUSED(name);
PU_EMRARC pEmr = (PU_EMRARC) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRARC)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n");
printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n");
printf(" ptlEnd: "); pointl_print(pEmr->ptlEnd); printf("\n");
@@ -734,16 +786,23 @@ void core10_print(const char *name, const char *contents){
UNUSED(name);
unsigned int i;
PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYLINE16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" nPolys: %d\n",pEmr->nPolys );
printf(" cpts: %d\n",pEmr->cpts );
printf(" Counts: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->aPolyCounts), pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit);
for(i=0;i<pEmr->nPolys; i++){
printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] );
}
printf("\n");
printf(" Points: ");
- PU_POINT16 papts = (PU_POINT16)((char *)pEmr->aPolyCounts + sizeof(uint32_t)* pEmr->nPolys);
+ PU_POINT16 papts = (PU_POINT16)((char *)pEmr->aPolyCounts + pEmr->nPolys*sizeof(U_POLYCOUNTS) );
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit);
for(i=0; i<pEmr->cpts; i++){
printf(" [%d]:",i); point16_print(papts[i]);
}
@@ -754,20 +813,18 @@ void core10_print(const char *name, const char *contents){
// Functions with the same form starting with U_EMRINVERTRGN_print and U_EMRPAINTRGN_print,
void core11_print(const char *name, const char *contents){
UNUSED(name);
- unsigned int i,roff;
PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRINVERTRGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" cbRgnData: %d\n",pEmr->cbRgnData);
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- roff=0;
- i=1;
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + sizeof(U_RGNDATAHEADER) < pEmr->cbRgnData){ // stop at end of the record 4*4 = header + 4*4=rect
- printf(" RegionData:%d",i);
- rgndata_print((PU_RGNDATA) (prd + roff));
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- printf("\n");
- }
+ printf(" RegionData:");
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ rgndata_print(pEmr->RgnData, minptr);
+ printf("\n");
}
@@ -775,13 +832,18 @@ void core11_print(const char *name, const char *contents){
void core12_print(const char *name, const char *contents){
UNUSED(name);
PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEMONOBRUSH)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" ihBrush: %u\n",pEmr->ihBrush );
printf(" iUsage : %u\n",pEmr->iUsage );
printf(" offBmi : %u\n",pEmr->offBmi );
printf(" cbBmi : %u\n",pEmr->cbBmi );
if(pEmr->cbBmi){
printf(" bitmap:");
- bitmapinfo_print(contents + pEmr->offBmi);
+ bitmapinfo_print(contents + pEmr->offBmi, blimit);
printf("\n");
}
printf(" offBits: %u\n",pEmr->offBits );
@@ -792,6 +854,11 @@ void core12_print(const char *name, const char *contents){
void core13_print(const char *name, const char *contents){
UNUSED(name);
PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRALPHABLEND)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
@@ -804,7 +871,7 @@ void core13_print(const char *name, const char *contents){
printf(" cbBmiSrc: %u\n",pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" bitmap:");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n",pEmr->offBitsSrc );
@@ -839,6 +906,11 @@ void U_EMRHEADER_print(const char *contents){
int p1len;
PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRHEADER)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" rclFrame: "); rectl_print( pEmr->rclFrame); printf("\n");
printf(" dSignature: 0x%8.8X\n", pEmr->dSignature );
@@ -850,6 +922,7 @@ void U_EMRHEADER_print(const char *contents){
printf(" nDescription: %d\n", pEmr->nDescription );
printf(" offDescription: %d\n", pEmr->offDescription);
if(pEmr->offDescription){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offDescription + pEmr->nDescription*2*sizeof(char), blimit);
string = U_Utf16leToUtf8((uint16_t *)((char *) pEmr + pEmr->offDescription), pEmr->nDescription, NULL);
printf(" Desc. A: %s\n",string);
free(string);
@@ -868,6 +941,7 @@ void U_EMRHEADER_print(const char *contents){
printf(" offPixelFormat: %d\n", pEmr->offPixelFormat);
if(pEmr->cbPixelFormat){
printf(" PFD:");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offPixelFormat + sizeof(U_PIXELFORMATDESCRIPTOR), blimit);
pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + pEmr->offPixelFormat));
printf("\n");
}
@@ -997,6 +1071,10 @@ void U_EMRSETBRUSHORGEX_print(const char *contents){
*/
void U_EMREOF_print(const char *contents){
PU_EMREOF pEmr = (PU_EMREOF)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREOF)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" cbPalEntries: %u\n", pEmr->cbPalEntries );
printf(" offPalEntries: %u\n", pEmr->offPalEntries);
if(pEmr->cbPalEntries){
@@ -1014,6 +1092,10 @@ void U_EMREOF_print(const char *contents){
*/
void U_EMRSETPIXELV_print(const char *contents){
PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETPIXELV)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ptlPixel: "); pointl_print( pEmr->ptlPixel); printf("\n");
printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n");
}
@@ -1026,6 +1108,10 @@ void U_EMRSETPIXELV_print(const char *contents){
*/
void U_EMRSETMAPPERFLAGS_print(const char *contents){
PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETMAPPERFLAGS)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" dwFlags: 0x%8.8X\n",pEmr->dwFlags);
}
@@ -1091,6 +1177,10 @@ void U_EMRSETTEXTALIGN_print(const char *contents){
*/
void U_EMRSETCOLORADJUSTMENT_print(const char *contents){
PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETCOLORADJUSTMENT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ColorAdjustment:");
coloradjustment_print(pEmr->ColorAdjustment);
printf("\n");
@@ -1203,6 +1293,10 @@ void U_EMRRESTOREDC_print(const char *contents){
*/
void U_EMRSETWORLDTRANSFORM_print(const char *contents){
PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETWORLDTRANSFORM)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" xform:");
xform_print(pEmr->xform);
printf("\n");
@@ -1215,6 +1309,10 @@ void U_EMRSETWORLDTRANSFORM_print(const char *contents){
*/
void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents){
PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRMODIFYWORLDTRANSFORM)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" xform:");
xform_print(pEmr->xform);
printf("\n");
@@ -1228,6 +1326,10 @@ void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents){
*/
void U_EMRSELECTOBJECT_print(const char *contents){
PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSELECTOBJECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
if(pEmr->ihObject & U_STOCK_OBJECT){
printf(" StockObject: 0x%8.8X\n", pEmr->ihObject );
}
@@ -1243,6 +1345,10 @@ void U_EMRSELECTOBJECT_print(const char *contents){
*/
void U_EMRCREATEPEN_print(const char *contents){
PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEPEN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ihPen: %u\n", pEmr->ihPen );
printf(" lopn: "); logpen_print(pEmr->lopn); printf("\n");
}
@@ -1254,6 +1360,10 @@ void U_EMRCREATEPEN_print(const char *contents){
*/
void U_EMRCREATEBRUSHINDIRECT_print(const char *contents){
PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEBRUSHINDIRECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ihBrush: %u\n", pEmr->ihBrush );
printf(" lb: "); logbrush_print(pEmr->lb); printf("\n");
}
@@ -1265,6 +1375,10 @@ void U_EMRCREATEBRUSHINDIRECT_print(const char *contents){
*/
void U_EMRDELETEOBJECT_print(const char *contents){
PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRDELETEOBJECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ihObject: %u\n", pEmr->ihObject );
}
@@ -1275,6 +1389,10 @@ void U_EMRDELETEOBJECT_print(const char *contents){
*/
void U_EMRANGLEARC_print(const char *contents){
PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRANGLEARC)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ptlCenter: "), pointl_print(pEmr->ptlCenter ); printf("\n");
printf(" nRadius: %u\n", pEmr->nRadius );
printf(" eStartAngle: %f\n", pEmr->eStartAngle );
@@ -1306,6 +1424,10 @@ void U_EMRRECTANGLE_print(const char *contents){
*/
void U_EMRROUNDRECT_print(const char *contents){
PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRROUNDRECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" rclBox: "), rectl_print(pEmr->rclBox ); printf("\n");
printf(" szlCorner: "), sizel_print(pEmr->szlCorner ); printf("\n");
}
@@ -1353,6 +1475,10 @@ void U_EMRSELECTPALETTE_print(const char *contents){
*/
void U_EMRCREATEPALETTE_print(const char *contents){
PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEPALETTE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ihPal: %u\n",pEmr->ihPal);
printf(" lgpl: "), logpalette_print( (PU_LOGPALETTE)&(pEmr->lgpl) ); printf("\n");
}
@@ -1365,12 +1491,18 @@ void U_EMRCREATEPALETTE_print(const char *contents){
void U_EMRSETPALETTEENTRIES_print(const char *contents){
unsigned int i;
PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETPALETTEENTRIES)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" ihPal: %u\n",pEmr->ihPal);
printf(" iStart: %u\n",pEmr->iStart);
printf(" cEntries: %u\n",pEmr->cEntries);
if(pEmr->cEntries){
printf(" PLTEntries:");
PU_LOGPLTNTRY aPalEntries = (PU_LOGPLTNTRY) &(pEmr->aPalEntries);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(aPalEntries, pEmr->cEntries*sizeof(U_LOGPLTNTRY), blimit);
for(i=0; i<pEmr->cEntries; i++){
printf("%d:",i); logpltntry_print(aPalEntries[i]);
}
@@ -1403,6 +1535,10 @@ void U_EMRREALIZEPALETTE_print(const char *contents){
*/
void U_EMREXTFLOODFILL_print(const char *contents){
PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREXTFLOODFILL)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n");
printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n");
printf(" iMode: %u\n",pEmr->iMode);
@@ -1434,17 +1570,25 @@ void U_EMRARCTO_print(const char *contents){
void U_EMRPOLYDRAW_print(const char *contents){
unsigned int i;
PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" cptl: %d\n",pEmr->cptl );
printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit);
for(i=0;i<pEmr->cptl; i++){
printf(" [%d]:",i);
pointl_print(pEmr->aptl[i]);
}
printf("\n");
printf(" Types: ");
+ const char *abTypes = (const char *) pEmr->aptl + pEmr->cptl*sizeof(U_POINTL);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cptl, blimit);
for(i=0;i<pEmr->cptl; i++){
- printf(" [%d]:%u ",i,pEmr->abTypes[i]);
+ printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]);
}
printf("\n");
}
@@ -1565,12 +1709,11 @@ void U_EMRABORTPATH_print(const char *contents){
/**
\brief Print a pointer to a U_EMR_COMMENT record.
\param contents pointer to a location in memory holding the comment record
- \param blimit size in bytes of the comment record
- \param off offset in bytes to the first byte in this record
+ \param off offset in bytes to the first byte in this record (needed for EMF+ record printing)
EMF+ records, if any, are stored in EMF comment records.
*/
-void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off){
+void U_EMRCOMMENT_print(const char *contents, size_t off){
char *string;
char *src;
uint32_t cIdent,cIdent2,cbData;
@@ -1579,21 +1722,30 @@ void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off){
static int recnum=0;
PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCOMMENT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
/* There are several different types of comments */
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT), blimit);
cbData = pEmr->cbData;
printf(" cbData: %d\n",cbData );
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMR) + sizeof(U_CBDATA) + cbData, blimit);
src = (char *)&(pEmr->Data); // default
if(cbData >= 4){
/* Since the comment is just a big bag of bytes the emf endian code cannot safely touch
- any of its payload. This is the only record type with that limitation. Try to determine
+ any of its payload. This is the only record type with that limitation. So the record
+ may appear at this stage with the wrong endianness. Try to determine
what the contents are even if more byte swapping is required. */
cIdent = *(uint32_t *)(src);
if(U_BYTE_SWAP){ U_swap4(&(cIdent),1); }
if( cIdent == U_EMR_COMMENT_PUBLIC ){
printf(" cIdent: Public\n");
PU_EMRCOMMENT_PUBLIC pEmrp = (PU_EMRCOMMENT_PUBLIC) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_PUBLIC), blimit);
cIdent2 = pEmrp->pcIdent;
if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); }
printf(" pcIdent: 0x%8.8x\n",cIdent2);
@@ -1603,6 +1755,7 @@ void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off){
else if(cIdent == U_EMR_COMMENT_SPOOL ){
printf(" cIdent: Spool\n");
PU_EMRCOMMENT_SPOOL pEmrs = (PU_EMRCOMMENT_SPOOL) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_SPOOL), blimit);
cIdent2 = pEmrs->esrIdent;
if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); }
printf(" esrIdent: 0x%8.8x\n",cIdent2);
@@ -1612,11 +1765,16 @@ void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off){
else if(cIdent == U_EMR_COMMENT_EMFPLUSRECORD){
printf(" cIdent: EMF+\n");
PU_EMRCOMMENT_EMFPLUS pEmrpl = (PU_EMRCOMMENT_EMFPLUS) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_EMFPLUS), blimit);
src = (char *)&(pEmrpl->Data);
loff = 16; /* Header size of the header part of an EMF+ comment record */
while(loff < cbData + 12){ // EMF+ records may not fill the entire comment, cbData value includes cIdent, but not U_EMR or cbData
recsize = U_pmf_onerec_print(src, blimit, recnum, loff + off);
- if(recsize<=0)break;
+ if(recsize==0){ break; }
+ else if(recsize<0){
+ printf(" record corruption HERE\n");
+ return;
+ }
loff += recsize;
src += recsize;
recnum++;
@@ -1642,19 +1800,17 @@ void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off){
\param contents pointer to a buffer holding all EMR records
*/
void U_EMRFILLRGN_print(const char *contents){
- int i,roff;
PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRFILLRGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" cbRgnData: %u\n",pEmr->cbRgnData);
printf(" ihBrush: %u\n",pEmr->ihBrush);
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- roff=0;
- i=1;
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + sizeof(U_RGNDATAHEADER) < pEmr->emr.nSize){ // up to the end of the record
- printf(" RegionData[%d]: ",i); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData + sizeof(U_RGNDATAHEADER)),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
}
// U_EMRFRAMERGN 72
@@ -1663,20 +1819,18 @@ void U_EMRFILLRGN_print(const char *contents){
\param contents pointer to a buffer holding all EMR records
*/
void U_EMRFRAMERGN_print(const char *contents){
- int i,roff;
PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRFRAMERGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
printf(" cbRgnData: %u\n",pEmr->cbRgnData);
printf(" ihBrush: %u\n",pEmr->ihBrush);
printf(" szlStroke: "), sizel_print(pEmr->szlStroke ); printf("\n");
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- roff=0;
- i=1;
- char *prd = (char *) &(pEmr->RgnData);
- while(roff + sizeof(U_RGNDATAHEADER) < pEmr->emr.nSize){ // up to the end of the record
- printf(" RegionData[%d]: ",i); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
}
// U_EMRINVERTRGN 73
@@ -1703,17 +1857,16 @@ void U_EMRPAINTRGN_print(const char *contents){
\param contents pointer to a buffer holding all EMR records
*/
void U_EMREXTSELECTCLIPRGN_print(const char *contents){
- int i,roff;
PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREXTSELECTCLIPRGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" cbRgnData: %u\n",pEmr->cbRgnData);
printf(" iMode: %u\n",pEmr->iMode);
- // This one is a pain since each RGNDATA may be a different size, so it isn't possible to index through them.
- char *prd = (char *) &(pEmr->RgnData);
- i=roff=0;
- while(roff + sizeof(U_RGNDATAHEADER) < pEmr->cbRgnData){ // stop at end of the record 4*4 = header + 4*4=rect
- printf(" RegionData[%d]: ",i++); rgndata_print((PU_RGNDATA) (prd + roff)); printf("\n");
- roff += (((PU_RGNDATA)prd)->rdh.dwSize + ((PU_RGNDATA)prd)->rdh.nRgnSize - 16);
- }
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
}
// U_EMRBITBLT 76
@@ -1723,6 +1876,11 @@ void U_EMREXTSELECTCLIPRGN_print(const char *contents){
*/
void U_EMRBITBLT_print(const char *contents){
PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRBITBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
@@ -1735,7 +1893,7 @@ void U_EMRBITBLT_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1749,6 +1907,11 @@ void U_EMRBITBLT_print(const char *contents){
*/
void U_EMRSTRETCHBLT_print(const char *contents){
PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
@@ -1761,7 +1924,7 @@ void U_EMRSTRETCHBLT_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1776,6 +1939,11 @@ void U_EMRSTRETCHBLT_print(const char *contents){
*/
void U_EMRMASKBLT_print(const char *contents){
PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRMASKBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
@@ -1788,7 +1956,7 @@ void U_EMRMASKBLT_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" Src bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1799,7 +1967,7 @@ void U_EMRMASKBLT_print(const char *contents){
printf(" cbBmiMask: %u\n", pEmr->cbBmiMask );
if(pEmr->cbBmiMask){
printf(" Mask bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiMask);
+ bitmapinfo_print(contents + pEmr->offBmiMask, blimit);
printf("\n");
}
printf(" offBitsMask: %u\n", pEmr->offBitsMask );
@@ -1813,6 +1981,11 @@ void U_EMRMASKBLT_print(const char *contents){
*/
void U_EMRPLGBLT_print(const char *contents){
PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPLGBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" aptlDst(UL): "); pointl_print(pEmr->aptlDst[0]); printf("\n");
printf(" aptlDst(UR): "); pointl_print(pEmr->aptlDst[1]); printf("\n");
@@ -1826,7 +1999,7 @@ void U_EMRPLGBLT_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" Src bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1837,7 +2010,7 @@ void U_EMRPLGBLT_print(const char *contents){
printf(" cbBmiMask: %u\n", pEmr->cbBmiMask );
if(pEmr->cbBmiMask){
printf(" Mask bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiMask);
+ bitmapinfo_print(contents + pEmr->offBmiMask, blimit);
printf("\n");
}
printf(" offBitsMask: %u\n", pEmr->offBitsMask );
@@ -1851,6 +2024,11 @@ void U_EMRPLGBLT_print(const char *contents){
*/
void U_EMRSETDIBITSTODEVICE_print(const char *contents){
PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETDIBITSTODEVICE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
@@ -1859,7 +2037,7 @@ void U_EMRSETDIBITSTODEVICE_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" Src bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1876,6 +2054,11 @@ void U_EMRSETDIBITSTODEVICE_print(const char *contents){
*/
void U_EMRSTRETCHDIBITS_print(const char *contents){
PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHDIBITS)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
@@ -1884,7 +2067,7 @@ void U_EMRSTRETCHDIBITS_print(const char *contents){
printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
if(pEmr->cbBmiSrc){
printf(" Src bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmiSrc);
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
printf("\n");
}
printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
@@ -1901,12 +2084,19 @@ void U_EMRSTRETCHDIBITS_print(const char *contents){
*/
void U_EMREXTCREATEFONTINDIRECTW_print(const char *contents){
PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents);
+ if(pEmr->emr.nSize < U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT){ // smallest variant
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" ihFont: %u\n",pEmr->ihFont );
printf(" Font: ");
- if(pEmr->emr.nSize == sizeof(U_EMREXTCREATEFONTINDIRECTW)){ // holds logfont_panose
+ if(pEmr->emr.nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){ // holds logfont_panose
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_PANOSE), blimit);
logfont_panose_print(pEmr->elfw);
}
- else { // holds logfont
+ else { // holds logfont or logfontExDv. The latter isn't supported but it starts with logfont, so use that
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_LOGFONT), blimit);
logfont_print( *(PU_LOGFONT) &(pEmr->elfw));
}
printf("\n");
@@ -2002,17 +2192,25 @@ void U_EMRPOLYPOLYGON16_print(const char *contents){
void U_EMRPOLYDRAW16_print(const char *contents){
unsigned int i;
PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" cpts: %d\n",pEmr->cpts );
printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->apts, pEmr->cpts*sizeof(U_POINT16), blimit);
for(i=0;i<pEmr->cpts; i++){
printf(" [%d]:",i);
point16_print(pEmr->apts[i]);
}
printf("\n");
printf(" Types: ");
+ const char *abTypes = (const char *) pEmr->apts + pEmr->cpts*sizeof(U_POINT16);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cpts, blimit);
for(i=0;i<pEmr->cpts; i++){
- printf(" [%d]:%u ",i,pEmr->abTypes[i]);
+ printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]);
}
printf("\n");
}
@@ -2043,12 +2241,17 @@ void U_EMRCREATEDIBPATTERNBRUSHPT_print(const char *contents){
*/
void U_EMREXTCREATEPEN_print(const char *contents){
PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREXTCREATEPEN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" ihPen: %u\n", pEmr->ihPen );
printf(" offBmi: %u\n", pEmr->offBmi );
printf(" cbBmi: %u\n", pEmr->cbBmi );
if(pEmr->cbBmi){
printf(" bitmap: ");
- bitmapinfo_print(contents + pEmr->offBmi);
+ bitmapinfo_print(contents + pEmr->offBmi, blimit);
printf("\n");
}
printf(" offBits: %u\n", pEmr->offBits );
@@ -2077,6 +2280,10 @@ void U_EMRSETICMMODE_print(const char *contents){
*/
void U_EMRCREATECOLORSPACE_print(const char *contents){
PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
printf(" ihCS: %u\n", pEmr->ihCS );
printf(" ColorSpace: "); logcolorspacea_print(pEmr->lcs); printf("\n");
}
@@ -2111,6 +2318,12 @@ void U_EMRDELETECOLORSPACE_print(const char *contents){
*/
void U_EMRPIXELFORMAT_print(const char *contents){
PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPIXELFORMAT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->pfd), sizeof(U_PIXELFORMATDESCRIPTOR), blimit);
printf(" Pfd: "); pixelformatdescriptor_print(pEmr->pfd); printf("\n");
}
@@ -2130,6 +2343,11 @@ void U_EMRSMALLTEXTOUT_print(const char *contents){
int roff;
char *string;
PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSMALLTEXTOUT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
printf(" cChars: %u\n", pEmr->cChars );
printf(" fuOptions: 0x%8.8X\n", pEmr->fuOptions );
@@ -2138,14 +2356,17 @@ void U_EMRSMALLTEXTOUT_print(const char *contents){
printf(" eyScale: %f\n", pEmr->eyScale );
roff = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields
if(!(pEmr->fuOptions & U_ETO_NO_RECT)){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff, blimit);
printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + roff)); printf("\n");
roff += sizeof(U_RECTL);
}
if(pEmr->fuOptions & U_ETO_SMALL_CHARS){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*sizeof(char), blimit);
printf(" Text8: <%.*s>\n",pEmr->cChars,contents+roff); /* May not be null terminated */
}
else {
string = U_Utf16leToUtf8((uint16_t *)(contents+roff), pEmr->cChars, NULL);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*2*sizeof(char), blimit);
printf(" Text16: <%s>\n",contents+roff);
free(string);
}
@@ -2199,12 +2420,18 @@ void U_EMRTRANSPARENTBLT_print(const char *contents){
void U_EMRGRADIENTFILL_print(const char *contents){
unsigned int i;
PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRGRADIENTFILL)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
printf(" nTriVert: %u\n", pEmr->nTriVert );
printf(" nGradObj: %u\n", pEmr->nGradObj );
printf(" ulMode: %u\n", pEmr->ulMode );
contents += sizeof(U_EMRGRADIENTFILL);
if(pEmr->nTriVert){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nTriVert*sizeof(U_TRIVERTEX), blimit);
printf(" TriVert: ");
for(i=0; i<pEmr->nTriVert; i++, contents+=sizeof(U_TRIVERTEX)){
trivertex_print(*(PU_TRIVERTEX)(contents));
@@ -2214,12 +2441,14 @@ void U_EMRGRADIENTFILL_print(const char *contents){
if(pEmr->nGradObj){
printf(" GradObj: ");
if( pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT3), blimit);
for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT3)){
gradient3_print(*(PU_GRADIENT3)(contents));
}
}
else if(pEmr->ulMode == U_GRADIENT_FILL_RECT_H ||
pEmr->ulMode == U_GRADIENT_FILL_RECT_V){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT4), blimit);
for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT4)){
gradient4_print(*(PU_GRADIENT4)(contents));
}
@@ -2244,12 +2473,18 @@ void U_EMRGRADIENTFILL_print(const char *contents){
void U_EMRCREATECOLORSPACEW_print(const char *contents){
unsigned int i;
PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACEW)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
printf(" ihCS: %u\n", pEmr->ihCS );
printf(" ColorSpace: "); logcolorspacew_print(pEmr->lcs); printf("\n");
printf(" dwFlags: 0x%8.8X\n", pEmr->dwFlags );
printf(" cbData: %u\n", pEmr->cbData );
printf(" Data(hexvalues):");
if(pEmr->dwFlags & 1){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->cbData, blimit);
for(i=0; i<pEmr->cbData; i++){
printf("[%d]:%2.2X ",i,pEmr->Data[i]);
}
@@ -2267,145 +2502,154 @@ void U_EMRCREATECOLORSPACEW_print(const char *contents){
*/
int U_emf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off){
PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off);
- unsigned int size;
-
- printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d\n",U_emr_names(lpEMFR->iType),recnum,lpEMFR->iType,(int) off,lpEMFR->nSize);
- size = lpEMFR->nSize;
- contents += off;
+ uint32_t nSize;
+ uint32_t iType;
+ const char *record = contents + off;
- /* Check that the record size is OK, abort if not.
- Pointer math might wrap, so check both sides of the range */
- if(size < sizeof(U_EMR) ||
- contents + size - 1 >= blimit ||
- contents + size - 1 < contents)return(-1);
+ if(record < contents)return(-1); // offset wrapped
+ /* Check that COMMON data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range.
+ */
+ if(!U_emf_record_sizeok(record, blimit, &nSize, &iType, 1))return(-1);
+
+ printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d\n",U_emr_names(iType),recnum,iType,(int) off,nSize);
+ fflush(stdout);
+
+ /* print the record header before checking further.
+ Note if this is a corrupt record, but continue anyway.
+ The _print routines will stop at the actual problem and print another corrupt message.
+ */
+ if(!U_emf_record_safe(record)){printf("WARNING: Corrupt record. Emitting fields above the problem.\n");}
+
switch (lpEMFR->iType)
{
- case U_EMR_HEADER: U_EMRHEADER_print(contents); break;
- case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(contents); break;
- case U_EMR_POLYGON: U_EMRPOLYGON_print(contents); break;
- case U_EMR_POLYLINE: U_EMRPOLYLINE_print(contents); break;
- case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(contents); break;
- case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(contents); break;
- case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(contents); break;
- case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(contents); break;
- case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(contents); break;
- case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(contents); break;
- case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(contents); break;
- case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(contents); break;
- case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(contents); break;
- case U_EMR_EOF: U_EMREOF_print(contents); size=0; break;
- case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(contents); break;
- case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(contents); break;
- case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(contents); break;
- case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(contents); break;
- case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(contents); break;
- case U_EMR_SETROP2: U_EMRSETROP2_print(contents); break;
- case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(contents); break;
- case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(contents); break;
- case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(contents); break;
- case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(contents); break;
- case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(contents); break;
- case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(contents); break;
- case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(contents); break;
- case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(contents); break;
- case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(contents); break;
- case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(contents); break;
- case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(contents); break;
- case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(contents); break;
- case U_EMR_SAVEDC: U_EMRSAVEDC_print(contents); break;
- case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(contents); break;
- case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(contents); break;
- case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(contents); break;
- case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(contents); break;
- case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(contents); break;
- case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(contents); break;
- case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(contents); break;
- case U_EMR_ANGLEARC: U_EMRANGLEARC_print(contents); break;
- case U_EMR_ELLIPSE: U_EMRELLIPSE_print(contents); break;
- case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(contents); break;
- case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(contents); break;
- case U_EMR_ARC: U_EMRARC_print(contents); break;
- case U_EMR_CHORD: U_EMRCHORD_print(contents); break;
- case U_EMR_PIE: U_EMRPIE_print(contents); break;
- case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(contents); break;
- case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(contents); break;
- case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(contents); break;
- case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(contents); break;
- case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(contents); break;
- case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(contents); break;
- case U_EMR_LINETO: U_EMRLINETO_print(contents); break;
- case U_EMR_ARCTO: U_EMRARCTO_print(contents); break;
- case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(contents); break;
- case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(contents); break;
- case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(contents); break;
- case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(contents); break;
- case U_EMR_ENDPATH: U_EMRENDPATH_print(contents); break;
- case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(contents); break;
- case U_EMR_FILLPATH: U_EMRFILLPATH_print(contents); break;
- case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(contents); break;
- case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(contents); break;
- case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(contents); break;
- case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(contents); break;
- case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(contents); break;
- case U_EMR_ABORTPATH: U_EMRABORTPATH_print(contents); break;
- case U_EMR_UNDEF69: U_EMRUNDEF69_print(contents); break;
- case U_EMR_COMMENT: U_EMRCOMMENT_print(contents, blimit, off); break;
- case U_EMR_FILLRGN: U_EMRFILLRGN_print(contents); break;
- case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(contents); break;
- case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(contents); break;
- case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(contents); break;
- case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(contents); break;
- case U_EMR_BITBLT: U_EMRBITBLT_print(contents); break;
- case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(contents); break;
- case U_EMR_MASKBLT: U_EMRMASKBLT_print(contents); break;
- case U_EMR_PLGBLT: U_EMRPLGBLT_print(contents); break;
- case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(contents); break;
- case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(contents); break;
- case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(contents); break;
- case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(contents); break;
- case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(contents); break;
- case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(contents); break;
- case U_EMR_POLYGON16: U_EMRPOLYGON16_print(contents); break;
- case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(contents); break;
- case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(contents); break;
- case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(contents); break;
- case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(contents); break;
- case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(contents); break;
- case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(contents); break;
- case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(contents); break;
- case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(contents); break;
- case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(contents); break;
- case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(contents); break;
- case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(contents); break;
- case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(contents); break;
- case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(contents); break;
- case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(contents); break;
- case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(contents); break;
- case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(contents); break;
- case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(contents); break;
- case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(contents); break;
- case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(contents); break;
- case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(contents); break;
- case U_EMR_UNDEF107: U_EMRUNDEF107_print(contents); break;
- case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(contents); break;
- case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(contents); break;
- case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(contents); break;
- case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(contents); break;
- case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(contents); break;
- case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(contents); break;
- case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(contents); break;
- case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(contents); break;
- case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(contents); break;
- case U_EMR_UNDEF117: U_EMRUNDEF117_print(contents); break;
- case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(contents); break;
- case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(contents); break;
- case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(contents); break;
- case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(contents); break;
- case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(contents); break;
- default: U_EMRNOTIMPLEMENTED_print("?",contents); break;
+ case U_EMR_HEADER: U_EMRHEADER_print(record); break;
+ case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(record); break;
+ case U_EMR_POLYGON: U_EMRPOLYGON_print(record); break;
+ case U_EMR_POLYLINE: U_EMRPOLYLINE_print(record); break;
+ case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(record); break;
+ case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(record); break;
+ case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(record); break;
+ case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(record); break;
+ case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(record); break;
+ case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(record); break;
+ case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(record); break;
+ case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(record); break;
+ case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(record); break;
+ case U_EMR_EOF: U_EMREOF_print(record); nSize=0; break;
+ case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(record); break;
+ case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(record); break;
+ case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(record); break;
+ case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(record); break;
+ case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(record); break;
+ case U_EMR_SETROP2: U_EMRSETROP2_print(record); break;
+ case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(record); break;
+ case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(record); break;
+ case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(record); break;
+ case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(record); break;
+ case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(record); break;
+ case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(record); break;
+ case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(record); break;
+ case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(record); break;
+ case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(record); break;
+ case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(record); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(record); break;
+ case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(record); break;
+ case U_EMR_SAVEDC: U_EMRSAVEDC_print(record); break;
+ case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(record); break;
+ case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(record); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(record); break;
+ case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(record); break;
+ case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(record); break;
+ case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(record); break;
+ case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(record); break;
+ case U_EMR_ANGLEARC: U_EMRANGLEARC_print(record); break;
+ case U_EMR_ELLIPSE: U_EMRELLIPSE_print(record); break;
+ case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(record); break;
+ case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(record); break;
+ case U_EMR_ARC: U_EMRARC_print(record); break;
+ case U_EMR_CHORD: U_EMRCHORD_print(record); break;
+ case U_EMR_PIE: U_EMRPIE_print(record); break;
+ case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(record); break;
+ case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(record); break;
+ case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(record); break;
+ case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(record); break;
+ case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(record); break;
+ case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(record); break;
+ case U_EMR_LINETO: U_EMRLINETO_print(record); break;
+ case U_EMR_ARCTO: U_EMRARCTO_print(record); break;
+ case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(record); break;
+ case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(record); break;
+ case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(record); break;
+ case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(record); break;
+ case U_EMR_ENDPATH: U_EMRENDPATH_print(record); break;
+ case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(record); break;
+ case U_EMR_FILLPATH: U_EMRFILLPATH_print(record); break;
+ case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(record); break;
+ case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(record); break;
+ case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(record); break;
+ case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(record); break;
+ case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(record); break;
+ case U_EMR_ABORTPATH: U_EMRABORTPATH_print(record); break;
+ case U_EMR_UNDEF69: U_EMRUNDEF69_print(record); break;
+ case U_EMR_COMMENT: U_EMRCOMMENT_print(record, off); break;
+ case U_EMR_FILLRGN: U_EMRFILLRGN_print(record); break;
+ case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(record); break;
+ case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(record); break;
+ case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(record); break;
+ case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(record); break;
+ case U_EMR_BITBLT: U_EMRBITBLT_print(record); break;
+ case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(record); break;
+ case U_EMR_MASKBLT: U_EMRMASKBLT_print(record); break;
+ case U_EMR_PLGBLT: U_EMRPLGBLT_print(record); break;
+ case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(record); break;
+ case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(record); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(record); break;
+ case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(record); break;
+ case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(record); break;
+ case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(record); break;
+ case U_EMR_POLYGON16: U_EMRPOLYGON16_print(record); break;
+ case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(record); break;
+ case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(record); break;
+ case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(record); break;
+ case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(record); break;
+ case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(record); break;
+ case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(record); break;
+ case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(record); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(record); break;
+ case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(record); break;
+ case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(record); break;
+ case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(record); break;
+ case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(record); break;
+ case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(record); break;
+ case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(record); break;
+ case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(record); break;
+ case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(record); break;
+ case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(record); break;
+ case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(record); break;
+ case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(record); break;
+ case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(record); break;
+ case U_EMR_UNDEF107: U_EMRUNDEF107_print(record); break;
+ case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(record); break;
+ case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(record); break;
+ case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(record); break;
+ case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(record); break;
+ case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(record); break;
+ case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(record); break;
+ case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(record); break;
+ case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(record); break;
+ case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(record); break;
+ case U_EMR_UNDEF117: U_EMRUNDEF117_print(record); break;
+ case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(record); break;
+ case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(record); break;
+ case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(record); break;
+ case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(record); break;
+ case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(record); break;
+ default: U_EMRNOTIMPLEMENTED_print("?",record); break;
} //end of switch
- return(size);
+ return(nSize);
}
diff --git a/src/libuemf/uemf_print.h b/src/libuemf/uemf_print.h
index 896de659e..6568b4cfa 100644
--- a/src/libuemf/uemf_print.h
+++ b/src/libuemf/uemf_print.h
@@ -6,11 +6,11 @@
/*
File: uemf_print.h
-Version: 0.0.5
-Date: 14-FEB-2013
+Version: 0.0.7
+Date: 24-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2013 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifndef _UEMF_PRINT_
@@ -44,17 +44,17 @@ void panose_print(U_PANOSE panose);
void logfont_print(U_LOGFONT lf);
void logfont_panose_print(U_LOGFONT_PANOSE lfp);
void bitmapinfoheader_print(const char *Bmih);
-void bitmapinfo_print(const char *Bmi);
+void bitmapinfo_print(const char *Bmi, const char *blimit);
void blend_print(U_BLEND blend);
void extlogpen_print(const PU_EXTLOGPEN elp);
void logpen_print(U_LOGPEN lp);
void logpltntry_print(U_LOGPLTNTRY lpny);
void logpalette_print(const PU_LOGPALETTE lp);
void rgndataheader_print(U_RGNDATAHEADER rdh);
-void rgndata_print(const PU_RGNDATA rd);
+void rgndata_print(const PU_RGNDATA rd, const char *blimit);
void coloradjustment_print(U_COLORADJUSTMENT ca);
void pixelformatdescriptor_print(U_PIXELFORMATDESCRIPTOR pfd);
-void emrtext_print(const char *emt, const char *record, int type);
+void emrtext_print(const char *emt, const char *record, const char *blimit, int type);
/* prototypes for EMR records */
void U_EMRNOTIMPLEMENTED_print(const char *name, const char *contents, int recnum, int off);
@@ -126,7 +126,7 @@ void U_EMRFLATTENPATH_print(const char *contents);
void U_EMRWIDENPATH_print(const char *contents);
void U_EMRSELECTCLIPPATH_print(const char *contents);
void U_EMRABORTPATH_print(const char *contents);
-void U_EMRCOMMENT_print(const char *contents, const char *blimit, size_t off);
+void U_EMRCOMMENT_print(const char *contents, size_t off);
void U_EMRFILLRGN_print(const char *contents);
void U_EMRFRAMERGN_print(const char *contents);
void U_EMRINVERTRGN_print(const char *contents);
diff --git a/src/libuemf/uemf_safe.c b/src/libuemf/uemf_safe.c
new file mode 100644
index 000000000..36284d60e
--- /dev/null
+++ b/src/libuemf/uemf_safe.c
@@ -0,0 +1,1202 @@
+/**
+ @file uemf_safe.c
+
+ @brief Functions for checking EMF records for memory issues.
+
+ EMF records come in a variety of sizes, and some types have variable sizes.
+ These functions check the record types and report if there are any issues
+ that could cause a memory access problem. All counts and offsets are examined
+ and the data structure checked so that no referenced byte is outside of the
+ declared size of the record.
+
+ Many variables are initialized to zero even though they will always be set because
+ some versions of gcc give spurious "may be used uninitialized" warnings otherwise.
+*/
+
+/*
+File: uemf_safe.c
+Version: 0.0.4
+Date: 23-APR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h> /* for offsetof() macro */
+#include "uemf.h"
+#include "uemf_endian.h" // for u_emf_record_sizeok
+
+// hide almost everuything in here from Doxygen
+//! \cond
+
+/**
+ \brief Test a U_EXTLOGPEN object.
+ \param elp PU_EXTLOGPEN object
+ \param blimit one byte past the end of the record
+*/
+int extlogpen_safe(
+ PU_EXTLOGPEN elp,
+ const char *blimit
+ ){
+ int count=elp->elpNumEntries;
+ if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0);
+ return(1);
+}
+
+/**
+ \brief Test a U_EMRTEXT record
+ \param pemt Pointer to a U_EMRTEXT record
+ \param record Pointer to the start of the record which contains this U_EMRTEXT
+ \param blimit one byte past the end of the record.
+*/
+int emrtext_safe(
+ PU_EMRTEXT pemt,
+ const char *record,
+ const char *blimit
+ ){
+ int off;
+ uint32_t count = pemt->nChars;
+ uint32_t fOptions = pemt->fOptions;
+ uint32_t offDx = 0;
+ off = sizeof(U_EMRTEXT);
+ if(!(fOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0);
+ off+=sizeof(U_RECTL);
+ }
+ offDx = *(uint32_t *)((char *)pemt +off);
+ if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(record, offDx + count*4, blimit))return(0);
+ return(1);
+}
+
+/**
+ \return 1 on success, 0 on failure
+ \brief Test a U_RGNDATA object.
+ \param rd pointer to a U_RGNDATA object.
+ \param cbRgnData size of the U_RGNDATA object.
+*/
+int rgndata_safe(
+ PU_RGNDATA rd,
+ int cbRgnData
+ ){
+ int count = rd->rdh.nCount;
+ if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0);
+ return(1);
+}
+
+
+/**
+ \return 1 on success, 0 on failure
+ \brief Test a U_BITMAPINFO object.
+ \param Bmi pointer to a U_BITMAPINFO object.
+ \param blimit one byte past the end of the record.
+*/
+int bitmapinfo_safe(
+ const char *Bmi,
+ const char *blimit
+ ){
+ int ClrUsed;
+ if(IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit))return(0);
+ ClrUsed = get_real_color_count(Bmi + offsetof(U_BITMAPINFO,bmiHeader));
+ if(ClrUsed && IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit))return(0);
+ return(1);
+}
+
+/**
+ \brief Check that the bitmap in the specified DIB is compatible with the record size
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param iUsage DIBcolors Enumeration
+ \param offBmi offset from the start of the record to the start of the bitmapinfo structure
+ \param cbBmi declared space for the bitmapinfo structure in the record
+ \param offBits offset from the start of the record to the start of the bitmap
+ \param cbBits declared space for the bitmap in the record (amount used may be less than this)
+ \param blimit one byte past the end of the record.
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+*/
+int DIB_safe(
+ const char *record,
+ uint32_t iUsage,
+ uint32_t offBmi,
+ uint32_t cbBmi,
+ uint32_t offBits,
+ uint32_t cbBits,
+ const char *blimit
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!cbBmi)return(1); // No DIB in a record where it is optional
+ if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0);
+ if(!bitmapinfo_safe(record + offBmi, blimit))return(0); // checks the number of colors
+ if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0);
+ if(iUsage == U_DIB_RGB_COLORS){
+ uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the EMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0);
+ }
+ }
+ return(1);
+}
+
+
+/* **********************************************************************************************
+These functions contain shared code used by various U_EMR*_safe functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+
+
+ These all have this form:
+
+ void core1_safe(const char *record){
+
+ but some do not actually use torev.
+
+
+
+*********************************************************************************************** */
+
+// all core*_safe call this, U_EMRSETMARGN_safe and some others all it directly
+// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype
+// sizeof(U_ENHMETARECORD) bytes in the record
+int core5_safe(const char *record, int minSize){
+ PU_EMR pEmr = (PU_EMR)(record);
+ if((int) pEmr->nSize < minSize)return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_safe
+int core1_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYLINETO))return(0);
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record);
+ int count=pEmr->cptl;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_safe
+int core2_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE))return(0);
+ PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record);
+ int count = pEmr->cptl;
+ int nPolys = pEmr->nPolys;
+ const char * blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0);
+ record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_safe
+int core3_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETMAPMODE))return(0);
+ return(1);
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_safe, also U_EMRFILLPATH_safe,
+int core4_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRELLIPSE))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_safe
+int core6_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYBEZIER16))return(0);
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record);
+ int count=pEmr->cpts;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+
+// Records with the same form starting with U_EMRSETWINDOWEXTEX_safe, that is, all with two uint32_t values after the emr
+int core7_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETWINDOWEXTEX))return(0);
+ return(1);
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
+int core8_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTTEXTOUTA))return(0);
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ if(!emrtext_safe(&(pEmr->emrtext),record,blimit))return(0);
+ return(1);
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_safe
+int core9_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRARC))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE16_safe
+int core10_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE16))return(0);
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record);
+ int count = pEmr->cpts;
+ int nPolys = pEmr->nPolys;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0);
+ record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRINVERTRGN_safe and U_EMRPAINTRGN_safe,
+int core11_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRINVERTRGN))return(0);
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_safe and U_EMRCREATEDIBPATTERNBRUSHPT_safe,
+int core12_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRCREATEMONOBRUSH))return(0);
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMI offBmi = pEmr->offBmi;
+ U_CBBMI cbBmi = pEmr->cbBmi;
+ U_OFFBITS offBits = pEmr->offBits;
+ U_CBBITS cbBits = pEmr->cbBits;
+ uint32_t iUsage = pEmr->iUsage;
+ return(DIB_safe(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit));
+}
+
+// common code for U_EMRALPHABLEND_safe and U_EMRTRANSPARENTBLT_safe,
+int core13_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRALPHABLEND))return(0);
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+/* **********************************************************************************************
+These are the core EMR_safe functions, each converts a particular type of record.
+All operate in place on the chunk of memory holding that record.
+Some of these have offsets or counts which, if corrupt or evil would result in access outside
+ the record. These cases return a status value of 0 if that happens, 1 on success. Other
+ records which do not have these issues do not return a status value.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+/**
+ All of the record level (hidden) functions have this form:
+ \brief Convert a pointer to a U_EMR_whatever record which has not been implemented.
+ \param record pointer to a buffer holding the EMR record
+ \param torev 1 for native to reversed, 0 for reversed to native
+*/
+int U_EMRNOTIMPLEMENTED_safe(const char *record){
+ fprintf(stderr,"EMF WARNING: could not safety check record because that type has not been implemented!\n");
+ return(core5_safe(record, sizeof(U_EMR)));
+}
+
+// U_EMRHEADER 1
+int U_EMRHEADER_safe(const char *record){
+ // use _MIN form so that it accepts very old EMF files
+ return(core5_safe(record, U_SIZE_EMRHEADER_MIN));
+}
+
+// U_EMRPOLYBEZIER 2
+int U_EMRPOLYBEZIER_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYGON 3
+int U_EMRPOLYGON_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYLINE 4
+int U_EMRPOLYLINE_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYBEZIERTO 5
+int U_EMRPOLYBEZIERTO_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYLINETO 6
+int U_EMRPOLYLINETO_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYPOLYLINE 7
+int U_EMRPOLYPOLYLINE_safe(const char *record){
+ return(core2_safe(record));
+}
+
+// U_EMRPOLYPOLYGON 8
+int U_EMRPOLYPOLYGON_safe(const char *record){
+ return(core2_safe(record));
+}
+
+// U_EMRSETWINDOWEXTEX 9
+int U_EMRSETWINDOWEXTEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETWINDOWORGEX 10
+int U_EMRSETWINDOWORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+int U_EMRSETVIEWPORTEXTEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+int U_EMRSETVIEWPORTORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETBRUSHORGEX 13
+int U_EMRSETBRUSHORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMREOF 14
+int U_EMREOF_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREOF))return(0);
+ PU_EMREOF pEmr = (PU_EMREOF)(record);
+ const char *blimit = record + pEmr->emr.nSize;
+ int cbPalEntries=pEmr->cbPalEntries;
+ if(cbPalEntries){
+ if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0);// 2 16 bit values in U_LOGPALLETE
+ }
+ int off = sizeof(U_EMREOF) + 4 * cbPalEntries;
+ if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0);
+ return(1);
+}
+
+
+// U_EMRSETPIXELV 15
+int U_EMRSETPIXELV_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETPIXELV));
+
+}
+
+
+// U_EMRSETMAPPERFLAGS 16
+int U_EMRSETMAPPERFLAGS_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETMAPPERFLAGS));
+}
+
+
+// U_EMRSETMAPMODE 17
+int U_EMRSETMAPMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETBKMODE 18
+int U_EMRSETBKMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETPOLYFILLMODE 19
+int U_EMRSETPOLYFILLMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETROP2 20
+int U_EMRSETROP2_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+int U_EMRSETSTRETCHBLTMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETTEXTALIGN 22
+int U_EMRSETTEXTALIGN_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+int U_EMRSETCOLORADJUSTMENT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETCOLORADJUSTMENT));
+}
+
+// U_EMRSETTEXTCOLOR 24
+int U_EMRSETTEXTCOLOR_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETTEXTCOLOR));
+}
+
+// U_EMRSETBKCOLOR 25
+int U_EMRSETBKCOLOR_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETBKCOLOR));
+}
+
+// U_EMROFFSETCLIPRGN 26
+int U_EMROFFSETCLIPRGN_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRMOVETOEX 27
+int U_EMRMOVETOEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETMETARGN 28
+int U_EMRSETMETARGN_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETMETARGN));
+}
+
+// U_EMREXCLUDECLIPRECT 29
+int U_EMREXCLUDECLIPRECT_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+int U_EMRINTERSECTCLIPRECT_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+int U_EMRSCALEVIEWPORTEXTEX_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSCALEWINDOWEXTEX 32
+int U_EMRSCALEWINDOWEXTEX_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSAVEDC 33
+int U_EMRSAVEDC_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSAVEDC));
+}
+
+// U_EMRRESTOREDC 34
+int U_EMRRESTOREDC_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+int U_EMRSETWORLDTRANSFORM_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETWORLDTRANSFORM));
+}
+
+// U_EMRMODIFYWORLDTRANSFORM 36
+int U_EMRMODIFYWORLDTRANSFORM_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRMODIFYWORLDTRANSFORM));
+}
+
+// U_EMRSELECTOBJECT 37
+int U_EMRSELECTOBJECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSELECTOBJECT));
+}
+
+// U_EMRCREATEPEN 38
+int U_EMRCREATEPEN_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEPEN));
+}
+
+// U_EMRCREATEBRUSHINDIRECT 39
+int U_EMRCREATEBRUSHINDIRECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEBRUSHINDIRECT));
+}
+
+// U_EMRDELETEOBJECT 40
+int U_EMRDELETEOBJECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRDELETEOBJECT));
+
+}
+
+// U_EMRANGLEARC 41
+int U_EMRANGLEARC_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRANGLEARC));
+}
+
+// U_EMRELLIPSE 42
+int U_EMRELLIPSE_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRRECTANGLE 43
+int U_EMRRECTANGLE_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRROUNDRECT 44
+int U_EMRROUNDRECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRROUNDRECT));
+}
+
+// U_EMRARC 45
+int U_EMRARC_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRCHORD 46
+int U_EMRCHORD_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRPIE 47
+int U_EMRPIE_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRSELECTPALETTE 48
+int U_EMRSELECTPALETTE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRCREATEPALETTE 49
+int U_EMRCREATEPALETTE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEPALETTE));
+}
+
+// U_EMRSETPALETTEENTRIES 50
+int U_EMRSETPALETTEENTRIES_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETPALETTEENTRIES));
+}
+
+// U_EMRRESIZEPALETTE 51
+int U_EMRRESIZEPALETTE_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRREALIZEPALETTE 52
+int U_EMRREALIZEPALETTE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRREALIZEPALETTE));
+}
+
+// U_EMREXTFLOODFILL 53
+int U_EMREXTFLOODFILL_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMREXTFLOODFILL));
+}
+
+// U_EMRLINETO 54
+int U_EMRLINETO_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRARCTO 55
+int U_EMRARCTO_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRPOLYDRAW 56
+int U_EMRPOLYDRAW_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYDRAW))return(0);
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record);
+ int count = pEmr->cptl;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+// U_EMRSETARCDIRECTION 57
+int U_EMRSETARCDIRECTION_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETMITERLIMIT 58
+int U_EMRSETMITERLIMIT_safe(const char *record){
+ return(core3_safe(record));
+}
+
+
+// U_EMRBEGINPATH 59
+int U_EMRBEGINPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRBEGINPATH));
+}
+
+// U_EMRENDPATH 60
+int U_EMRENDPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRENDPATH));
+}
+
+// U_EMRCLOSEFIGURE 61
+int U_EMRCLOSEFIGURE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCLOSEFIGURE));
+}
+
+// U_EMRFILLPATH 62
+int U_EMRFILLPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+int U_EMRSTROKEANDFILLPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSTROKEPATH 64
+int U_EMRSTROKEPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRFLATTENPATH 65
+int U_EMRFLATTENPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRFLATTENPATH));
+}
+
+// U_EMRWIDENPATH 66
+int U_EMRWIDENPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRWIDENPATH));
+}
+
+// U_EMRSELECTCLIPPATH 67
+int U_EMRSELECTCLIPPATH_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRABORTPATH 68
+int U_EMRABORTPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRABORTPATH));
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
+int U_EMRCOMMENT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRCOMMENT))return(0);
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record);
+ int cbData = pEmr->cbData;
+ const char *blimit =record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0);
+ return(1);
+}
+
+// U_EMRFILLRGN 71
+int U_EMRFILLRGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRFILLRGN))return(0);
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRFRAMERGN 72
+int U_EMRFRAMERGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRFRAMERGN))return(0);
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRINVERTRGN 73
+int U_EMRINVERTRGN_safe(const char *record){
+ return(core11_safe(record));
+}
+
+// U_EMRPAINTRGN 74
+int U_EMRPAINTRGN_safe(const char *record){
+ return(core11_safe(record));
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+int U_EMREXTSELECTCLIPRGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTSELECTCLIPRGN))return(0);
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRBITBLT 76
+int U_EMRBITBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRBITBLT))return(0);
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRSTRETCHBLT 77
+int U_EMRSTRETCHBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSTRETCHBLT))return(0);
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRMASKBLT 78
+int U_EMRMASKBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRMASKBLT))return(0);
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBMIMSK offBmiMask = pEmr->offBmiMask;
+ U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ U_OFFBITSMSK offBitsMask = pEmr->offBitsMask;
+ U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ uint32_t iUsageMask = pEmr->iUsageMask;
+ if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0);
+ return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit));
+}
+
+// U_EMRPLGBLT 79
+int U_EMRPLGBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPLGBLT))return(0);
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBMIMSK offBmiMask = pEmr->offBmiMask;
+ U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ U_OFFBITSMSK offBitsMask = pEmr->offBitsMask;
+ U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ uint32_t iUsageMask = pEmr->iUsageMask;
+ if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0);
+ return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit));
+}
+
+// U_EMRSETDIBITSTODEVICE 80
+int U_EMRSETDIBITSTODEVICE_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETDIBITSTODEVICE))return(0);
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRSTRETCHDIBITS 81
+int U_EMRSTRETCHDIBITS_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSTRETCHDIBITS))return(0);
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMREXTCREATEFONTINDIRECTW 82
+int U_EMREXTCREATEFONTINDIRECTW_safe(const char *record){
+ /* Panose or logfont, LogFontExDv is not supported. Test smallest to largest */
+ if(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT))return(1);
+ return(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE));
+}
+
+// U_EMREXTTEXTOUTA 83
+int U_EMREXTTEXTOUTA_safe(const char *record){
+ return(core8_safe(record));
+}
+
+// U_EMREXTTEXTOUTW 84
+int U_EMREXTTEXTOUTW_safe(const char *record){
+ return(core8_safe(record));
+}
+
+// U_EMRPOLYBEZIER16 85
+/**
+ \brief Convert a pointer to a U_EMR_POLYBEZIER16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYBEZIER16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYGON16 86
+int U_EMRPOLYGON16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYLINE16 87
+int U_EMRPOLYLINE16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYBEZIERTO16 88
+int U_EMRPOLYBEZIERTO16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYLINETO16 89
+/**
+ \brief Convert a pointer to a U_EMR_POLYLINETO16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYLINETO16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYPOLYLINE16 90
+int U_EMRPOLYPOLYLINE16_safe(const char *record){
+ return(core10_safe(record));
+}
+
+// U_EMRPOLYPOLYGON16 91
+int U_EMRPOLYPOLYGON16_safe(const char *record){
+ return(core10_safe(record));
+}
+
+
+// U_EMRPOLYDRAW16 92
+int U_EMRPOLYDRAW16_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYDRAW16))return(0);
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record);
+ int count = pEmr->cpts;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+// U_EMRCREATEMONOBRUSH 93
+int U_EMRCREATEMONOBRUSH_safe(const char *record){
+ return(core12_safe(record));
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_safe 94
+int U_EMRCREATEDIBPATTERNBRUSHPT_safe(const char *record){
+ return(core12_safe(record));
+}
+
+
+// U_EMREXTCREATEPEN 95
+int U_EMREXTCREATEPEN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTCREATEPEN))return(0);
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMI offBmi = pEmr->offBmi;
+ U_CBBMI cbBmi = pEmr->cbBmi;
+ U_OFFBITS offBits = pEmr->offBits;
+ U_CBBITS cbBits = pEmr->cbBits;
+ if(!DIB_safe(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit))return(0);
+ return(extlogpen_safe((PU_EXTLOGPEN) &(pEmr->elp), blimit));
+}
+
+// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRSETICMMODE 98
+int U_EMRSETICMMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRCREATECOLORSPACE 99
+int U_EMRCREATECOLORSPACE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACE));
+}
+
+// U_EMRSETCOLORSPACE 100
+int U_EMRSETCOLORSPACE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRDELETECOLORSPACE 101
+int U_EMRDELETECOLORSPACE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRPIXELFORMAT 104
+int U_EMRPIXELFORMAT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRPIXELFORMAT));
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRSMALLTEXTOUT 108
+int U_EMRSMALLTEXTOUT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSMALLTEXTOUT))return(0);
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record);
+ int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
+ int fuOptions = pEmr->fuOptions;
+ int cChars = pEmr->cChars;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(!(fuOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0);
+ }
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0);
+ return(1);
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRALPHABLEND 114
+int U_EMRALPHABLEND_safe(const char *record){
+ return(core13_safe(record));
+}
+
+// U_EMRSETLAYOUT 115
+int U_EMRSETLAYOUT_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRTRANSPARENTBLT 116
+int U_EMRTRANSPARENTBLT_safe(const char *record){
+ return(core13_safe(record));
+}
+
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRGRADIENTFILL 118
+int U_EMRGRADIENTFILL_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRGRADIENTFILL))return(0);
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record);
+ int nTriVert = pEmr->nTriVert;
+ int nGradObj = pEmr->nGradObj;
+ int ulMode = pEmr->ulMode;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0);
+ record += nTriVert * sizeof(U_TRIVERTEX);
+ if(nGradObj){
+ if( ulMode == U_GRADIENT_FILL_TRIANGLE){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0);
+ }
+ else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0);
+ }
+ }
+ return(1);
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRCREATECOLORSPACEW 122
+int U_EMRCREATECOLORSPACEW_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACEW));
+}
+
+//! \endcond
+
+/**
+ \brief Test an EMF record in memory from Big Endian to Little Endian.
+ \return 0 on failure, 1 on success
+ \param record pointer to the EMF record in memory
+
+ Normally this would be called immediately after reading a record from a file
+ and having called U_emf_record_sizeok().
+ It is NOT safe to call this routine without first calling U_emf_record_sizeok)()!
+ If the file has been converted from one endian to another calling this routine is
+ not necessary, because those routines also perform these checks.
+*/
+int U_emf_record_safe(const char *record){
+ int rstatus=1;
+
+ if(!record)return(0); // programming error
+
+ switch (U_EMRTYPE(record))
+ {
+ case U_EMR_HEADER: rstatus=U_EMRHEADER_safe(record); break;
+ case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_safe(record); break;
+ case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_safe(record); break;
+ case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_safe(record); break;
+ case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_safe(record); break;
+ case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_safe(record); break;
+ case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_safe(record); break;
+ case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_safe(record); break;
+ case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_safe(record); break;
+ case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_safe(record); break;
+ case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_safe(record); break;
+ case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_safe(record); break;
+ case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_safe(record); break;
+ case U_EMR_EOF: rstatus=U_EMREOF_safe(record); break;
+ case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_safe(record); break;
+ case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_safe(record); break;
+ case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_safe(record); break;
+ case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_safe(record); break;
+ case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_safe(record); break;
+ case U_EMR_SETROP2: rstatus=U_EMRSETROP2_safe(record); break;
+ case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_safe(record); break;
+ case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_safe(record); break;
+ case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_safe(record); break;
+ case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_safe(record); break;
+ case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_safe(record); break;
+ case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_safe(record); break;
+ case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_safe(record); break;
+ case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_safe(record); break;
+ case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_safe(record); break;
+ case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_safe(record); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_safe(record); break;
+ case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_safe(record); break;
+ case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_safe(record); break;
+ case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_safe(record); break;
+ case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_safe(record); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_safe(record); break;
+ case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_safe(record); break;
+ case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_safe(record); break;
+ case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_safe(record); break;
+ case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_safe(record); break;
+ case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_safe(record); break;
+ case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_safe(record); break;
+ case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_safe(record); break;
+ case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_safe(record); break;
+ case U_EMR_ARC: rstatus=U_EMRARC_safe(record); break;
+ case U_EMR_CHORD: rstatus=U_EMRCHORD_safe(record); break;
+ case U_EMR_PIE: rstatus=U_EMRPIE_safe(record); break;
+ case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_safe(record); break;
+ case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_safe(record); break;
+ case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_safe(record); break;
+ case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_safe(record); break;
+ case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_safe(record); break;
+ case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_safe(record); break;
+ case U_EMR_LINETO: rstatus=U_EMRLINETO_safe(record); break;
+ case U_EMR_ARCTO: rstatus=U_EMRARCTO_safe(record); break;
+ case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_safe(record); break;
+ case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_safe(record); break;
+ case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_safe(record); break;
+ case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_safe(record); break;
+ case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_safe(record); break;
+ case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_safe(record); break;
+ case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_safe(record); break;
+ case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_safe(record); break;
+ case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_safe(record); break;
+ case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_safe(record); break;
+ case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_safe(record); break;
+ case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_safe(record); break;
+ case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_safe(record); break;
+ case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_safe(record); break;
+ case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_safe(record); break;
+ case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_safe(record); break;
+ case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_safe(record); break;
+ case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_safe(record); break;
+ case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_safe(record); break;
+ case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_safe(record); break;
+ case U_EMR_BITBLT: rstatus=U_EMRBITBLT_safe(record); break;
+ case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_safe(record); break;
+ case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_safe(record); break;
+ case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_safe(record); break;
+ case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_safe(record); break;
+ case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_safe(record); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_safe(record); break;
+ case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_safe(record); break;
+ case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_safe(record); break;
+ case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_safe(record); break;
+ case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_safe(record); break;
+ case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_safe(record); break;
+ case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_safe(record); break;
+ case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_safe(record); break;
+ case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_safe(record); break;
+ case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_safe(record); break;
+ case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_safe(record); break;
+ case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_safe(record); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_safe(record); break;
+ case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_safe(record); break;
+ case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_safe(record); break;
+ case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_safe(record); break;
+ case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_safe(record); break;
+ case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_safe(record); break;
+ case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_safe(record); break;
+ case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_safe(record); break;
+ case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_safe(record); break;
+ case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_safe(record); break;
+ case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_safe(record); break;
+ case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_safe(record); break;
+ case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_safe(record); break;
+ case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_safe(record); break;
+ case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_safe(record); break;
+ case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_safe(record); break;
+ case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_safe(record); break;
+ case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_safe(record); break;
+ case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_safe(record); break;
+ case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_safe(record); break;
+ case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_safe(record); break;
+ case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_safe(record); break;
+ case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_safe(record); break;
+ case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_safe(record); break;
+ case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_safe(record); break;
+ case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_safe(record); break;
+ case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_safe(record); break;
+ case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_safe(record); break;
+ case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_safe(record); break;
+ default: rstatus=U_EMRNOTIMPLEMENTED_safe(record); break;
+ } //end of switch
+ return(rstatus);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libuemf/uemf_safe.h b/src/libuemf/uemf_safe.h
new file mode 100644
index 000000000..0c9e3cc69
--- /dev/null
+++ b/src/libuemf/uemf_safe.h
@@ -0,0 +1,32 @@
+/**
+ @file uemf_safe.h
+
+ @brief Defintions and prototype for function for converting EMF records between Big Endian and Little Endian byte orders.
+*/
+
+/*
+File: uemf_endian.h
+Version: 0.0.2
+Date: 26-MAR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_SAFE_
+#define _UEMF_SAFE_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// prototypes
+int U_emf_record_safe(const char *record);
+int bitmapinfo_safe(const char *Bmi, const char *blimit);
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_SAFE_ */
diff --git a/src/libuemf/upmf.c b/src/libuemf/upmf.c
index 01f7ba3a4..7d6349185 100644
--- a/src/libuemf/upmf.c
+++ b/src/libuemf/upmf.c
@@ -21,11 +21,11 @@
/*
File: upmf.c
-Version: 0.0.6
-Date: 26-MAR-2014
+Version: 0.0.9
+Date: 25-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
@@ -1459,11 +1459,18 @@ int U_PMF_PTRSAV_COND(const char **Dst, const char *Src, int Doit){
else { *Dst = NULL; }
return(1);
}
+/*
+
+ =====================================================================================
+ start of U_PMF_*_get() functions
+
+*/
/**
\brief Get the 16 bit unsigned Flags field from a header.
\param contents Record from which to extract data, will be incremented by header size.
\return Flags field
+
In many records the only value needed from the header is Flags. Rather than mapping
the entire Header and returning it, in these instances this function may be called to
just get this one value.
@@ -1516,6 +1523,19 @@ int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header){
}
/**
+ \brief return the size in bytes of the EMF+ record
+ \param contents Record from which to extract data, will not be modified.
+ \returns size, or 0 if contents is Null
+*/
+int U_PMF_RECORD_SIZE_get(const char *contents){
+ if(!contents){ return(0); }
+ int Size;
+ const char *from = contents + 4;
+ U_PMF_SERIAL_get(&from, &Size, 4, 1, U_LE);
+ return(Size);
+}
+
+/**
\brief Return the size of a PenData object from an EMF+ record.
\param PenData Address in memory where the PenData object starts.
\returns size of the object in bytes
@@ -5362,6 +5382,17 @@ U_PSEUDO_OBJ *U_PMR_TRANSLATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Dx, U_FLOAT
return(po);
}
+/*
+
+ end of U_PMF_*_set() functions
+ =====================================================================================
+ start of U_PMF_*_get() functions
+
+ These functions all take a blimit value so that they can check if the data description in the fields
+ they process extend beyond the end of the record.
+
+*/
+
//! \cond
/* core _get functions, not accessed outside of this routine */
@@ -5387,11 +5418,15 @@ int U_PMF_CORE1_get(const char *contents, void *v1, void *v2, void *v3, void *v4
\param Version EmfPlusGraphicsVersion object
\param Type BrushType Enumeration
\param Data one of the 5 types of Brush data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data){
- if(!contents || !Version || !Type || !Data){ return(0); }
+int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents,sizeof(U_PMF_BRUSH), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -5405,11 +5440,15 @@ int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, con
\param Version EmfPlusGraphicsVersion object
\param Type CustomLineCapData Enumeration
\param Data one of the 2 types of Linecap data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data){
- if(!contents || !Version || !Type || !Data){ return(0); }
+int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAP), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -5428,10 +5467,13 @@ int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *T
\param Data Unicode (UTF-16LE) name of font family
EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object
+
+ Caller must check Data for possible memory access violations.
*/
int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit,
- int32_t *FSFlags, uint32_t *Length, const char **Data){
- if(!contents || !Version || !EmSize || !SizeUnit || !FSFlags || !Length || !Data){ return(0); }
+ int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit){
+ if(!contents || !Version || !EmSize || !SizeUnit || !FSFlags || !Length || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FONT), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, EmSize, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, SizeUnit, 4, 1, U_LE);
@@ -5452,9 +5494,12 @@ int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uin
\param Data one of the 2 types of image data
EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data){
- if(!contents || !Version || !Type){ return(0); }
+int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGE), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -5472,8 +5517,10 @@ int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, con
EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object
*/
-int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, uint32_t *ObjectClamp){
- if(!contents || !Version || !WrapMode || !ClampColor || !ObjectClamp){ return(0); }
+int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor,
+ uint32_t *ObjectClamp, const char *blimit){
+ if(!contents || !Version || !WrapMode || !ClampColor || !ObjectClamp || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGEATTRIBUTES), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
contents += 4; /* Skip Reserved 1*/
U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE);
@@ -5494,21 +5541,31 @@ int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t
\param Types array of U_PMF_PATHPOINTTYPERLE and/or U_PMF_PATHPOINTTYPE
EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+
+ Caller must check Types for possible memory access violations if type can be U_PMF_PATHPOINTTYPERLE.
*/
-int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, const char **Points, const char **Types){
- if(!contents || !Version || !Count || !Flags || !Points || !Types){ return(0); }
+int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags,
+ const char **Points, const char **Types, const char *blimit){
+ if(!contents || !Version || !Count || !Flags || !Points || !Types || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATH), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Flags, 2, 1, U_LE);
contents+=2; /* reserved */
- U_PMF_PTRSAV_SHIFT(Points, &contents, 0);
+ uint32_t sizeP, sizeT;
if(*Flags & U_PPF_P){
- int killme = U_PMF_LEN_REL715(contents,*Count); //DEBUG
- printf("DEBUG U_PMF_PATH_get count:%d LENREL715:%d\n",*Count,killme);fflush(stdout);
- contents += killme;
+ sizeP = U_PMF_LEN_REL715(contents,*Count); //DEBUG
+ printf("DEBUG U_PMF_PATH_get count:%d LENREL715:%d\n",*Count,sizeP);fflush(stdout);
}
- else if(*Flags & U_PPF_C){ contents += *Count * sizeof(U_PMF_POINT); }
- else { contents += *Count * sizeof(U_PMF_POINTF); }
+ else if(*Flags & U_PPF_C){ sizeP = *Count * sizeof(U_PMF_POINT); }
+ else { sizeP = *Count * sizeof(U_PMF_POINTF); }
+ if(IS_MEM_UNSAFE(contents, sizeP, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Points, &contents, 0);
+ contents += sizeP;
+ /* this limit is correct if there are only U_PMF_PATHPOINTTYPE PointTypes, it is a lower bound if
+ there can also be U_PMF_PATHPOINTTYPERLE */
+ sizeT = *Count * sizeof(U_PMF_PATHPOINTTYPE);
+ if(IS_MEM_UNSAFE(contents, sizeT, blimit))return(0);
U_PMF_PTRSAV_SHIFT(Types, &contents, 0);
return(1);
}
@@ -5523,9 +5580,12 @@ int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uin
\param Brush Brush Description
EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object
+
+ Caller must check Brush and PenData for possible memory access violations.
*/
-int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush){
- if(!contents || !Type || !PenData || !Brush){ return(0); }
+int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit){
+ if(!contents || !Type || !PenData || !Brush || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PEN), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(PenData, &contents, 0);
@@ -5543,8 +5603,9 @@ int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const
EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object
*/
-int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes){
- if(!contents || !Version || !Count || !Nodes){ return(0); }
+int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit){
+ if(!contents || !Version || !Count || !Nodes || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGION), blimit))return(0);
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Nodes, &contents, 0);
@@ -5560,8 +5621,9 @@ int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, c
EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object
*/
-int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data){
- if(!contents || !Sfs || !Data){ return(0); }
+int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit){
+ if(!contents || !Sfs || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_STRINGFORMAT), blimit))return(0);
U_PMF_SERIAL_get(&contents, Sfs, 4, 15, U_LE);
*Data = contents;
return(1);
@@ -5578,8 +5640,9 @@ int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const
EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
*/
-int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha){
- if(!contents || !Blue || !Green || !Red || !Alpha){ return(0); }
+int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit){
+ if(!contents || !Blue || !Green || !Red || !Alpha || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ARGB), blimit))return(0);
U_PMF_SERIAL_get(&contents, Blue, 1, 1, U_XE);
U_PMF_SERIAL_get(&contents, Green, 1, 1, U_XE);
U_PMF_SERIAL_get(&contents, Red, 1, 1, U_XE);
@@ -5595,11 +5658,14 @@ int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t
\param Data pointer to variable part
EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data){
- if(!contents || !Bs || !Data){ return(0); }
- U_PMF_SERIAL_get(&contents, Bs, 4, 5, U_LE);
- U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit){
+ if(!contents || !Bs || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BITMAP), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Bs, 4, 5, U_LE); // width, height, stride, pixelformat, type
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0); // bitmapdata
return(1);
}
@@ -5612,11 +5678,16 @@ int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data){
\param Data An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration.
EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data){
- if(!contents || !Ps || !Colors || !Data ){ return(0); }
+int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit){
+ if(!contents || !Ps || !Colors || !Data || !blimit){ return(0); }
+ /* this structure is entirely optional */
+ if(IS_MEM_UNSAFE(contents, 4*2, blimit))return(0);
U_PMF_SERIAL_get(&contents, Ps, 4, 2, U_LE);
U_PMF_PTRSAV_SHIFT(Colors, &contents, Ps->Elements * sizeof(U_PMF_ARGB));
+ /* difficult to know how big the actual bitmap will be, just return the pointer to it untested */
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -5627,13 +5698,15 @@ int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **C
\param contents Record from which to extract data
\param Elements Number of members in Positions and Colors
\param Positions Caller must free. Pointer to memory holding positions along gradient line.
- \param Colors Caller must NOT free memory ,Pointer to memory holding colors at positions on gradient line.
+ \param Colors Caller must NOT free memory, Pointer to memory holding colors at positions on gradient line.
EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
*/
-int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors){
- if(!contents || !Positions || !Colors){ return(0); }
+int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit){
+ if(!contents || !Positions || !Colors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDCOLORS), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0);
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE,1)){ return(0); }
U_PMF_PTRSAV_SHIFT(Colors, &contents, 0);
return(1);
@@ -5649,9 +5722,11 @@ int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Po
EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
*/
-int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors){
- if(!contents || !Elements || !Positions || !Factors){ return(0); }
+int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit){
+ if(!contents || !Elements || !Positions || !Factors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDFACTORS), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4 * 2, blimit))return(0);
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE, 1)){ return(0); }
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Factors, 4, *Elements, U_LE, 1)){
free(*Positions);
@@ -5668,9 +5743,12 @@ int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **P
\param Data boundary of the brush
EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPATHDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -5680,14 +5758,16 @@ int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char *
\brief Get data from a U_PMF_BOUNDARYPOINTDATA object
\return 1 on success, 0 on error
\param contents Record from which to extract data
- \param Elements Members in POints
+ \param Elements Members in Points
\param Points Caller must free. Pointer to memory holding points along gradient line. Boundary of the brush.
EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object
*/
-int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points){
- if(!contents || !Elements || !Points){ return(0); }
+int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit){
+ if(!contents || !Elements || !Points || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPOINTDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0);
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements * 2, U_LE, 1)){ return(0); }
return(1);
}
@@ -5701,8 +5781,9 @@ int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_P
EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object
*/
-int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length){
- if(!contents || !First || !Length){ return(0); }
+int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit){
+ if(!contents || !First || !Length || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CHARACTERRANGE), blimit))return(0);
U_PMF_SERIAL_get(&contents, First, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Length, 4, 1, U_LE);
return(1);
@@ -5717,9 +5798,11 @@ int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Leng
EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
*/
-int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths){
- if(!contents || !Elements || !Widths){ return(0); }
+int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit){
+ if(!contents || !Elements || !Widths || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_COMPOUNDLINEDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0);
*Widths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT));
if(!*Widths){ return(0); }
U_PMF_SERIAL_get(&contents, *Widths, 4, *Elements, U_LE);
@@ -5736,9 +5819,12 @@ int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT
This function does not do anything useful, but it is included so that all objects have a corresponding _get().
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data){
- if(!contents || !Data){ return(0); }
+int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit){
+ if(!contents || !Data || !blimit){ return(0); }
+ if(contents >= blimit)return(0);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -5751,9 +5837,12 @@ int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data){
\param Data Description of linecap
EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMENDCAPDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -5767,8 +5856,9 @@ int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char *
EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object
*/
-int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad){
- if(!contents || !Ccad){ return(0); }
+int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit){
+ if(!contents || !Ccad || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPARROWDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Ccad, 4, 13, U_LE);
return(1);
}
@@ -5781,9 +5871,12 @@ int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPAR
\param Data variable part of U_PMF_CUSTOMLINECAPDATA
EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data){
- if(!contents || !Clcd){ return(0); }
+int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit){
+ if(!contents || !Clcd || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Clcd, 4, 12, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -5798,14 +5891,19 @@ int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *C
\param LineData Path to stroke (optional)
EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
+
+ Caller must check LineData for possible memory access violations.
*/
-int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData){
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit){
uint32_t length;
int status = 1;
- if(!contents){ return(0); }
+ if(!contents || !*FillData || !*LineData || !blimit){ return(0); }
+ /* this structure is entirely optional */
if(Flags & U_CLCD_FillPath){
if(!FillData){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, length, blimit))return(0);
contents -= 4; /* undo the unneeded shift from preceding */
U_PMF_PTRSAV_SHIFT(FillData, &contents, 4 + length);
status += 2;
@@ -5814,6 +5912,10 @@ int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, co
if(Flags & U_CLCD_LinePath){
if(!LineData){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, length, blimit))return(0);
+ contents -= 4; /* undo the unneeded shift from preceding */
U_PMF_PTRSAV_SHIFT(LineData, &contents, 0);
status += 4;
}
@@ -5829,9 +5931,12 @@ int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, co
\param Data Description of linecap
EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMSTARTCAPDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -5846,9 +5951,11 @@ int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char
EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
*/
-int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths){
- if(!contents || !Elements || !Lengths){ return(0); }
+int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit){
+ if(!contents || !Elements || !Lengths || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_DASHEDLINEDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0);
*Lengths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT));
if(!*Lengths){ return(0); }
U_PMF_SERIAL_get(&contents, *Lengths, 4, *Elements, U_LE);
@@ -5863,9 +5970,12 @@ int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **
\param Data Path specification
EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FILLPATHO), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -5881,8 +5991,9 @@ int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data
EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
*/
-int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY){
- if(!contents || !Count || !ScaleX || !ScaleY){ return(0); }
+int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit){
+ if(!contents || !Count || !ScaleX || !ScaleY || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
if(*Count != 2){ return(0); }
U_PMF_SERIAL_get(&contents, ScaleX, 4, 1, U_LE);
@@ -5899,9 +6010,10 @@ int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *Sca
EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
*/
-int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion){
- if(!contents || !Signature || !GrfVersion){ return(0); }
+int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit){
uint32_t tmp;
+ if(!contents || !Signature || !GrfVersion || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_GRAPHICSVERSION), blimit))return(0);
memcpy(&tmp, contents, 4);
*Signature = tmp >> 12;
*GrfVersion = tmp & U_GFVR_MASKLO;
@@ -5918,8 +6030,9 @@ int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVers
EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object
*/
-int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background){
- if(!contents || !Style || !Foreground || !Background){ return(0); }
+int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit){
+ if(!contents || !Style || !Foreground || !Background || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_HATCHBRUSHDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Foreground, 4, 1, U_XE);
U_PMF_SERIAL_get(&contents, Background, 4, 1, U_XE);
@@ -5931,12 +6044,14 @@ int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param Value 7 bit signed integer (stored in an integer)
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object
*/
-int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value){
- if(!contents || !*contents || !Value){ return(0); }
+int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit){
uint8_t tmp;
+ if(!contents || !*contents || !Value || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 1, blimit))return(0); /* past end of buffer */
if(**contents & U_TEST_INT7)return(0); /* this bit must be 0 in this object type */
U_PMF_SERIAL_get(contents, &tmp, 1, 1, U_XE);
if(tmp & U_SIGN_INT7){
@@ -5954,12 +6069,14 @@ int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value){
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param Value 15 bit signed integer (stored in an integer)
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object
*/
-int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value){
- if(!contents || !*contents || !Value){ return(0); }
+int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit){
+ if(!contents || !*contents || !Value || !blimit){ return(0); }
uint16_t tmp;
+ if(IS_MEM_UNSAFE(*contents, 2, blimit))return(0); /* past end of buffer */
if(!(**contents & U_TEST_INT7))return(0); /* this bit must be 1 in this object type */
U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_BE);
tmp &= U_MASK_INT15; /* drop the 7/15 flag from the most significant bit */
@@ -6000,11 +6117,15 @@ int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int
\param contents Record from which to extract data
\param Lgbd U_PMF_LINEARGRADIENTBRUSHDATA structure, with no variable part
\param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data){
- if(!contents || !Lgbd || !Data){ return(0); }
+int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit){
+ if(!contents || !Lgbd || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEARGRADIENTBRUSHDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Lgbd, 4, 6, U_LE); /* Flags, WrapMode, RectF*/
U_PMF_SERIAL_get(&contents, &(Lgbd->StartColor), 4, 4, U_XE); /* StartColor, EndColor, Reserved1 & 2 */
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -6020,27 +6141,42 @@ int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENT
\param Bc U_PMF_BLENDCOLORS object or NULL
\param BfH U_PMF_BLENDFACTORS (H) object or NULL
\param BfV U_PMF_BLENDFACTORS (V) object or NULL (WARNING, GDI+ defines this field but does not render it. DO NOT USE.)
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
+
*/
int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm,
- const char **Bc, const char **BfH, const char **BfV){
+ const char **Bc, const char **BfH, const char **BfV, const char *blimit){
uint32_t Elements;
- if(!contents || !Tm|| !Bc || !BfH || !BfV){ return(0); }
+ if(!contents || !Tm|| !Bc || !BfH || !BfV || !blimit){ return(0); }
+ /* all of the fields are optional! */
*Bc = *BfH = *BfV = NULL;
- if(Flags & U_BD_Transform)U_PMF_SERIAL_get(&contents, Tm, 4, 6, U_LE);
+ if(Flags & U_BD_Transform){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ROTMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Tm, 4, 6, U_LE);
+ }
if(Flags & U_BD_PresetColors){
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * ( sizeof(U_FLOAT) + sizeof(U_PMF_ARGB)), blimit))return(0);
+ contents-=4; /* back up to the front of the count, as it is part of the data field */
U_PMF_PTRSAV_SHIFT(Bc, &contents, 0);
}
else if(Flags & U_BD_BlendFactorsH){
U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
contents-=4; /* back up to the front of the count, as it is part of the data field */
- U_PMF_PTRSAV_SHIFT(BfH, &contents, 4 + 8*Elements); /* 4 byte count + 2 * 4bytes * Elements */
+ U_PMF_PTRSAV_SHIFT(BfH, &contents, 4 + (Elements * 2 * sizeof(U_FLOAT))); /* 4 byte count + 2 * 4bytes * Elements */
if(Flags & U_BD_BlendFactorsV){
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
U_PMF_PTRSAV_SHIFT(BfV, &contents, 0);
}
}
else if(Flags & U_BD_BlendFactorsV){
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
+ contents-=4; /* back up to the front of the count, as it is part of the data field */
U_PMF_PTRSAV_SHIFT(BfV, &contents, 0);
}
return(1);
@@ -6052,11 +6188,15 @@ int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Fla
\param contents Record from which to extract data
\param Size Bytes in Data
\param Data Outline path
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEPATH), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
@@ -6069,11 +6209,15 @@ int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data){
\param Type
\param Size Bytes in Data
\param Data Various types of data, like an EMF metafile, WMF metafile, another EMF+ metafile
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data){
- if(!contents || !Type || !Size || !Data){ return(0); }
+int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Type || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_METAFILE), blimit))return(0);
U_PMF_SERIAL_get(&contents, &Type, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -6087,13 +6231,16 @@ int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, con
\param Flags PaletteStyle flags
\param Elements Members in the array
\param Colors Palette data (array of colors)
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object
*/
-int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Colors){
- if(!contents || !Flags || !Elements || !Colors){ return(0); }
+int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Colors, const char *blimit){
+ if(!contents || !Flags || !Elements || !Colors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PALETTE), blimit))return(0);
U_PMF_SERIAL_get(&contents, &Flags, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements*sizeof(U_RGBQUAD), blimit))return(0);
U_PMF_PTRSAV_SHIFT(Colors, &contents, 0);
return(1);
@@ -6107,21 +6254,32 @@ int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements,
\param Gradient variable part of U_PMF_LINEARGRADIENTBRUSHDATA, Color Gradient with Elements members
\param Boundary variable part of U_PMF_LINEARGRADIENTBRUSHDATA, U_PMF_BOUNDARYPATHDATA object if BrushDataPath bit set in Flag, else U_PMF_BOUNDARYPOINTDATA object
\param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA, exact composition depends on Flags
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object
+
+ Caller must check Data for possible memory access violations.
+
*/
-int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, const char **Boundary, const char **Data){
- if(!contents || !Pgbd || !Gradient || !Boundary || !Data){ return(0); }
+int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient,
+ const char **Boundary, const char **Data, const char *blimit){
+ if(!contents || !Pgbd || !Gradient || !Boundary || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATHGRADIENTBRUSHDATA), blimit))return(0);
uint32_t Size;
U_PMF_SERIAL_get(&contents, Pgbd, 4, 2, U_LE); /* Flags and WrapMode*/
U_PMF_SERIAL_get(&contents, &(Pgbd->CenterColor), 4, 1, U_XE);
U_PMF_SERIAL_get(&contents, &(Pgbd->Center), 4, 3, U_LE); /* Center and Elements */
+ if(IS_MEM_UNSAFE(contents, Pgbd->Elements * sizeof(U_PMF_ARGB), blimit))return(0);
U_PMF_PTRSAV_SHIFT(Gradient, &contents, Pgbd->Elements * sizeof(U_PMF_ARGB));
U_PMF_PTRSAV_SHIFT(Boundary, &contents, 0);
U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); /* The first 4 bytes of the Boundary are always a size */
if(Pgbd->Flags & U_BD_Path){ contents += Size; } // U_PMF_BOUNDARYPATHDATA
else { contents += Size*2*sizeof(U_FLOAT); } // U_PMF_BOUNDARYPOINTDATA
- U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ if(Pgbd->Flags & (U_BD_Transform |U_BD_PresetColors | U_BD_BlendFactorsH| U_BD_FocusScales)){ // optional data present
+ if(contents >= blimit)return(0); // the size is variable but this must still hold
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ }
+ else { *Data = NULL; } // no optional data present
return(1);
}
@@ -6133,15 +6291,34 @@ int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUS
\param Matrix Transformation matrix
\param Pattern Blend Pattern
\param Data Focus scales for the brush
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
*/
-int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, const char **Pattern, const char **Data){
- if(!contents || !Flags || !Matrix || !Pattern || !Data){ return(0); }
- U_PMF_SERIAL_get(&contents, &Flags, 4, 1, U_LE);
- U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
- U_PMF_PTRSAV_COND(Data, contents, (Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)));
- U_PMF_PTRSAV_COND(Data, contents, (Flags & U_BD_FocusScales));
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix,
+ const char **Pattern, const char **Data, const char *blimit){
+ int varsize;
+ if(!contents || !Flags || !Matrix || !Pattern || !Data || !blimit){ return(0); }
+ /* this structure is entirely optional */
+ if(Flags & U_BD_Transform){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)){
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ uint32_t Elements;
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE);
+ contents -= 4;
+ varsize=(Elements * 4 * (Flags & U_BD_BlendFactorsH ? 2 :1));
+ if(IS_MEM_UNSAFE(contents, varsize, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Pattern, &contents, varsize);
+ }
+ else { *Pattern=NULL; }
+ if(Flags & U_BD_FocusScales){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, sizeof(U_PMF_FOCUSSCALEDATA));
+ }
+ else { *Data=NULL; }
return(1);
}
@@ -6151,14 +6328,16 @@ int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags
\param contents Record from which to extract data
\param Flags PathPointType flags
\param Type PathPointType enumeration
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
Note: order of 4bit fields appears to be shown in the LE column, not as
documented in the BE column.
*/
-int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type){
- if(!contents || !Flags || !Type){ return(0); }
+int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit){
+ if(!contents || !Flags || !Type || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 1, blimit))return(0);
uint8_t tmp;
memcpy(&tmp, contents, 1);
*Flags =(tmp & U_PTP_MASK) >> U_PTP_SHIFT;
@@ -6172,13 +6351,15 @@ int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type){
\param contents Record from which to extract data
\param Bezier Set: Bezier curve, Clear: straight line
\param RL Run Length
- \param Ppt PathPointType enumeration
+ \param Ppt PathPointType enumeration
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
*/
-int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt){
- if(!contents || !Bezier || !RL || !Ppt){ return(0); }
+int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit){
+ if(!contents || !Bezier || !RL || !Ppt || !blimit){ return(0); }
uint16_t tmp;
+ if(IS_MEM_UNSAFE(contents, 2, blimit))return(0);
U_PMF_SERIAL_get(&contents, &tmp, 2, 1, U_LE);
*Bezier = tmp & U_PPF_BZ;
*RL = (tmp >> U_FF_SHFT_RL) & U_FF_MASK_RL;
@@ -6194,14 +6375,17 @@ int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *
\param Unit UnitType enumeration
\param Width Width in units set by Unit
\param Data Optional pen data, exact composition depends on Flags
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
*/
-int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data){
- if(!contents || !Flags || !Unit || !Width || !Data){ return(0); }
+int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit){
+ if(!contents || !Flags || !Unit || !Width || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 3*4, blimit))return(0);
U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Unit, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Width, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // variable data will extend farther, but this much at least must be true
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -6224,6 +6408,7 @@ int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_F
\param CmpndLineData Compount Line (parallel lines drawn instead of one)
\param CSCapData Custom start cap
\param CECapData Custom end cap
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
@@ -6245,26 +6430,56 @@ int U_PMF_PENOPTIONALDATA_get(
int32_t *Alignment,
const char **CmpndLineData,
const char **CSCapData,
- const char **CECapData){
+ const char **CECapData,
+ const char *blimit){
if(!contents ||
!Flags || !Matrix || !StartCap || !EndCap ||
!Join || !MiterLimit || !Style || !DLCap ||
!DLOffset || !DLData || !Alignment || !CmpndLineData ||
- !CSCapData || !CECapData){ return(0); }
-
- if(Flags & U_PD_Transform){ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE); }
- if(Flags & U_PD_StartCap){ U_PMF_SERIAL_get(&contents, StartCap, 4, 1, U_LE); }
- if(Flags & U_PD_EndCap){ U_PMF_SERIAL_get(&contents, EndCap, 4, 1, U_LE); }
- if(Flags & U_PD_Join){ U_PMF_SERIAL_get(&contents, Join, 4, 1, U_LE); }
- if(Flags & U_PD_MiterLimit){ U_PMF_SERIAL_get(&contents, MiterLimit, 4, 1, U_LE); }
- if(Flags & U_PD_LineStyle){ U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE); }
- if(Flags & U_PD_DLCap){ U_PMF_SERIAL_get(&contents, DLCap, 4, 1, U_LE); }
- if(Flags & U_PD_DLOffset){ U_PMF_SERIAL_get(&contents, DLOffset, 4, 1, U_LE); }
- if(Flags & U_PD_DLData){ U_PMF_PTRSAV_SHIFT( DLData, &contents, U_PMF_LEN_FLOATDATA(contents)); }
- if(Flags & U_PD_NonCenter){ U_PMF_SERIAL_get(&contents, Alignment, 4, 1, U_LE); }
- if(Flags & U_PD_CLData){ U_PMF_PTRSAV_SHIFT( CmpndLineData, &contents, U_PMF_LEN_FLOATDATA(contents)); }
- if(Flags & U_PD_CustomStartCap){ U_PMF_PTRSAV_SHIFT( CSCapData, &contents, U_PMF_LEN_BYTEDATA(contents)); }
- if(Flags & U_PD_CustomEndCap){ U_PMF_PTRSAV_SHIFT( CECapData, &contents, U_PMF_LEN_BYTEDATA(contents)); }
+ !CSCapData || !CECapData || !blimit){ return(0); }
+
+ if(Flags & U_PD_Transform){ if(IS_MEM_UNSAFE(contents, 4*6, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(Flags & U_PD_StartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, StartCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_EndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, EndCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_Join){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Join, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_MiterLimit){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, MiterLimit, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_LineStyle){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, DLCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLOffset){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, DLOffset, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( DLData, &contents, U_PMF_LEN_FLOATDATA(contents));
+ }
+ if(Flags & U_PD_NonCenter){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Alignment, 4, 1, U_LE); }
+ if(Flags & U_PD_CLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CmpndLineData, &contents, U_PMF_LEN_FLOATDATA(contents));
+ }
+ if(Flags & U_PD_CustomStartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CSCapData, &contents, U_PMF_LEN_BYTEDATA(contents));
+ }
+ if(Flags & U_PD_CustomEndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CECapData, &contents, U_PMF_LEN_BYTEDATA(contents));
+ }
return(1);
}
@@ -6274,12 +6489,14 @@ int U_PMF_PENOPTIONALDATA_get(
\param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINT).
\param X X coordinate
\param Y Y coordinate
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
*/
-int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
- if(!contents || !X || !Y){ return(0); }
+int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !X || !Y || !blimit){ return(0); }
int16_t tmp;
+ if(IS_MEM_UNSAFE(*contents, 2*2, blimit))return(0);
U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *X = tmp;
U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *Y = tmp;
return(1);
@@ -6291,11 +6508,13 @@ int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
\param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINTF).
\param X X coordinate
\param Y Y coordinate
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
*/
-int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
- if(!contents || !X || !Y){ return(0); }
+int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !X || !Y || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 4*2, blimit))return(0);
U_PMF_SERIAL_get(contents, X, 4, 1, U_LE);
U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE);
return(1);
@@ -6307,19 +6526,20 @@ int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
\param contents Record from which to extract data. On return position is offset by returned size.
\param X X coordinate
\param Y Y coordinate
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
*/
-int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
- if(!contents || !*contents | !X || !Y){ return(0); }
+int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !*contents | !X || !Y || !blimit){ return(0); }
int size=0;
- if( U_PMF_INTEGER7_get( contents, X)){ size +=1; }
- else if(U_PMF_INTEGER15_get(contents, X)){ size +=2; }
+ if( U_PMF_INTEGER7_get( contents, X, blimit)){ size +=1; }
+ else if(U_PMF_INTEGER15_get(contents, X, blimit)){ size +=2; }
else { return(0); }
- if( U_PMF_INTEGER7_get( contents, Y)){ size +=1; }
- else if(U_PMF_INTEGER15_get(contents, Y)){ size +=2; }
+ if( U_PMF_INTEGER7_get( contents, Y, blimit)){ size +=1; }
+ else if(U_PMF_INTEGER15_get(contents, Y, blimit)){ size +=2; }
else { return(0); }
return(size);
@@ -6332,31 +6552,38 @@ int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y){
\param Flags Record flags (bits U_PPF_C and U_PPF_P are referenced)
\param Elements Number of points to retrieve.
\param Points Caller must free. Array of U_PMF_POINTF coordinates.
+ \param blimit one byte past the end of data
+
+ This function should never be called directly by end user code.
*/
-int U_PMF_VARPOINTS_get(const char **contents, uint16_t Flags, int Elements, U_PMF_POINTF **Points){
+int U_PMF_VARPOINTS_get(const char *contents, uint16_t Flags, int Elements, U_PMF_POINTF **Points, const char *blimit){
int status = 0;
- if(!contents || !*contents || !Points || !Elements){ return(status); }
+ if(!contents || !Points || !Elements || !blimit){ return(status); }
U_PMF_POINTF *pts = (U_PMF_POINTF *)malloc(Elements * sizeof(U_PMF_POINTF));
if(!pts){ return(status); }
*Points = pts;
U_FLOAT XF, YF;
U_FLOAT XFS, YFS;
- for(XFS = YFS = 0.0; Elements; Elements--, pts++){
- if(Flags & U_PPF_P){
- if(!U_PMF_POINTR_get(contents, &XF, &YF))break; /* this should never happen */
+ if(Flags & U_PPF_P){
+ for(XFS = YFS = 0.0; Elements; Elements--, pts++){
+ if(!U_PMF_POINTR_get(&contents, &XF, &YF, blimit))return(0); /* this should never happen */
XFS += XF; /* position relative to previous point, first point is always 0,0 */
YFS += YF;
pts->X = XFS;
pts->Y = YFS;
}
- else if(Flags & U_PPF_C){
- if(!U_PMF_POINT_get(contents, &XF, &XF))break; /* this should never happen */
+ }
+ else if(Flags & U_PPF_C){
+ for(XFS = YFS = 0.0; Elements; Elements--, pts++){
+ if(!U_PMF_POINT_get(&contents, &XF, &XF, blimit))break; /* this should never happen */
pts->X = XF;
pts->Y = YF;
}
- else {
- (void) U_PMF_POINTF_get(contents, &(pts->X), &(pts->Y));
+ }
+ else {
+ for(XFS = YFS = 0.0; Elements; Elements--, pts++){
+ (void) U_PMF_POINTF_get(&contents, &(pts->X), &(pts->Y), blimit);
}
}
if(Elements){ /* some error in the preceding */
@@ -6377,11 +6604,13 @@ int U_PMF_VARPOINTS_get(const char **contents, uint16_t Flags, int Elements, U_P
\param Y UL Y value
\param Width Width
\param Height Height
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
*/
-int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height){
+int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit){
if(!contents || !X || !Y|| !Width || !Height){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 2*4, blimit))return(0);
U_PMF_SERIAL_get(contents, X, 2, 1, U_LE);
U_PMF_SERIAL_get(contents, Y, 2, 1, U_LE);
U_PMF_SERIAL_get(contents, Width, 2, 1, U_LE);
@@ -6397,11 +6626,13 @@ int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width
\param Y UL Y value
\param Width Width
\param Height Height
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
*/
-int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height){
+int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit){
if(!contents || !X || !Y|| !Width || !Height){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 4*4, blimit))return(0);
U_PMF_SERIAL_get(contents, X, 4, 1, U_LE);
U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE);
U_PMF_SERIAL_get(contents, Width, 4, 1, U_LE);
@@ -6416,13 +6647,14 @@ int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Widt
\param Flags Record flags (bit U_PPF_C is referenced)
\param Elements Number of rects to retrieve.
\param Rects Caller must free. Array of U_PMF_RECTF coordinates.
+ \param blimit one byte past the end of data
Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always
returns U_PMF_RECTF
*/
-int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PMF_RECTF **Rects){
+int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PMF_RECTF **Rects, const char *blimit){
int16_t X16, Y16, Width, Height;
- if(!contents || !*contents || !Rects){ return(0); }
+ if(!contents || !*contents || !Rects || !blimit){ return(0); }
U_PMF_RECTF *rts = (U_PMF_RECTF *)malloc(Elements * sizeof(U_PMF_RECTF));
if(!rts){
*Rects = NULL;
@@ -6430,16 +6662,28 @@ int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PM
}
*Rects = rts;
+ if(Flags & U_PPF_C){
+ if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){
+ free(rts);
+ return(0);
+ }
+ }
+ else {
+ if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){
+ free(rts);
+ return(0);
+ }
+ }
for(; Elements; Elements--, rts++){
if(Flags & U_PPF_C){
- (void) U_PMF_RECT_get(contents, &X16, &Y16, &Width, &Height);
+ (void) U_PMF_RECT_get(contents, &X16, &Y16, &Width, &Height, blimit);
rts->X = X16;
rts->Y = Y16;
rts->Width = Width;
rts->Height = Height;
}
else {
- (void) U_PMF_RECTF_get(contents, &(rts->X), &(rts->Y), &(rts->Width), &(rts->Height));
+ (void) U_PMF_RECTF_get(contents, &(rts->X), &(rts->Y), &(rts->Width), &(rts->Height), blimit);
}
}
return(1);
@@ -6451,13 +6695,18 @@ int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PM
\param contents Record from which to extract data
\param Type RegionNodeDataType
\param Data Depending on Type: U_PMF_REGIONNODEPATH, U_PMF_RECTF, or U_PMF_REGIONNODECHILDNODES
-
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data){
- if(!contents || !Type|| !Data){ return(0); }
+int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Type || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODE), blimit))return(0);
U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
U_PMF_PTRSAV_COND(Data, contents, !(*Type == U_RNDT_Empty || *Type == U_RNDT_Infinite ));
return(1);
}
@@ -6481,12 +6730,16 @@ int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data
\param contents Record from which to extract data
\param Size Bytes in Data
\param Data Boundary of region node
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object
*/
-int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data){
- if(!contents || !Size || !Data){ return(0); }
+int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODEPATH), blimit))return(0);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -6496,11 +6749,13 @@ int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **D
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param Color Color of brush
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
*/
-int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color){
- if(!contents || !Color){ return(0); }
+int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit){
+ if(!contents || !Color || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_SOLIDBRUSHDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Color, 4, 1, U_XE);
return(1);
}
@@ -6513,12 +6768,14 @@ int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color){
\param RangeCount Entries in CharRange array
\param TabStops Array of tabstop locations
\param CharRange Array of character ranges in the text
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
*/
int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount,
- const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange){
- if(!contents || !TabStops|| !CharRange){ return(0); }
+ const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit){
+ if(!contents || !TabStops|| !CharRange || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, (TabStopCount + 2*RangeCount)*4, blimit))return(0);
*TabStops = NULL;
if(TabStopCount > 0){ U_PMF_SERIAL_get(&contents, TabStops, 4, TabStopCount, U_LE); }
*CharRange = NULL;
@@ -6533,13 +6790,19 @@ int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint
\param Flags BrushData flags
\param WrapMode WrapMode enumeration
\param Data Optional texture data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object
+
+ Caller must check Data for possible memory access violations.
*/
-int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data){
- if(!contents || !Flags || !WrapMode || !Data){ return(0); }
+int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit){
+ if(!contents || !Flags || !WrapMode || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TEXTUREBRUSHDATA), blimit))return(0);
U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -6549,16 +6812,25 @@ int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *W
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param HasImage True if this object has an Image
- \param Matrix Transformation matrix, present if Flag BrushDataTransform is set.
+ \param Matrix Transformation matrix, NULL if Flag BrushDataTransform is not set.
\param Image Image that contains the texture.
-
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
+
+ Caller must check Image for possible memory access violations.
*/
-int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, const char **Image){
- if(!contents || !Matrix || !Image){ return(0); }
- U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
- U_PMF_PTRSAV_COND(Image, contents, HasImage);
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix,
+ const char **Image, const char *blimit){
+ if(!contents || !Image || !blimit){ return(0); }
+ if(Matrix){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(HasImage){
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
+ U_PMF_PTRSAV_COND(Image, contents, HasImage);
+ }
return(1);
}
@@ -6567,11 +6839,13 @@ int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param Matrix Transformation matrix, present if Flag BrushDataTransform is set.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
*/
-int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix){
- if(!contents || !Matrix){ return(0); }
+int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit){
+ if(!contents || !Matrix || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
return(1);
}
@@ -6582,11 +6856,13 @@ int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matri
\param contents Record from which to extract data
\param Radius Blur radius in pixels
\param ExpandEdge 1: expand bitmap by Radius; 0: bitmap size unchanged
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object
*/
-int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge){
- if(!contents || !Radius || !ExpandEdge){ return(0); }
+int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit){
+ if(!contents || !Radius || !ExpandEdge || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BLUR), blimit))return(0);
U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, ExpandEdge, 4, 1, U_LE);
return(1);
@@ -6598,11 +6874,13 @@ int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdg
\param contents Record from which to extract data
\param Brightness -255 to 255, 0 is unchanged, positive increases, negative decreases
\param Contrast -100 to 100, 0 is unchanged, positive increases, negative decreases
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object
*/
-int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast){
- if(!contents || !Brightness || !Contrast){ return(0); }
+int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit){
+ if(!contents || !Brightness || !Contrast || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BRIGHTNESSCONTRAST), blimit))return(0);
U_PMF_SERIAL_get(&contents, Brightness, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Contrast, 4, 1, U_LE);
return(1);
@@ -6615,11 +6893,13 @@ int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, i
\param CyanRed -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite
\param MagentaGreen -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite
\param YellowBlue -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object
*/
-int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue){
- if(!contents || !CyanRed || !MagentaGreen || !YellowBlue){ return(0); }
+int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit){
+ if(!contents || !CyanRed || !MagentaGreen || !YellowBlue || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORBALANCE), blimit))return(0);
U_PMF_SERIAL_get(&contents, CyanRed, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, MagentaGreen, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, YellowBlue, 4, 1, U_LE);
@@ -6634,11 +6914,13 @@ int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *M
\param Adjust CurveAdjustment enumeration
\param Channel CurveChannel enumeration
\param Intensity adjustment to apply. "Adjust" determines what field this is and range values.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
*/
-int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity){
- if(!contents || !Adjust || !Channel || !Intensity){ return(0); }
+int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit){
+ if(!contents || !Adjust || !Channel || !Intensity || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORCURVE), blimit))return(0);
U_PMF_SERIAL_get(&contents, Adjust, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Channel, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Intensity, 4, 1, U_LE);
@@ -6653,12 +6935,14 @@ int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Ch
\param GLUT Green color lookup table
\param RLUT Red color lookup table
\param ALUT Alpha color lookup table
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object
*/
int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents,
- const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT){
- if(!contents || !BLUT || !GLUT || !RLUT || !ALUT){ return(0); }
+ const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit){
+ if(!contents || !BLUT || !GLUT || !RLUT || !ALUT || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORLOOKUPTABLE) + 4 * 256, blimit))return(0);
U_PMF_PTRSAV_SHIFT((const char **)BLUT, &contents, 256);
U_PMF_PTRSAV_SHIFT((const char **)GLUT, &contents, 256);
U_PMF_PTRSAV_SHIFT((const char **)RLUT, &contents, 256);
@@ -6671,11 +6955,14 @@ int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents,
\return 1 on success, 0 on error
\param contents Record from which to extract data
\param Matrix 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0]
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object
*/
-int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix){
- if(!contents || !Matrix){ return(0); }
+int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit){
+ if(!contents || !Matrix || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORMATRIX), blimit))return(0);
U_PMF_SERIAL_get(&contents, Matrix, 4, 5*5, U_LE);
return(1);
}
@@ -6687,11 +6974,13 @@ int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix)
\param Hue -180 to 180, 0 is unchanged
\param Saturation -100 to 100, 0 is unchanged
\param Lightness -100 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object
*/
-int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness){
- if(!contents || !Hue || !Saturation || !Lightness){ return(0); }
+int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit){
+ if(!contents || !Hue || !Saturation || !Lightness || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS), blimit))return(0);
U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Saturation, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Lightness, 4, 1, U_LE);
@@ -6705,11 +6994,13 @@ int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int3
\param Highlight 0 to 100, 100 is unchanged
\param Midtone -100 to 100, 0 is unchanged
\param Shadow 0 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object
*/
-int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow){
- if(!contents || !Highlight || !Midtone || !Shadow){ return(0); }
+int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit){
+ if(!contents || !Highlight || !Midtone || !Shadow || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_LEVELS), blimit))return(0);
U_PMF_SERIAL_get(&contents, Highlight, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Midtone, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Shadow, 4, 1, U_LE);
@@ -6722,12 +7013,15 @@ int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midto
\param contents Record from which to extract data
\param Elements Number of members in Rects
\param Rects Caller must free. Pointer to memory holding an array of U_RECTL.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object
*/
-int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects){
- if(!contents || !Elements || !Rects){ return(0); }
+int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit){
+ if(!contents || !Elements || !Rects || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_REDEYECORRECTION), blimit))return(0);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0);
*Rects = (U_RECTL *) malloc(*Elements * sizeof(U_RECTL));
if(!*Rects){ return(0); }
U_PMF_SERIAL_get(&contents, *Rects, 4, *Elements * 4, U_LE);
@@ -6740,11 +7034,13 @@ int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_REC
\param contents Record from which to extract data
\param Radius Sharpening radius in pixels
\param Sharpen 0 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object
*/
-int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen){
- if(!contents || !Radius || !Sharpen){ return(0); }
+int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit){
+ if(!contents || !Radius || !Sharpen || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_SHARPEN), blimit))return(0);
U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Sharpen, 4, 1, U_LE);
return(1);
@@ -6756,16 +7052,51 @@ int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen
\param contents Record from which to extract data
\param Hue -180 to 180, [positive==clockwise] rotation in degrees starting from blue
\param Amount -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object
*/
-int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount){
- if(!contents || !Hue || !Amount){ return(0); }
+int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit){
+ if(!contents || !Hue || !Amount || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_TINT), blimit))return(0);
U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Amount, 4, 1, U_LE);
return(1);
}
+/*
+
+ end of U_PMF_*_get() functions
+ =====================================================================================
+ start of U_PMR_*_get() functions
+
+ These functions all assume that the size field in the common EMF+ header has already
+ been checked, so that the extent the record claims exists in the data read in for the file.
+ Consequently none of them takes a blimit parameter. They generate a new one from the
+ header size field and contents if needed.
+
+*/
+
+int U_PMR_common_stack_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ if(!contents || !StackID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_RESTORE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
+ return(1);
+}
+
+/* for records that have a type but no associated flag bits or data */
+int U_PMR_common_header_get(const char *contents, U_PMF_CMN_HDR *Header){
+ /* memory access safe, only uses the common header */
+ if(!contents){ return(0); }
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
/**
\brief Get data from a U_PMR_OFFSETCLIP record
\return 1 on success, 0 on error
@@ -6779,7 +7110,12 @@ int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount){
int U_PMR_OFFSETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header,
U_FLOAT *dX, U_FLOAT *dY){
if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_OFFSETCLIP))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_SERIAL_get(&contents, dX, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, dY, 4, 1, U_LE);
return(1);
@@ -6812,10 +7148,14 @@ int U_PMR_RESETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header){
int U_PMR_SETCLIPPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *PathID, int *CMenum){
if(!contents || !PathID || !CMenum){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *CMenum = (Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
- *PathID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
return(1);
}
@@ -6833,9 +7173,13 @@ int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header,
int *CMenum,
U_PMF_RECTF *Rect){
if(!contents || !CMenum || !Rect ){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *CMenum = (Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPRECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
return(1);
}
@@ -6853,10 +7197,14 @@ int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *PathID, int *CMenum){
if(!contents || !PathID || !CMenum){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *CMenum = (Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
- *PathID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
return(1);
}
@@ -6868,11 +7216,18 @@ int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
\param Data Private data, may be anything
EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03
+
+ Caller must check Data for possible memory access violations.
*/
int U_PMR_COMMENT_get(const char *contents, U_PMF_CMN_HDR *Header,
const char **Data){
if(!contents || !Data){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_COMMENT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
return(1);
}
@@ -6922,9 +7277,13 @@ int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header,
U_PMF_GRAPHICSVERSION *Version, int *IsDual, int *IsVideo, uint32_t *LogicalDpiX, uint32_t *LogicalDpiY){
if(!contents || !Version || !IsDual || !IsVideo || !LogicalDpiX || !LogicalDpiY){ return(0); }
uint32_t tmp;
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *IsDual = (Flags & U_PPF_DM ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_HEADER))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *IsDual = (lclHeader.Flags & U_PPF_DM ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, &tmp, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, LogicalDpiX, 4, 1, U_LE);
@@ -6945,7 +7304,12 @@ int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_CLEAR_get(const char *contents, U_PMF_CMN_HDR *Header,
U_PMF_ARGB *Color){
if(!contents || !Color){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_CLEAR))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_SERIAL_get(&contents, Color, 4, 1, U_LE);
return(1);
}
@@ -6968,16 +7332,26 @@ int U_PMR_DRAWARC_get(const char *contents, U_PMF_CMN_HDR *Header,
U_FLOAT *Start, U_FLOAT *Sweep,
U_PMF_RECTF *Rect){
if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWARC))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
- U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
return(1);
}
+
/**
\brief Get data from a U_PMR_DRAWBEZIERS record
\return 1 on success, 0 on error
@@ -6996,14 +7370,20 @@ int U_PMR_DRAWBEZIERS_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !PenID || !ctype || !RelAbs || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_P ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWBEZIERS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
- return(1);
+ int status = U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit );
+ return(status);
}
/**
@@ -7025,14 +7405,20 @@ int U_PMR_DRAWCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
U_FLOAT *Tension, uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !PenID || !ctype || !RelAbs || !Tension || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_P ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWCLOSEDCURVE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7056,15 +7442,21 @@ int U_PMR_DRAWCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
U_FLOAT *Tension, uint32_t *Offset, uint32_t *NSegs, uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !PenID || !ctype || !Tension || !Offset || !NSegs || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWCURVE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Offset, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, NSegs, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7092,15 +7484,22 @@ int U_PMR_DRAWDRIVERSTRING_get(const char *contents, U_PMF_CMN_HDR *Header,
uint16_t **Glyphs, U_PMF_POINTF **Points, U_PMF_TRANSFORMMATRIX **Matrix){
if(!contents || !FontID || !btype || !Tension || !BrushID ||
!DSOFlags || !HasMatrix || !Elements || !Glyphs || !Points || !Matrix){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *FontID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWDRIVERSTRING))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, DSOFlags, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, HasMatrix, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements*2 + *Elements*2*4 + 24, blimit))return(0);
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Glyphs, 2, *Elements, U_LE, (*DSOFlags & U_DSO_CmapLookup))){ return(0); }
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements *2, U_LE, (*DSOFlags & U_DSO_RealizedAdvance))){ return(0); }
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Matrix, 4, 6, U_LE, (*HasMatrix))){ return(0); }
@@ -7122,10 +7521,14 @@ int U_PMR_DRAWELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *PenID, int *ctype,
U_PMF_RECTF *Rect){
if(!contents || !PenID || !ctype || !Rect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWELLIPSE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
return(1);
}
@@ -7149,10 +7552,14 @@ int U_PMR_DRAWIMAGE_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect,
U_PMF_RECTF *DstRect){
if(!contents || !ImgID || !ctype || !ImgAttrID || !SrcUnit || !SrcRect || !DstRect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *ImgID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
@@ -7182,17 +7589,23 @@ int U_PMR_DRAWIMAGEPOINTS_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !ImgID || !ctype || !etype || !RelAbs || !ImgAttrID || !SrcUnit || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *etype = (Flags & U_PPF_E ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_P ? 1 : 0 );
- *ImgID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGEPOINTS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *etype = (lclHeader.Flags & U_PPF_E ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7215,14 +7628,20 @@ int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !PenID || !ctype || !dtype || !RelAbs || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *dtype = (Flags & U_PPF_D ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_P ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *dtype = (lclHeader.Flags & U_PPF_D ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7239,9 +7658,13 @@ int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_DRAWPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *PathID, uint32_t *PenID){
if(!contents || !PathID || !PenID){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *PathID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, PenID, 4, 1, U_LE);
return(1);
}
@@ -7264,13 +7687,22 @@ int U_PMR_DRAWPIE_get(const char *contents, U_PMF_CMN_HDR *Header,
U_FLOAT *Start, U_FLOAT *Sweep,
U_PMF_RECTF *Rect){
if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
- U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
return(1);
}
@@ -7294,12 +7726,18 @@ int U_PMR_DRAWRECTS_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *Elements,
U_PMF_RECTF **Rects){
if(!contents || !PenID || !Elements || !Rects){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *PenID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARRECTS_get(&contents, Flags, *Elements, Rects);
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
return(1);
}
@@ -7323,14 +7761,21 @@ int U_PMR_DRAWSTRING_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID, uint32_t *FormatID, uint32_t *Elements, U_PMF_RECTF *Rect,
uint16_t **String){
if(!contents || !FontID || !btype || !BrushID || !FormatID || !Elements || !String){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *FontID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, FormatID, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0);
if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)String, 2, *Elements, U_XE, 1)){ return(0); }
return(1);
}
@@ -7356,16 +7801,22 @@ int U_PMR_FILLCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID, U_FLOAT *Tension, uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !btype || !ctype || !ftype || !RelAbs || !BrushID || !Tension || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *ftype = (Flags & U_PPF_F ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_P ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *ftype = (lclHeader.Flags & U_PPF_F ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7386,10 +7837,14 @@ int U_PMR_FILLELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID,
U_PMF_RECTF *Rect){
if(!contents || !btype || !ctype || !BrushID || !Rect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLELLIPSE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
return(1);
@@ -7412,10 +7867,14 @@ int U_PMR_FILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *PathID, int *btype,
uint32_t *BrushID){
if(!contents || !PathID || !btype || !BrushID){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *PathID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
return(1);
}
@@ -7439,14 +7898,23 @@ int U_PMR_FILLPIE_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID, U_FLOAT *Start, U_FLOAT *Sweep,
U_PMF_RECTF *Rect){
if(!contents || !btype || !ctype || !BrushID || !Start || !Sweep || !Rect){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
- U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
return(1);
}
@@ -7469,14 +7937,20 @@ int U_PMR_FILLPOLYGON_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID, uint32_t *Elements,
U_PMF_POINTF **Points){
if(!contents || !btype || !ctype || !RelAbs || !BrushID || !Elements || !Points){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *RelAbs = (Flags & U_PPF_R ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_R ? 1 : 0 );
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARPOINTS_get(&contents, Flags, *Elements, Points);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
return(1);
}
@@ -7505,13 +7979,19 @@ int U_PMR_FILLRECTS_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *BrushID, uint32_t *Elements,
U_PMF_RECTF **Rects){
if(!contents || !btype || !ctype || !BrushID || !Elements || !Rects){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLRECTS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
- U_PMF_VARRECTS_get(&contents, Flags, *Elements, Rects);
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
/* correct btype, if necessary, for invalid EMF+ input */
if((*BrushID > 63) & !*btype)*btype=1;
return(1);
@@ -7534,11 +8014,15 @@ int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *RgnID, int *btype, int *ctype,
uint32_t *BrushID){
if(!contents || !RgnID || !btype || !ctype || !BrushID){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *btype = (Flags & U_PPF_B ? 1 : 0 );
- *ctype = (Flags & U_PPF_C ? 1 : 0 );
- *RgnID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RgnID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
return(1);
}
@@ -7556,6 +8040,8 @@ int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+ Caller must check Data for possible memory access violations.
+
OTHER NOTES:
All objects are to be stored in the same table and retrieved by index.
Documentation indicates that this table contains only 64 slots, although the index
@@ -7585,11 +8071,15 @@ int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
uint32_t *ObjID, int *otype, int *ntype, uint32_t *TSize,
const char **Data){
if(!contents || !ObjID || !otype || !ntype || !Data){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ntype = (Flags & U_PPF_N ? 1 : 0 );
- *ObjID = (Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
- *otype = (Flags >> U_FF_SHFT_OT) & U_FF_MASK_OT;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_OBJECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ntype = (lclHeader.Flags & U_PPF_N ? 1 : 0 );
+ *ObjID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ *otype = (lclHeader.Flags >> U_FF_SHFT_OT) & U_FF_MASK_OT;
if(*ntype){ U_PMF_SERIAL_get(&contents, TSize, 4, 1, U_LE); }
else { *TSize = 0; }
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -7606,12 +8096,19 @@ int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
\param Data "Serialized image effects parameter block". One of the ImageEffects objects.
EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38
+
+ Caller must check Data for possible memory access violations.
*/
int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
uint8_t *GUID, uint32_t *Size,
const char **Data){
if(!contents || !GUID || !Size || !Data){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SERIALIZABLEOBJECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_SERIAL_get(&contents, GUID, 1, 16, U_XE);
U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
@@ -7631,10 +8128,14 @@ int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
int *SMenum, int *aatype){
if(!contents || !SMenum || !aatype){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *aatype = (Flags & U_PPF_AA ? 1 : 0 );
- *SMenum = (Flags >> U_FF_SHFT_AA) & U_FF_MASK_AA;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETANTIALIASMODE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *aatype = (lclHeader.Flags & U_PPF_AA ? 1 : 0 );
+ *SMenum = (lclHeader.Flags >> U_FF_SHFT_AA) & U_FF_MASK_AA;
return(1);
}
@@ -7649,6 +8150,7 @@ int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
int *CMenum){
+ /* memory access safe, only uses the common header */
if(!contents || !CMenum){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*CMenum = (Flags >> U_FF_SHFT_CM) & U_FF_MASK_CM;
@@ -7667,6 +8169,7 @@ int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header,
int *CQenum){
+ /* memory access safe, only uses the common header */
if(!contents || !CQenum){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*CQenum = (Flags >> U_FF_SHFT_CQ) & U_FF_MASK_CQ;
@@ -7685,6 +8188,7 @@ int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
int *IMenum){
+ /* memory access safe, only uses the common header */
if(!contents || !IMenum){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*IMenum = (Flags >> U_FF_SHFT_IM) & U_FF_MASK_IM;
@@ -7703,6 +8207,7 @@ int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
int *POMenum){
+ /* memory access safe, only uses the common header */
if(!contents || !POMenum){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*POMenum = (Flags >> U_FF_SHFT_PxOffM) & U_FF_MASK_PxOffM;
@@ -7723,7 +8228,12 @@ int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header,
int32_t *X, int32_t *Y){
if(!contents || !X || !Y){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ if(!U_PMF_CMN_HDR_get(&contents, &lclHeader))return(0);
+ if(lclHeader.Size < sizeof(U_PMF_SETRENDERINGORIGIN))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_SERIAL_get(&contents, X, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Y, 4, 1, U_LE);
return(1);
@@ -7740,6 +8250,7 @@ int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header,
int *TGC){
+ /* memory access safe, only uses the common header */
if(!contents || !TGC){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*TGC = (Flags >> U_FF_SHFT_TGC) & U_FF_MASK_TGC;
@@ -7758,6 +8269,7 @@ int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header,
*/
int U_PMR_SETTEXTRENDERINGHINT_get(const char *contents, U_PMF_CMN_HDR *Header,
int *TRHenum){
+ /* memory access safe, only uses the common header */
if(!contents || !TRHenum){ return(0); }
uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
*TRHenum = (Flags >> U_FF_SHFT_TRH) & U_FF_MASK_TRH;
@@ -7781,9 +8293,13 @@ int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header,
int *UTenum,
U_PMF_RECTF *DstRect, U_PMF_RECTF *SrcRect, uint32_t *StackID){
if(!contents || !UTenum || !DstRect || !SrcRect || !StackID){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *UTenum = (Flags >> U_FF_SHFT_UT) & U_FF_MASK_UT;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *UTenum = (lclHeader.Flags >> U_FF_SHFT_UT) & U_FF_MASK_UT;
U_PMF_SERIAL_get(&contents, DstRect, 4, 4, U_LE);
U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
@@ -7800,10 +8316,7 @@ int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header,
EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28
*/
int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
- if(!contents || !StackID){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
- return(1);
+ return(U_PMR_common_stack_get(contents, Header, StackID));
}
/**
@@ -7815,12 +8328,8 @@ int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header
EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29
*/
-int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header,
- uint32_t *StackID){
- if(!contents || !StackID){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
- return(1);
+int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ return(U_PMR_common_stack_get(contents, Header, StackID));
}
/**
@@ -7833,10 +8342,7 @@ int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header,
EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26
*/
int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
- if(!contents || !StackID){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
- return(1);
+ return(U_PMR_common_stack_get(contents, Header, StackID));
}
/**
@@ -7849,10 +8355,7 @@ int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *Sta
EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25
*/
int U_PMR_SAVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
- if(!contents || !StackID){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
- return(1);
+ return(U_PMR_common_stack_get(contents, Header, StackID));
}
/**
@@ -7870,11 +8373,17 @@ int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header,
int *ctype, uint32_t *Elements,
U_PMF_RECTF **Rects){
if(!contents || !ctype || !Elements || !Rects){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *ctype = (Flags & U_PPF_K ? 1 : 0 );
- *Elements = (Flags >> U_FF_SHFT_TSC) & U_FF_MASK_TSC;
- U_PMF_CMN_HDR_get(&contents, Header);
- U_PMF_VARRECTS_get(&contents, Flags, *Elements, Rects);
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETTSCLIP))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_K ? 1 : 0 );
+ *Elements = (lclHeader.Flags >> U_FF_SHFT_TSC) & U_FF_MASK_TSC;
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
return(1);
}
@@ -7898,6 +8407,8 @@ int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header,
\param Data Palette (optional)
EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39
+
+ Caller must check Data for possible memory access violations.
*/
int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header,
int *vgatype, int *pptype,
@@ -7909,10 +8420,14 @@ int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header,
!AntiAliasMode || !TextRenderHint || !CompositingMode || !CompositingQuality ||
!RenderOriginX || !RenderOriginY || !TextContrast || !FilterType ||
!PixelOffset || !WorldToDevice || !Data){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *vgatype = (Flags & U_PPF_VGA ? 1 : 0 );
- *pptype = (Flags & U_PPF_PP ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETTSGRAPHICS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *vgatype = (lclHeader.Flags & U_PPF_VGA ? 1 : 0 );
+ *pptype = (lclHeader.Flags & U_PPF_PP ? 1 : 0 );
U_PMF_SERIAL_get(&contents, AntiAliasMode, 1, 1, U_XE);
U_PMF_SERIAL_get(&contents, TextRenderHint, 1, 1, U_XE);
U_PMF_SERIAL_get(&contents, CompositingMode, 1, 1, U_XE);
@@ -7940,9 +8455,13 @@ int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header
int *xmtype,
U_PMF_TRANSFORMMATRIX *Matrix){
if(!contents || !xmtype || !Matrix){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *xmtype = (Flags & U_PPF_XM ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_MULTIPLYWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
return(1);
}
@@ -7956,9 +8475,7 @@ int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header
EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B
*/
int U_PMR_RESETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header){
- if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- return(1);
+ return( U_PMR_common_header_get(contents,Header));
}
/**
@@ -7975,9 +8492,13 @@ int U_PMR_ROTATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
int *xmtype,
U_FLOAT *Angle){
if(!contents || !xmtype || !Angle){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *xmtype = (Flags & U_PPF_XM ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_ROTATEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Angle, 4, 1, U_LE);
return(1);
}
@@ -7997,9 +8518,13 @@ int U_PMR_SCALEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
int *xmtype,
U_FLOAT *Sx, U_FLOAT *Sy){
if(!contents || !xmtype || !Sx || !Sy){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *xmtype = (Flags & U_PPF_XM ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SCALEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Sx, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Sy, 4, 1, U_LE);
return(1);
@@ -8019,9 +8544,13 @@ int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
int *PUenum,
U_FLOAT *Scale){
if(!contents || !PUenum || !Scale){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *PUenum = (Flags >> U_FF_SHFT_PU) & U_FF_MASK_PU;
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETPAGETRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *PUenum = (lclHeader.Flags >> U_FF_SHFT_PU) & U_FF_MASK_PU;
U_PMF_SERIAL_get(&contents, Scale, 4, 1, U_LE);
return(1);
}
@@ -8038,7 +8567,12 @@ int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
int U_PMR_SETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
U_PMF_TRANSFORMMATRIX *Matrix){
if(!contents || !Matrix){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
return(1);
}
@@ -8058,9 +8592,13 @@ int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Heade
int *xmtype,
U_FLOAT *Dx, U_FLOAT *Dy){
if(!contents || !xmtype || !Dx || !Dy){ return(0); }
- uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
- *xmtype = (Flags & U_PPF_XM ? 1 : 0 );
- U_PMF_CMN_HDR_get(&contents, Header);
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_TRANSLATEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
U_PMF_SERIAL_get(&contents, Dx, 4, 1, U_LE);
U_PMF_SERIAL_get(&contents, Dy, 4, 1, U_LE);
return(1);
@@ -8079,9 +8617,7 @@ int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Heade
the path by using the current pen, and fills its interior by using the current brush."
*/
int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header){
- if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- return(1);
+ return( U_PMR_common_header_get(contents,Header));
}
/**
@@ -8093,9 +8629,7 @@ int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header){
EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatStart Record, Index 0x05
*/
int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header){
- if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- return(1);
+ return( U_PMR_common_header_get(contents,Header));
}
/**
@@ -8107,9 +8641,7 @@ int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header){
EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatSection Record, Index 0x06
*/
int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header){
- if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- return(1);
+ return( U_PMR_common_header_get(contents,Header));
}
/**
@@ -8121,9 +8653,7 @@ int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header){
EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatEnd Record, Index 0x06
*/
int U_PMR_MULTIFORMATEND_get(const char *contents, U_PMF_CMN_HDR *Header){
- if(!contents){ return(0); }
- U_PMF_CMN_HDR_get(&contents, Header);
- return(1);
+ return( U_PMR_common_header_get(contents,Header));
}
diff --git a/src/libuemf/upmf.h b/src/libuemf/upmf.h
index 27ac94a89..dbda02ba7 100644
--- a/src/libuemf/upmf.h
+++ b/src/libuemf/upmf.h
@@ -27,11 +27,11 @@
/*
File: upmf.h
-Version: 0.0.2
-Date: 04-NOV-2013
+Version: 0.0.4
+Date: 17-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2013 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifndef _UPMF_
@@ -1805,9 +1805,8 @@ typedef struct {
/** @brief EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
For U_PMF_LINEARGRADIENTBRUSHDATA data field
*/
-typedef struct {
- U_PMF_ROTMATRIX Matrix; //!< Rotation matrix, Manuals says that this should be Transformation matrix, but last two values are missing
-/* variable part of object, not part of structure.
+/* Entire object is variable and not part of a structure! U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA
+ U_PMF_ROTMATRIX Matrix; //!< Rotation matrix, Manuals says that this should be Transformation matrix, but last two values are missing
(various) pattern; //!< Presence and meaning depend on Flags field, see below
Flag values
@@ -1818,7 +1817,6 @@ typedef struct {
0 0 1 U_PMF_BLENDFACTORS
0 1 1 U_PMF_BLENDFACTORS, U_PMF_BLENDFACTORS
*/
-} U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA;
/** @brief EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object */
typedef struct {
@@ -1888,7 +1886,10 @@ typedef struct {
Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are:
bits 4-7 PathPointType flags
bits 0-3 PathPointType enumeration
+ @{
*/
+typedef uint8_t U_PMF_PATHPOINTTYPE; //!< EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+/** @} */
/** \defgroup U_PMF_PPTYPERLE PMF Run Length Encoded Path Point Types
@brief EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
@@ -2838,6 +2839,7 @@ void U_PMF_MEMCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size);
void U_PMF_REPCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size, size_t Reps);
void U_PMF_PTRSAV_SHIFT(const char **Dst, const char **Src, size_t Size);
uint16_t U_PMF_HEADERFLAGS_get(const char *contents);
+int U_PMF_RECORD_SIZE_get(const char *contents);
int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header);
int U_OID_To_OT(uint32_t OID);
int U_OID_To_BT(uint32_t OID);
@@ -3035,77 +3037,77 @@ U_PSEUDO_OBJ *U_PMR_STROKEFILLPATH_set(void);
/* EMF+ prototypes (objects_get) */
-int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data);
-int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data);
-int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit, int32_t *FSFlags, uint32_t *Length, const char **Data);
-int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data);
-int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, uint32_t *ObjectClamp);
-int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, const char **Points, const char **Types);
-int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush);
-int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes);
-int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data);
-int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha);
-int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data);
-int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data);
-int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors);
-int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors);
-int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points);
-int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length);
-int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths);
-int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data);
-int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad);
-int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data);
-int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData);
-int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths);
-int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY);
-int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion);
-int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background);
-int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value);
-int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value);
+int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit, int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit);
+int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, uint32_t *ObjectClamp, const char *blimit);
+int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, const char **Points, const char **Types, const char *blimit);
+int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit);
+int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit);
+int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit);
+int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit);
+int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit);
+int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit);
+int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit);
+int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit);
+int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit);
+int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit);
+int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit);
+int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit);
+int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit);
+int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit);
+int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit);
+int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit);
+int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit);
+int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit);
+int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit);
+int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit);
int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int *PriLId);
-int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data);
-int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm, const char **Bc, const char **BfH, const char **BfV);
-int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data);
-int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Data);
-int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, const char **Boundary, const char **Data);
-int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, const char **Pattern, const char **Data);
-int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type);
-int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt);
-int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data);
+int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit);
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm, const char **Bc, const char **BfH, const char **BfV, const char *blimit);
+int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit);
+int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Data, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, const char **Boundary, const char **Data, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, const char **Pattern, const char **Data, const char *blimit);
+int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit);
+int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit);
+int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit);
int U_PMF_PENOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix,
int32_t *StartCap, int32_t *EndCap, uint32_t *Join, U_FLOAT *MiterLimit, int32_t *Style, int32_t *DLCap, U_FLOAT *DLOffset,
- const char **DLData, int32_t *Alignment, const char **CmpndLineData, const char **CSCapData, const char **CECapData);
-int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y);
-int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y);
-int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y);
-int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height);
-int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height);
-int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data);
+ const char **DLData, int32_t *Alignment, const char **CmpndLineData, const char **CSCapData, const char **CECapData, const char *blimit);
+int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit);
+int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit);
+int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit);
/* There is no U_PMF_REGIONNODECHILDNODES_get, see the note in upmf.c */
-int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data);
-int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color);
+int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit);
int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount,
- const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange);
-int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data);
-int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, const char **Image);
-int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix);
-int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge);
-int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast);
-int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue);
-int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity);
+ const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit);
+int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit);
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, const char **Image, const char *blimit);
+int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit);
+int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit);
+int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit);
+int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit);
+int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit);
int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents,
- const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT);
-int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix);
-int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness);
-int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow);
-int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects);
-int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen);
-int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount);
+ const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit);
+int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit);
+int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit);
+int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit);
+int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit);
+int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit);
+int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit);
/* EMF+ prototypes (records_get) */
diff --git a/src/libuemf/upmf_print.c b/src/libuemf/upmf_print.c
index 13bbfade8..7d9598b0d 100644
--- a/src/libuemf/upmf_print.c
+++ b/src/libuemf/upmf_print.c
@@ -6,11 +6,11 @@
/*
File: upmf_print.c
-Version: 0.0.3
-Date: 24-MAR-2014
+Version: 0.0.5
+Date: 24-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
/* compiler options:
@@ -30,6 +30,7 @@ extern "C" {
#include <string.h>
#include "upmf_print.h"
#include "uemf_print.h"
+#include "uemf_safe.h"
//! \cond
@@ -49,7 +50,7 @@ int U_PMR_NODATAREC_print(const char *contents){
/*
this function is not visible in the API. Common routine used by many functions that draw points.
*/
-void U_PMF_VARPOINTS_print(const char **contents, int Flags, uint32_t Elements){
+void U_PMF_VARPOINTS_print(const char **contents, int Flags, uint32_t Elements, const char *blimit){
unsigned int i;
U_FLOAT Xpos, Ypos;
@@ -58,9 +59,9 @@ void U_PMF_VARPOINTS_print(const char **contents, int Flags, uint32_t Elements){
else { printf(" + Points(Float):"); }
for(Xpos = Ypos = i = 0; i<Elements; i++){
printf(" %d:",i);
- if( Flags & U_PPF_P){ (void) U_PMF_POINTR_print(contents, &Xpos, &Ypos); }
- else if(Flags & U_PPF_C){ (void) U_PMF_POINT_print(contents); }
- else { (void) U_PMF_POINTF_print(contents); }
+ if( Flags & U_PPF_P){ (void) U_PMF_POINTR_print(contents, &Xpos, &Ypos, blimit); }
+ else if(Flags & U_PPF_C){ (void) U_PMF_POINT_print(contents, blimit); }
+ else { (void) U_PMF_POINTF_print(contents, blimit); }
}
#if 0
int residual;
@@ -120,16 +121,23 @@ int U_PMF_VARBRUSHID_print(int btype, uint32_t BrushID){
\brief Print any EMF+ record
\returns record length for a normal record, 0 for EMREOF or , -1 for a bad record
\param contents pointer to a buffer holding this EMF+ record
- \param blimit one byte past the end of data of this EMF+ record
+ \param blimit one byte after this EMF+ record
\param recnum EMF number of this record in contents
- \param off Offset from the beginning of the EMF+ file.
+ \param off Offset from the beginning of the EMF+ file to the start of this record.
*/
int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int off){
int status;
+ int rstatus;
static U_OBJ_ACCUM ObjCont={NULL,0,0,0,0}; /* for keeping track of object continuation. These may
be split across multiple EMF Comment records */
U_PMF_CMN_HDR Header;
const char *contemp = contents;
+
+ /* Check that COMMON header data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range.
+ */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CMN_HDR), blimit))return(-1);
if(!U_PMF_CMN_HDR_get(&contemp, &Header)){return(-1);}
int type = Header.Type & U_PMR_TYPE_MASK; /* strip the U_PMR_RECFLAG bit, leaving the indexable part */
@@ -142,67 +150,72 @@ int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int
U_PMR_OBJECT_print(contents, blimit, &ObjCont, 1);
}
+ /* Check that the record size is OK, abort if not. */
+ if(Header.Size < sizeof(U_PMF_CMN_HDR) ||
+ IS_MEM_UNSAFE(contents, Header.Size, blimit))return(-1);
+
switch(type){
- case (U_PMR_HEADER): U_PMR_HEADER_print(contents); break;
- case (U_PMR_ENDOFFILE): U_PMR_ENDOFFILE_print(contents);
- U_OA_release(&ObjCont); break;
- case (U_PMR_COMMENT): U_PMR_COMMENT_print(contents); break;
- case (U_PMR_GETDC): U_PMR_GETDC_print(contents); break;
- case (U_PMR_MULTIFORMATSTART): U_PMR_MULTIFORMATSTART_print(contents); break;
- case (U_PMR_MULTIFORMATSECTION): U_PMR_MULTIFORMATSECTION_print(contents); break;
- case (U_PMR_MULTIFORMATEND): U_PMR_MULTIFORMATEND_print(contents); break;
- case (U_PMR_OBJECT): U_PMR_OBJECT_print(contents,blimit,&ObjCont,0); break;
- case (U_PMR_CLEAR): U_PMR_CLEAR_print(contents); break;
- case (U_PMR_FILLRECTS): U_PMR_FILLRECTS_print(contents, blimit); break;
- case (U_PMR_DRAWRECTS): U_PMR_DRAWRECTS_print(contents, blimit); break;
- case (U_PMR_FILLPOLYGON): U_PMR_FILLPOLYGON_print(contents); break;
- case (U_PMR_DRAWLINES): U_PMR_DRAWLINES_print(contents); break;
- case (U_PMR_FILLELLIPSE): U_PMR_FILLELLIPSE_print(contents); break;
- case (U_PMR_DRAWELLIPSE): U_PMR_DRAWELLIPSE_print(contents); break;
- case (U_PMR_FILLPIE): U_PMR_FILLPIE_print(contents); break;
- case (U_PMR_DRAWPIE): U_PMR_DRAWPIE_print(contents); break;
- case (U_PMR_DRAWARC): U_PMR_DRAWARC_print(contents); break;
- case (U_PMR_FILLREGION): U_PMR_FILLREGION_print(contents); break;
- case (U_PMR_FILLPATH): U_PMR_FILLPATH_print(contents); break;
- case (U_PMR_DRAWPATH): U_PMR_DRAWPATH_print(contents); break;
- case (U_PMR_FILLCLOSEDCURVE): U_PMR_FILLCLOSEDCURVE_print(contents); break;
- case (U_PMR_DRAWCLOSEDCURVE): U_PMR_DRAWCLOSEDCURVE_print(contents); break;
- case (U_PMR_DRAWCURVE): U_PMR_DRAWCURVE_print(contents); break;
- case (U_PMR_DRAWBEZIERS): U_PMR_DRAWBEZIERS_print(contents); break;
- case (U_PMR_DRAWIMAGE): U_PMR_DRAWIMAGE_print(contents); break;
- case (U_PMR_DRAWIMAGEPOINTS): U_PMR_DRAWIMAGEPOINTS_print(contents); break;
- case (U_PMR_DRAWSTRING): U_PMR_DRAWSTRING_print(contents); break;
- case (U_PMR_SETRENDERINGORIGIN): U_PMR_SETRENDERINGORIGIN_print(contents); break;
- case (U_PMR_SETANTIALIASMODE): U_PMR_SETANTIALIASMODE_print(contents); break;
- case (U_PMR_SETTEXTRENDERINGHINT): U_PMR_SETTEXTRENDERINGHINT_print(contents); break;
- case (U_PMR_SETTEXTCONTRAST): U_PMR_SETTEXTCONTRAST_print(contents); break;
- case (U_PMR_SETINTERPOLATIONMODE): U_PMR_SETINTERPOLATIONMODE_print(contents); break;
- case (U_PMR_SETPIXELOFFSETMODE): U_PMR_SETPIXELOFFSETMODE_print(contents); break;
- case (U_PMR_SETCOMPOSITINGMODE): U_PMR_SETCOMPOSITINGMODE_print(contents); break;
- case (U_PMR_SETCOMPOSITINGQUALITY): U_PMR_SETCOMPOSITINGQUALITY_print(contents); break;
- case (U_PMR_SAVE): U_PMR_SAVE_print(contents); break;
- case (U_PMR_RESTORE): U_PMR_RESTORE_print(contents); break;
- case (U_PMR_BEGINCONTAINER): U_PMR_BEGINCONTAINER_print(contents); break;
- case (U_PMR_BEGINCONTAINERNOPARAMS): U_PMR_BEGINCONTAINERNOPARAMS_print(contents); break;
- case (U_PMR_ENDCONTAINER): U_PMR_ENDCONTAINER_print(contents); break;
- case (U_PMR_SETWORLDTRANSFORM): U_PMR_SETWORLDTRANSFORM_print(contents); break;
- case (U_PMR_RESETWORLDTRANSFORM): U_PMR_RESETWORLDTRANSFORM_print(contents); break;
- case (U_PMR_MULTIPLYWORLDTRANSFORM): U_PMR_MULTIPLYWORLDTRANSFORM_print(contents); break;
- case (U_PMR_TRANSLATEWORLDTRANSFORM): U_PMR_TRANSLATEWORLDTRANSFORM_print(contents); break;
- case (U_PMR_SCALEWORLDTRANSFORM): U_PMR_SCALEWORLDTRANSFORM_print(contents); break;
- case (U_PMR_ROTATEWORLDTRANSFORM): U_PMR_ROTATEWORLDTRANSFORM_print(contents); break;
- case (U_PMR_SETPAGETRANSFORM): U_PMR_SETPAGETRANSFORM_print(contents); break;
- case (U_PMR_RESETCLIP): U_PMR_RESETCLIP_print(contents); break;
- case (U_PMR_SETCLIPRECT): U_PMR_SETCLIPRECT_print(contents); break;
- case (U_PMR_SETCLIPPATH): U_PMR_SETCLIPPATH_print(contents); break;
- case (U_PMR_SETCLIPREGION): U_PMR_SETCLIPREGION_print(contents); break;
- case (U_PMR_OFFSETCLIP): U_PMR_OFFSETCLIP_print(contents); break;
- case (U_PMR_DRAWDRIVERSTRING): U_PMR_DRAWDRIVERSTRING_print(contents); break;
- case (U_PMR_STROKEFILLPATH): U_PMR_STROKEFILLPATH_print(contents); break;
- case (U_PMR_SERIALIZABLEOBJECT): U_PMR_SERIALIZABLEOBJECT_print(contents); break;
- case (U_PMR_SETTSGRAPHICS): U_PMR_SETTSGRAPHICS_print(contents); break;
- case (U_PMR_SETTSCLIP): U_PMR_SETTSCLIP_print(contents); break;
- }
+ case (U_PMR_HEADER): rstatus = U_PMR_HEADER_print(contents); break;
+ case (U_PMR_ENDOFFILE): rstatus = U_PMR_ENDOFFILE_print(contents);
+ U_OA_release(&ObjCont); break;
+ case (U_PMR_COMMENT): rstatus = U_PMR_COMMENT_print(contents); break;
+ case (U_PMR_GETDC): rstatus = U_PMR_GETDC_print(contents); break;
+ case (U_PMR_MULTIFORMATSTART): rstatus = U_PMR_MULTIFORMATSTART_print(contents); break;
+ case (U_PMR_MULTIFORMATSECTION): rstatus = U_PMR_MULTIFORMATSECTION_print(contents); break;
+ case (U_PMR_MULTIFORMATEND): rstatus = U_PMR_MULTIFORMATEND_print(contents); break;
+ case (U_PMR_OBJECT): rstatus = U_PMR_OBJECT_print(contents,blimit,&ObjCont,0); break;
+ case (U_PMR_CLEAR): rstatus = U_PMR_CLEAR_print(contents); break;
+ case (U_PMR_FILLRECTS): rstatus = U_PMR_FILLRECTS_print(contents); break;
+ case (U_PMR_DRAWRECTS): rstatus = U_PMR_DRAWRECTS_print(contents); break;
+ case (U_PMR_FILLPOLYGON): rstatus = U_PMR_FILLPOLYGON_print(contents); break;
+ case (U_PMR_DRAWLINES): rstatus = U_PMR_DRAWLINES_print(contents); break;
+ case (U_PMR_FILLELLIPSE): rstatus = U_PMR_FILLELLIPSE_print(contents); break;
+ case (U_PMR_DRAWELLIPSE): rstatus = U_PMR_DRAWELLIPSE_print(contents); break;
+ case (U_PMR_FILLPIE): rstatus = U_PMR_FILLPIE_print(contents); break;
+ case (U_PMR_DRAWPIE): rstatus = U_PMR_DRAWPIE_print(contents); break;
+ case (U_PMR_DRAWARC): rstatus = U_PMR_DRAWARC_print(contents); break;
+ case (U_PMR_FILLREGION): rstatus = U_PMR_FILLREGION_print(contents); break;
+ case (U_PMR_FILLPATH): rstatus = U_PMR_FILLPATH_print(contents); break;
+ case (U_PMR_DRAWPATH): rstatus = U_PMR_DRAWPATH_print(contents); break;
+ case (U_PMR_FILLCLOSEDCURVE): rstatus = U_PMR_FILLCLOSEDCURVE_print(contents); break;
+ case (U_PMR_DRAWCLOSEDCURVE): rstatus = U_PMR_DRAWCLOSEDCURVE_print(contents); break;
+ case (U_PMR_DRAWCURVE): rstatus = U_PMR_DRAWCURVE_print(contents); break;
+ case (U_PMR_DRAWBEZIERS): rstatus = U_PMR_DRAWBEZIERS_print(contents); break;
+ case (U_PMR_DRAWIMAGE): rstatus = U_PMR_DRAWIMAGE_print(contents); break;
+ case (U_PMR_DRAWIMAGEPOINTS): rstatus = U_PMR_DRAWIMAGEPOINTS_print(contents); break;
+ case (U_PMR_DRAWSTRING): rstatus = U_PMR_DRAWSTRING_print(contents); break;
+ case (U_PMR_SETRENDERINGORIGIN): rstatus = U_PMR_SETRENDERINGORIGIN_print(contents); break;
+ case (U_PMR_SETANTIALIASMODE): rstatus = U_PMR_SETANTIALIASMODE_print(contents); break;
+ case (U_PMR_SETTEXTRENDERINGHINT): rstatus = U_PMR_SETTEXTRENDERINGHINT_print(contents); break;
+ case (U_PMR_SETTEXTCONTRAST): rstatus = U_PMR_SETTEXTCONTRAST_print(contents); break;
+ case (U_PMR_SETINTERPOLATIONMODE): rstatus = U_PMR_SETINTERPOLATIONMODE_print(contents); break;
+ case (U_PMR_SETPIXELOFFSETMODE): rstatus = U_PMR_SETPIXELOFFSETMODE_print(contents); break;
+ case (U_PMR_SETCOMPOSITINGMODE): rstatus = U_PMR_SETCOMPOSITINGMODE_print(contents); break;
+ case (U_PMR_SETCOMPOSITINGQUALITY): rstatus = U_PMR_SETCOMPOSITINGQUALITY_print(contents); break;
+ case (U_PMR_SAVE): rstatus = U_PMR_SAVE_print(contents); break;
+ case (U_PMR_RESTORE): rstatus = U_PMR_RESTORE_print(contents); break;
+ case (U_PMR_BEGINCONTAINER): rstatus = U_PMR_BEGINCONTAINER_print(contents); break;
+ case (U_PMR_BEGINCONTAINERNOPARAMS): rstatus = U_PMR_BEGINCONTAINERNOPARAMS_print(contents); break;
+ case (U_PMR_ENDCONTAINER): rstatus = U_PMR_ENDCONTAINER_print(contents); break;
+ case (U_PMR_SETWORLDTRANSFORM): rstatus = U_PMR_SETWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_RESETWORLDTRANSFORM): rstatus = U_PMR_RESETWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_MULTIPLYWORLDTRANSFORM): rstatus = U_PMR_MULTIPLYWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_TRANSLATEWORLDTRANSFORM): rstatus = U_PMR_TRANSLATEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_SCALEWORLDTRANSFORM): rstatus = U_PMR_SCALEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_ROTATEWORLDTRANSFORM): rstatus = U_PMR_ROTATEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_SETPAGETRANSFORM): rstatus = U_PMR_SETPAGETRANSFORM_print(contents); break;
+ case (U_PMR_RESETCLIP): rstatus = U_PMR_RESETCLIP_print(contents); break;
+ case (U_PMR_SETCLIPRECT): rstatus = U_PMR_SETCLIPRECT_print(contents); break;
+ case (U_PMR_SETCLIPPATH): rstatus = U_PMR_SETCLIPPATH_print(contents); break;
+ case (U_PMR_SETCLIPREGION): rstatus = U_PMR_SETCLIPREGION_print(contents); break;
+ case (U_PMR_OFFSETCLIP): rstatus = U_PMR_OFFSETCLIP_print(contents); break;
+ case (U_PMR_DRAWDRIVERSTRING): rstatus = U_PMR_DRAWDRIVERSTRING_print(contents); break;
+ case (U_PMR_STROKEFILLPATH): rstatus = U_PMR_STROKEFILLPATH_print(contents); break;
+ case (U_PMR_SERIALIZABLEOBJECT): rstatus = U_PMR_SERIALIZABLEOBJECT_print(contents); break;
+ case (U_PMR_SETTSGRAPHICS): rstatus = U_PMR_SETTSGRAPHICS_print(contents); break;
+ case (U_PMR_SETTSCLIP): rstatus = U_PMR_SETTSCLIP_print(contents); break;
+ }
+ if(!rstatus)status=-1;
return(status);
}
@@ -446,15 +459,16 @@ int U_PMF_NODETYPE_print(int Type){
\brief Print data from a U_PMF_BRUSH object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
*/
-int U_PMF_BRUSH_print(const char *contents){
+int U_PMF_BRUSH_print(const char *contents, const char *blimit){
uint32_t Version, Type;
const char *Data;
- int status = U_PMF_BRUSH_get(contents, &Version, &Type, &Data);
+ int status = U_PMF_BRUSH_get(contents, &Version, &Type, &Data, blimit);
if(status){
printf(" + Brush:");
- (void) U_PMF_GRAPHICSVERSION_print((char *)&Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" Type:%X(",Type);
(void) U_PMF_BRUSHTYPEENUMERATION_print(Type);
printf(")");
@@ -464,19 +478,19 @@ int U_PMF_BRUSH_print(const char *contents){
break;
case U_BT_HatchFill:
printf("\n");
- status = U_PMF_HATCHBRUSHDATA_print(Data);
+ status = U_PMF_HATCHBRUSHDATA_print(Data, blimit);
break;
case U_BT_TextureFill:
printf("\n");
- status = U_PMF_TEXTUREBRUSHDATA_print(Data);
+ status = U_PMF_TEXTUREBRUSHDATA_print(Data, blimit);
break;
case U_BT_PathGradient:
printf("\n");
- status = U_PMF_PATHGRADIENTBRUSHDATA_print(Data);
+ status = U_PMF_PATHGRADIENTBRUSHDATA_print(Data, blimit);
break;
case U_BT_LinearGradient:
printf("\n");
- status = U_PMF_LINEARGRADIENTBRUSHDATA_print(Data);
+ status = U_PMF_LINEARGRADIENTBRUSHDATA_print(Data, blimit);
break;
default:
status = 0;
@@ -491,23 +505,24 @@ int U_PMF_BRUSH_print(const char *contents){
\return 1 on success, 0 on error
\param contents Record from which to print data
\param Which A string which is either "Start" or "End".
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object
*/
-int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which){
+int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit){
uint32_t Version, Type;
const char *Data;
- int status = U_PMF_CUSTOMLINECAP_get(contents, &Version, &Type, &Data);
+ int status = U_PMF_CUSTOMLINECAP_get(contents, &Version, &Type, &Data, blimit);
if(status){
printf(" + %sLineCap:",Which);
- (void) U_PMF_GRAPHICSVERSION_print((char *)&Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(", Type %X\n",Type);
switch(Type){
case U_CLCDT_Default:
- status = U_PMF_CUSTOMLINECAPDATA_print(Data);
+ status = U_PMF_CUSTOMLINECAPDATA_print(Data, blimit);
break;
case U_CLCDT_AdjustableArrow:
- status = U_PMF_CUSTOMLINECAPARROWDATA_print(Data);
+ status = U_PMF_CUSTOMLINECAPARROWDATA_print(Data, blimit);
break;
default:
status = 0;
@@ -520,18 +535,19 @@ int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which){
\brief Print data from a U_PMF_FONT object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object
*/
-int U_PMF_FONT_print(const char *contents){
+int U_PMF_FONT_print(const char *contents, const char *blimit){
uint32_t Version, SizeUnit, Length;
U_FLOAT EmSize;
int32_t FSFlags;
const char *Data;
char *string;
- int status = U_PMF_FONT_get(contents, &Version, &EmSize, &SizeUnit, &FSFlags, &Length, &Data);
+ int status = U_PMF_FONT_get(contents, &Version, &EmSize, &SizeUnit, &FSFlags, &Length, &Data, blimit);
if(status){
printf(" + Font:");
- (void) U_PMF_GRAPHICSVERSION_print((char *)&Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" EmSize:%f ", EmSize );
printf(" SizeUnit:%d ",SizeUnit);
printf(" FSFlags:%d ", FSFlags );
@@ -553,25 +569,27 @@ int U_PMF_FONT_print(const char *contents){
\brief Print data from a U_PMF_IMAGE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
+
EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object
*/
-int U_PMF_IMAGE_print(const char *contents){
+int U_PMF_IMAGE_print(const char *contents, const char *blimit){
uint32_t Version, Type;
const char *Data;
- int status = U_PMF_IMAGE_get(contents, &Version, &Type, &Data);
+ int status = U_PMF_IMAGE_get(contents, &Version, &Type, &Data, blimit);
if(status){
printf(" + Image:");
- (void) U_PMF_GRAPHICSVERSION_print((char *)&Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" Type:%X\n",Type);
switch(Type){
case U_IDT_Unknown:
printf(" + Unknown Image Type\n");
break;
case U_IDT_Bitmap:
- status = U_PMF_BITMAP_print(Data);
+ status = U_PMF_BITMAP_print(Data, blimit);
break;
case U_IDT_Metafile:
- status = U_PMF_METAFILE_print(Data);
+ status = U_PMF_METAFILE_print(Data, blimit);
break;
default:
status = 0;
@@ -585,15 +603,16 @@ int U_PMF_IMAGE_print(const char *contents){
\brief Print data from a U_PMF_IMAGEATTRIBUTES object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object
*/
-int U_PMF_IMAGEATTRIBUTES_print(const char *contents){
+int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit){
uint32_t Version, WrapMode, ClampColor, ObjectClamp;
- int status = U_PMF_IMAGEATTRIBUTES_get(contents, &Version, &WrapMode, &ClampColor, &ObjectClamp);
+ int status = U_PMF_IMAGEATTRIBUTES_get(contents, &Version, &WrapMode, &ClampColor, &ObjectClamp, blimit);
if(status){
printf(" + Image Attributes: ");
- (void) U_PMF_GRAPHICSVERSION_print((char *)&Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" WrapMode:%X", WrapMode);
printf(" ClampColor:%X", ClampColor);
printf(" ObjectClamp:%X\n", ObjectClamp);
@@ -607,20 +626,21 @@ int U_PMF_IMAGEATTRIBUTES_print(const char *contents){
\brief Print data from a U_PMF_PATH object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
*/
-int U_PMF_PATH_print(const char *contents){
+int U_PMF_PATH_print(const char *contents, const char *blimit){
unsigned int i, pos;
uint32_t Version, Count;
uint16_t Flags;
const char *Points;
const char *Types;
- int status = U_PMF_PATH_get(contents, &Version, &Count, &Flags, &Points, &Types);
+ int status = U_PMF_PATH_get(contents, &Version, &Count, &Flags, &Points, &Types, blimit);
if(status){
printf(" + Path: Version:%X Count:%d Flags:%X\n",Version, Count, Flags);
/* Points part */
- U_PMF_VARPOINTS_print(&Points, Flags, Count);
+ U_PMF_VARPOINTS_print(&Points, Flags, Count, blimit);
/* Types part */
printf(" + Types:");
@@ -631,12 +651,12 @@ int U_PMF_PATH_print(const char *contents){
is which type. */
if(Flags & U_PPF_R){
printf(" %u:",pos);
- pos += U_PMF_PATHPOINTTYPERLE_print(Types);
+ pos += U_PMF_PATHPOINTTYPERLE_print(Types, blimit);
Types+=2;
}
else {
printf(" %d:",i);
- (void) U_PMF_PATHPOINTTYPE_print(Types);
+ (void) U_PMF_PATHPOINTTYPE_print(Types, blimit);
Types++;
}
}
@@ -651,15 +671,15 @@ int U_PMF_PATH_print(const char *contents){
\param contents Record from which to print data
EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object
*/
-int U_PMF_PEN_print(const char *contents){
+int U_PMF_PEN_print(const char *contents, const char *blimit){
uint32_t Version, Type;
const char *PenData;
const char *Brush;
- int status = U_PMF_PEN_get(contents, &Version, &Type, &PenData, &Brush);
+ int status = U_PMF_PEN_get(contents, &Version, &Type, &PenData, &Brush, blimit);
if(status){
printf(" + Pen: Version:%X Type:%d\n",Version,Type);
- (void) U_PMF_PENDATA_print(PenData);
- (void) U_PMF_BRUSH_print(Brush);
+ (void) U_PMF_PENDATA_print(PenData, blimit);
+ (void) U_PMF_BRUSH_print(Brush, blimit);
}
return(status);
}
@@ -668,17 +688,19 @@ int U_PMF_PEN_print(const char *contents){
\brief Print data from a U_PMF_REGION object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
+
EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object
*/
-int U_PMF_REGION_print(const char *contents){
+int U_PMF_REGION_print(const char *contents, const char *blimit){
uint32_t Version, Count;
const char *Nodes;
- int status = U_PMF_REGION_get(contents, &Version, &Count, &Nodes);
+ int status = U_PMF_REGION_get(contents, &Version, &Count, &Nodes, blimit);
if(status){
printf(" + ");
- (void) U_PMF_GRAPHICSVERSION_print((char *) &Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" ChildNodes:%d",Count);
- (void) U_PMF_REGIONNODE_print(Nodes, 1); /* 1 == top level*/
+ (void) U_PMF_REGIONNODE_print(Nodes, 1, blimit); /* 1 == top level*/
}
return(status);
}
@@ -687,12 +709,13 @@ int U_PMF_REGION_print(const char *contents){
\brief Print data from a U_PMF_STRINGFORMAT object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object
*/
-int U_PMF_STRINGFORMAT_print(const char *contents){
+int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit){
U_PMF_STRINGFORMAT Sfs;
const char *Data;
- int status = U_PMF_STRINGFORMAT_get(contents, &Sfs, &Data);
+ int status = U_PMF_STRINGFORMAT_get(contents, &Sfs, &Data, blimit);
if(status){
printf(" + StringFormat: ");
printf(" Version:%X", Sfs.Version );
@@ -710,7 +733,7 @@ int U_PMF_STRINGFORMAT_print(const char *contents){
printf(" Trimming:%X", Sfs.Trimming );
printf(" TabStopCount:%u", Sfs.TabStopCount );
printf(" RangeCount:%u", Sfs.RangeCount );
- (void) U_PMF_STRINGFORMATDATA_print(Data, Sfs.TabStopCount, Sfs.RangeCount);
+ (void) U_PMF_STRINGFORMATDATA_print(Data, Sfs.TabStopCount, Sfs.RangeCount, blimit);
}
return(status);
}
@@ -719,11 +742,13 @@ int U_PMF_STRINGFORMAT_print(const char *contents){
\brief Print data from a U_PMF_ARGB object
\return 1 on success, 0 on error
\param contents Record from which to print data
+
+ Does not accept a blimit value.
EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
*/
int U_PMF_ARGB_print(const char *contents){
uint8_t Blue, Green, Red, Alpha;
- int status = U_PMF_ARGB_get(contents, &Blue, &Green, &Red, &Alpha);
+ int status = U_PMF_ARGB_get(contents, &Blue, &Green, &Red, &Alpha, contents + sizeof(U_RGBQUAD));
if(status){
printf(" RGBA{%2.2X,%2.2X,%2.2X,%2.2X}", Red, Green, Blue, Alpha);
}
@@ -735,12 +760,13 @@ int U_PMF_ARGB_print(const char *contents){
\brief Print data from a U_PMF_BITMAP object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object
*/
-int U_PMF_BITMAP_print(const char *contents){
+int U_PMF_BITMAP_print(const char *contents, const char *blimit){
U_PMF_BITMAP Bs;
const char *Data;
- int status = U_PMF_BITMAP_get(contents, &Bs, &Data);
+ int status = U_PMF_BITMAP_get(contents, &Bs, &Data, blimit);
if(status){
printf(" + Bitmap: Width:%d Height:%d Stride:%d\n",Bs.Width, Bs.Height, Bs.Stride);
U_PMF_PX_FMT_ENUM_print(Bs.PxFormat);
@@ -759,14 +785,15 @@ int U_PMF_BITMAP_print(const char *contents){
\brief Print data from a U_PMF_BITMAPDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
*/
-int U_PMF_BITMAPDATA_print(const char *contents){
+int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit){
unsigned int i;
U_PMF_PALETTE Ps;
const char *Colors;
const char *Data;
- int status = U_PMF_BITMAPDATA_get(contents, &Ps, &Colors, &Data);
+ int status = U_PMF_BITMAPDATA_get(contents, &Ps, &Colors, &Data, blimit);
if(status){
status = 0;
printf(" BMData: Flags:%X, Elements:%u Colors:", Ps.Flags, Ps.Elements);
@@ -781,14 +808,15 @@ int U_PMF_BITMAPDATA_print(const char *contents){
\brief Print data from a U_PMF_BLENDCOLORS object
\return size in bytes on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
*/
-int U_PMF_BLENDCOLORS_print(const char *contents){
+int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit){
unsigned int i;
uint32_t Elements;
U_FLOAT *Positions;
const char *Colors;
- int status = U_PMF_BLENDCOLORS_get(contents, &Elements, &Positions, &Colors);
+ int status = U_PMF_BLENDCOLORS_get(contents, &Elements, &Positions, &Colors, blimit);
if(status){
printf(" + BlendColors: Entries:%d (entry,pos,color): ", Elements);
for(i=0; i<Elements; i++){
@@ -808,14 +836,15 @@ int U_PMF_BLENDCOLORS_print(const char *contents){
\return size on success, 0 on error
\param type Type of BlendFactors, usually H or V
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
*/
-int U_PMF_BLENDFACTORS_print(const char *contents, const char *type){
+int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit){
unsigned int i;
uint32_t Elements;
U_FLOAT *Positions;
U_FLOAT *Factors;
- int status = U_PMF_BLENDFACTORS_get(contents, &Elements, &Positions, &Factors);
+ int status = U_PMF_BLENDFACTORS_get(contents, &Elements, &Positions, &Factors, blimit);
if(status){
printf(" + BlendFactors%s: Entries:%d (entry,pos,factor): ",type, Elements);
for(i=0; i<Elements; i++){
@@ -832,15 +861,16 @@ int U_PMF_BLENDFACTORS_print(const char *contents, const char *type){
\brief Print data from a U_PMF_BOUNDARYPATHDATA object
\return size on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object
*/
-int U_PMF_BOUNDARYPATHDATA_print(const char *contents){
+int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char * blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_BOUNDARYPATHDATA_get(contents, &Size, &Data);
+ int status = U_PMF_BOUNDARYPATHDATA_get(contents, &Size, &Data, blimit);
if(status){
printf(" + BoundaryPathData: Size:%d\n",Size);
- (void) U_PMF_PATH_print(Data);
+ (void) U_PMF_PATH_print(Data, blimit);
}
return(status);
}
@@ -850,12 +880,13 @@ int U_PMF_BOUNDARYPATHDATA_print(const char *contents){
\brief Print data from a U_PMF_BOUNDARYPOINTDATA object
\return size on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object
*/
-int U_PMF_BOUNDARYPOINTDATA_print(const char *contents){
+int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit){
int32_t Elements;
U_PMF_POINTF *Points;
- int status = U_PMF_BOUNDARYPOINTDATA_get(contents, &Elements, &Points);
+ int status = U_PMF_BOUNDARYPOINTDATA_get(contents, &Elements, &Points, blimit);
if(status){
printf(" + BoundaryPointData: Elements:%u\n",Elements);
U_PMF_VARPOINTF_S_print(Points, Elements);
@@ -868,11 +899,12 @@ int U_PMF_BOUNDARYPOINTDATA_print(const char *contents){
\brief Print data from a U_PMF_CHARACTERRANGE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object
*/
-int U_PMF_CHARACTERRANGE_print(const char *contents){
+int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit){
int32_t First, Length;
- int status = U_PMF_CHARACTERRANGE_get(contents, &First, &Length);
+ int status = U_PMF_CHARACTERRANGE_get(contents, &First, &Length, blimit);
if(status){
printf(" {%d,%d}",First,Length);
}
@@ -882,14 +914,15 @@ int U_PMF_CHARACTERRANGE_print(const char *contents){
/**
\brief Print data from a U_PMF_DASHEDLINEDATA object
\return 1 on success, 0 on error
+ \param blimit one byte past the end of data
\param contents Record from which to print data
EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
*/
-int U_PMF_COMPOUNDLINEDATA_print(const char *contents){
+int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit){
int32_t Elements;
U_FLOAT *Widths;
U_FLOAT *hold;
- int status = U_PMF_COMPOUNDLINEDATA_get(contents, &Elements, &Widths);
+ int status = U_PMF_COMPOUNDLINEDATA_get(contents, &Elements, &Widths, blimit);
if(status){
printf(" + CompoundLineData: Elements:%u {",Elements);
Elements--;
@@ -905,13 +938,14 @@ int U_PMF_COMPOUNDLINEDATA_print(const char *contents){
\brief Print data from a U_PMF_COMPRESSEDIMAGE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object
This function does not do anything useful, but it is included so that all objects have a corresponding _get().
*/
-int U_PMF_COMPRESSEDIMAGE_print(const char *contents){
+int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit){
const char *Data;
- int status = U_PMF_COMPRESSEDIMAGE_get(contents, &Data);
+ int status = U_PMF_COMPRESSEDIMAGE_get(contents, &Data, blimit);
if(status){
printf("CompressedImage:\n");
}
@@ -922,15 +956,16 @@ int U_PMF_COMPRESSEDIMAGE_print(const char *contents){
\brief Print data from a U_PMF_CUSTOMENDCAPDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object
*/
-int U_PMF_CUSTOMENDCAPDATA_print(const char *contents){
+int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_CUSTOMENDCAPDATA_get(contents, &Size, &Data);
+ int status = U_PMF_CUSTOMENDCAPDATA_get(contents, &Size, &Data, blimit);
if(status){
printf(" + CustomEndCap: Size:%d\n",Size);
- (void) U_PMF_CUSTOMLINECAP_print(Data, "End");
+ (void) U_PMF_CUSTOMLINECAP_print(Data, "End", blimit);
}
return(status);
}
@@ -939,11 +974,12 @@ int U_PMF_CUSTOMENDCAPDATA_print(const char *contents){
\brief Print data from a U_PMF_CUSTOMLINECAPARROWDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object
*/
-int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents){
+int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit){
U_PMF_CUSTOMLINECAPARROWDATA Ccad;
- int status = U_PMF_CUSTOMLINECAPARROWDATA_get(contents, &Ccad);
+ int status = U_PMF_CUSTOMLINECAPARROWDATA_get(contents, &Ccad, blimit);
if(status){
printf("CustomLineCapArrowData: ");
printf(" Width:%f", Ccad.Width );
@@ -966,12 +1002,13 @@ int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents){
\brief Print data from a U_PMF_CUSTOMLINECAPDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object
*/
-int U_PMF_CUSTOMLINECAPDATA_print(const char *contents){
+int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit){
U_PMF_CUSTOMLINECAPDATA Clcd;
const char *Data;
- int status = U_PMF_CUSTOMLINECAPDATA_get(contents, &Clcd, &Data);
+ int status = U_PMF_CUSTOMLINECAPDATA_get(contents, &Clcd, &Data, blimit);
if(status){
printf(" + CustomLineCapData: ");
printf(" Flags:%X", Clcd.Flags );
@@ -984,7 +1021,7 @@ int U_PMF_CUSTOMLINECAPDATA_print(const char *contents){
printf(" WidthScale:%f", Clcd.WidthScale );
printf(" FillHotSpot:{%f,%f}",Clcd.FillHotSpot[0],Clcd.FillHotSpot[1]);
printf(" LineHotSpot:{%f,%f}\n",Clcd.LineHotSpot[0],Clcd.LineHotSpot[1]);
- (void) U_PMF_CUSTOMLINECAPOPTIONALDATA_print(Data, Clcd.Flags);
+ (void) U_PMF_CUSTOMLINECAPOPTIONALDATA_print(Data, Clcd.Flags, blimit);
/* preceding line always emits an EOL */
}
return(status);
@@ -996,18 +1033,19 @@ int U_PMF_CUSTOMLINECAPDATA_print(const char *contents){
\return 1 on success, 0 on error
\param contents Record from which to print data
\param Flags CustomLineCapData Flags
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
*/
-int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags){
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit){
const char *FillData;
const char *LineData;
- int status = U_PMF_CUSTOMLINECAPOPTIONALDATA_get(contents, Flags, &FillData, &LineData);
+ int status = U_PMF_CUSTOMLINECAPOPTIONALDATA_get(contents, Flags, &FillData, &LineData, blimit);
if(status){ /* True even if there is nothing in it! */
printf(" + CustomLineCapOptionalData:");
if(FillData || LineData){
- if(FillData){ (void) U_PMF_FILLPATHOBJ_print(FillData); }
- if(LineData){ (void) U_PMF_LINEPATH_print(LineData); }
+ if(FillData){ (void) U_PMF_FILLPATHOBJ_print(FillData, blimit); }
+ if(LineData){ (void) U_PMF_LINEPATH_print(LineData, blimit); }
}
else {
printf("None");
@@ -1021,15 +1059,16 @@ int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags){
\brief Print data from a U_PMF_CUSTOMSTARTCAPDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object
*/
-int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents){
+int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_CUSTOMSTARTCAPDATA_get(contents, &Size, &Data);
+ int status = U_PMF_CUSTOMSTARTCAPDATA_get(contents, &Size, &Data, blimit);
if(status){
printf(" + CustomStartCap: Size:%d ",Size);
- (void) U_PMF_CUSTOMLINECAP_print(Data, "Start");
+ (void) U_PMF_CUSTOMLINECAP_print(Data, "Start", blimit);
}
return(status);
}
@@ -1038,13 +1077,14 @@ int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents){
\brief Print data from a U_PMF_DASHEDLINEDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
*/
-int U_PMF_DASHEDLINEDATA_print(const char *contents){
+int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit){
int32_t Elements;
U_FLOAT *Lengths;
U_FLOAT *hold;
- int status = U_PMF_DASHEDLINEDATA_get(contents, &Elements, &Lengths);
+ int status = U_PMF_DASHEDLINEDATA_get(contents, &Elements, &Lengths, blimit);
if(status){
printf(" DashedLineData: Elements:%u {",Elements);
Elements--;
@@ -1059,15 +1099,16 @@ int U_PMF_DASHEDLINEDATA_print(const char *contents){
\brief Print data from a U_PMF_FILLPATHOBJ object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
*/
-int U_PMF_FILLPATHOBJ_print(const char *contents){
+int U_PMF_FILLPATHOBJ_print(const char *contents, const char * blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_FILLPATHOBJ_get(contents, &Size, &Data);
+ int status = U_PMF_FILLPATHOBJ_get(contents, &Size, &Data, blimit);
if(status){
printf(" FillPathObj: Size:%d\n",Size);
- if(Size){ (void) U_PMF_PATH_print(Data); }
+ if(Size){ (void) U_PMF_PATH_print(Data, blimit); }
}
return(status);
}
@@ -1076,12 +1117,13 @@ int U_PMF_FILLPATHOBJ_print(const char *contents){
\brief Print data from a U_PMF_FOCUSSCALEDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
*/
-int U_PMF_FOCUSSCALEDATA_print(const char *contents){
+int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit){
uint32_t Count;
U_FLOAT ScaleX, ScaleY;
- int status = U_PMF_FOCUSSCALEDATA_get(contents, &Count, &ScaleX, &ScaleY);
+ int status = U_PMF_FOCUSSCALEDATA_get(contents, &Count, &ScaleX, &ScaleY, blimit);
if(status){
printf(" FocusScaleData: Count:%d ScaleX:%f ScaleY:%f ",Count,ScaleX,ScaleY);
}
@@ -1089,14 +1131,31 @@ int U_PMF_FOCUSSCALEDATA_print(const char *contents){
}
/**
- \brief Print data from a U_PMF_GRAPHICSVERSION_print object
+ \brief Print data from a U_PMF_GRAPHICSVERSION object already known to be memory safe
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+
+ In this module the only time a U_PMF_GRAPHICSVERSION is printed is after it
+ has already been copied into a safe memory structure. This routine fakes up
+ a blimit for the general routine.
+
+*/
+int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents){
+ const char *blimit = contents + sizeof(U_PMF_GRAPHICSVERSION);
+ return(U_PMF_GRAPHICSVERSION_print(contents, blimit));
+}
+
+/**
+ \brief Print data from a U_PMF_GRAPHICSVERSION object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
*/
-int U_PMF_GRAPHICSVERSION_print(const char *contents){
+int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit){
int Signature,GrfVersion;
- int status = U_PMF_GRAPHICSVERSION_get(contents, &Signature, &GrfVersion);
+ int status = U_PMF_GRAPHICSVERSION_get(contents, &Signature, &GrfVersion, blimit);
if(status){
printf(" MetaFileSig:%X",Signature );
printf(" GraphicsVersion:%X", GrfVersion);
@@ -1106,15 +1165,16 @@ int U_PMF_GRAPHICSVERSION_print(const char *contents){
/**
- \brief Print data from a U_PMF_HATCHBRUSHDATA_print object
+ \brief Print data from a U_PMF_HATCHBRUSHDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit One byte past the last record in memory.
EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object
*/
-int U_PMF_HATCHBRUSHDATA_print(const char *contents){
+int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit){
uint32_t Style;
U_PMF_ARGB Foreground, Background;
- int status = U_PMF_HATCHBRUSHDATA_get(contents, &Style, &Foreground, &Background);
+ int status = U_PMF_HATCHBRUSHDATA_get(contents, &Style, &Foreground, &Background, blimit);
if(status){
printf(" + HBdata: Style:%u(",Style);
U_PMF_HATCHSTYLEENUMERATION_print(Style);
@@ -1148,12 +1208,13 @@ int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId){
\brief Print data from a U_PMF_LINEARGRADIENTBRUSHDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit One byte past the last record in memory.
EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
*/
-int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents){
+int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){
U_PMF_LINEARGRADIENTBRUSHDATA Lgbd;
const char *Data;
- int status = U_PMF_LINEARGRADIENTBRUSHDATA_get(contents, &Lgbd, &Data);
+ int status = U_PMF_LINEARGRADIENTBRUSHDATA_get(contents, &Lgbd, &Data, blimit);
if(status){
printf(" + LinearGradientBrushData: Flags:%X WrapMode:%d Rect:",Lgbd.Flags, Lgbd.WrapMode);
(void) U_PMF_RECTF_S_print(&(Lgbd.RectF));
@@ -1167,7 +1228,7 @@ int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents){
printf(" Reserved2:");
(void) U_PMF_ARGB_print((char *)&(Lgbd.Reserved2));
printf("\n");
- (void) U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(Data, Lgbd.Flags);
+ (void) U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(Data, Lgbd.Flags, blimit);
}
return(status);
}
@@ -1179,16 +1240,17 @@ int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents){
\return 1 on success, 0 on error
\param contents Record from which to print data
\param BDFlag Describes optional values in contents
+ \param blimit One byte past the last record in memory.
EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
*/
-int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag){
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){
U_PMF_TRANSFORMMATRIX Tm;
const char *Bc;
const char *BfH;
const char *BfV;
int None=1;
printf(" + LinearGradientBrushOptionalData: ");
- int status = U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(contents, BDFlag, &Tm, &Bc, &BfH, &BfV);
+ int status = U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(contents, BDFlag, &Tm, &Bc, &BfH, &BfV, blimit);
if(status){
if(BDFlag & U_BD_Transform){
U_PMF_TRANSFORMMATRIX2_print(&Tm);
@@ -1196,17 +1258,17 @@ int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag
}
if(Bc){
printf("\n");
- (void) U_PMF_BLENDCOLORS_print(Bc);
+ (void) U_PMF_BLENDCOLORS_print(Bc, blimit);
None=0;
}
if(BfH){
printf("\n");
- (void) U_PMF_BLENDFACTORS_print(BfH,"H");
+ (void) U_PMF_BLENDFACTORS_print(BfH,"H", blimit);
None=0;
}
if(BfV){
printf("\n");
- (void) U_PMF_BLENDFACTORS_print(BfV,"V");
+ (void) U_PMF_BLENDFACTORS_print(BfV,"V", blimit);
None=0;
}
if(None){
@@ -1220,15 +1282,16 @@ int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag
\brief Print data from a U_PMF_LINEPATH object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object
*/
-int U_PMF_LINEPATH_print(const char *contents){
+int U_PMF_LINEPATH_print(const char *contents, const char * blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_LINEPATH_get(contents, &Size, &Data);
+ int status = U_PMF_LINEPATH_get(contents, &Size, &Data, blimit);
if(status){
printf(" LinePath: Size:%d\n", Size);
- (void) U_PMF_PATH_print(Data);
+ (void) U_PMF_PATH_print(Data, blimit);
}
return(status);
}
@@ -1237,13 +1300,14 @@ int U_PMF_LINEPATH_print(const char *contents){
\brief Print data from a U_PMF_METAFILE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object
*/
-int U_PMF_METAFILE_print(const char *contents){
+int U_PMF_METAFILE_print(const char *contents, const char * blimit){
uint32_t Type;
uint32_t Size;
const char *Data;
- int status = U_PMF_METAFILE_get(contents, &Type, &Size, &Data);
+ int status = U_PMF_METAFILE_get(contents, &Type, &Size, &Data, blimit);
if(status){
printf(" MetaFile: Type:%X Size:%d",Type, Size);
/* embedded metafiles are not handled beyond this*/
@@ -1255,14 +1319,15 @@ int U_PMF_METAFILE_print(const char *contents){
\brief Print data from a U_PMF_PALETTE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object
*/
-int U_PMF_PALETTE_print(const char *contents){
+int U_PMF_PALETTE_print(const char *contents, const char *blimit){
unsigned int i;
uint32_t Flags;
uint32_t Elements;
const char *Data;
- int status = U_PMF_PALETTE_get(contents, &Flags, &Elements, &Data);
+ int status = U_PMF_PALETTE_get(contents, &Flags, &Elements, &Data, blimit);
if(status){
printf(" Palette: Flags:%X Elements:%u Colors:",Flags, Elements);
for(i=0; i<Elements; i++){
@@ -1278,15 +1343,16 @@ int U_PMF_PALETTE_print(const char *contents){
\brief Print data from a U_PMF_PATHGRADIENTBRUSHDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object
*/
-int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents){
+int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){
U_PMF_PATHGRADIENTBRUSHDATA Pgbd;
const char *Gradient;
const char *Boundary;
const char *Data=NULL;
unsigned int i;
- int status = U_PMF_PATHGRADIENTBRUSHDATA_get(contents, &Pgbd, &Gradient, &Boundary, &Data);
+ int status = U_PMF_PATHGRADIENTBRUSHDATA_get(contents, &Pgbd, &Gradient, &Boundary, &Data, blimit);
if(status){
printf(" + PathGradientBrushData: Flags:%X WrapMode:%d, CenterColor:",Pgbd.Flags, Pgbd.WrapMode);
(void) U_PMF_ARGB_print((char *)&(Pgbd.CenterColor));
@@ -1301,12 +1367,12 @@ int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents){
printf("\n");
}
if(Pgbd.Flags & U_BD_Path){
- (void) U_PMF_BOUNDARYPATHDATA_print(Boundary);
+ (void) U_PMF_BOUNDARYPATHDATA_print(Boundary, blimit);
}
else {
- (void) U_PMF_BOUNDARYPOINTDATA_print(Boundary);
+ (void) U_PMF_BOUNDARYPOINTDATA_print(Boundary, blimit);
}
- (void) U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(Data, Pgbd.Flags);
+ (void) U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(Data, Pgbd.Flags, blimit);
}
return(status);
}
@@ -1316,25 +1382,26 @@ int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents){
\return 1 on success, 0 on error
\param contents Record from which to print data
\param BDFlag Describes optional values in contents
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
*/
-int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag){
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){
if(BDFlag & (U_BD_Transform | U_BD_PresetColors | U_BD_BlendFactorsH | U_BD_FocusScales)){
printf(" + PathGradientBrushOptionalData: ");
}
if(BDFlag & U_BD_Transform){
- U_PMF_TRANSFORMMATRIX_print(contents);
+ U_PMF_TRANSFORMMATRIX_print(contents, blimit);
contents += sizeof(U_PMF_TRANSFORMMATRIX);
}
if(BDFlag & U_BD_PresetColors){ /* If this is present, BlendFactorsH will not be */
- contents += U_PMF_BLENDCOLORS_print(contents);
+ contents += U_PMF_BLENDCOLORS_print(contents, blimit);
}
if(BDFlag & U_BD_BlendFactorsH){/* If this is present, U_BD_PresetColors will not be */
- contents += U_PMF_BLENDFACTORS_print(contents,"");
+ contents += U_PMF_BLENDFACTORS_print(contents,"", blimit);
}
if(BDFlag & U_BD_FocusScales){
- contents += U_PMF_BLENDFACTORS_print(contents,"");
- U_PMF_FOCUSSCALEDATA_print(contents);
+ contents += U_PMF_BLENDFACTORS_print(contents,"", blimit);
+ U_PMF_FOCUSSCALEDATA_print(contents, blimit);
}
return(1);
}
@@ -1343,11 +1410,12 @@ int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag){
\brief Print data from a U_PMF_PATHPOINTTYPE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
*/
-int U_PMF_PATHPOINTTYPE_print(const char *contents){
+int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit){
int Flags, Type;
- int status = U_PMF_PATHPOINTTYPE_get(contents, &Flags, &Type);
+ int status = U_PMF_PATHPOINTTYPE_get(contents, &Flags, &Type, blimit);
if(status){
printf("{Flags:%X Type:",Flags);
(void) U_PMF_PATHPOINTTYPE_ENUM_print(Type);
@@ -1360,11 +1428,12 @@ int U_PMF_PATHPOINTTYPE_print(const char *contents){
\brief Print data from a U_PMF_PATHPOINTTYPERLE object
\return Number of elements in the run, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
*/
-int U_PMF_PATHPOINTTYPERLE_print(const char *contents){
+int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit){
int Bezier, Elements, Type;
- int status = U_PMF_PATHPOINTTYPERLE_get(contents, &Bezier, &Elements, &Type);
+ int status = U_PMF_PATHPOINTTYPERLE_get(contents, &Bezier, &Elements, &Type, blimit);
if(status){
status = Elements;
printf(" PathPointTypeRLE: Bezier:%c Elements:%u, Type: ",(Bezier ? 'Y' : 'N'), Elements);
@@ -1378,16 +1447,17 @@ int U_PMF_PATHPOINTTYPERLE_print(const char *contents){
\brief Print data from a U_PMF_PATHPOINTTYPERLE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
*/
-int U_PMF_PENDATA_print(const char *contents){
+int U_PMF_PENDATA_print(const char *contents, const char *blimit){
uint32_t Flags, Unit;
U_FLOAT Width;
const char *Data;
- int status = U_PMF_PENDATA_get(contents, &Flags, &Unit, &Width, &Data);
+ int status = U_PMF_PENDATA_get(contents, &Flags, &Unit, &Width, &Data, blimit);
if(status){
printf(" + Pendata: Flags:%X Unit:%X Width:%f",Flags, Unit, Width);
- (void) U_PMF_PENOPTIONALDATA_print(Data, Flags); /* prints a new line at end */
+ (void) U_PMF_PENOPTIONALDATA_print(Data, Flags, blimit); /* prints a new line at end */
}
return(status);
}
@@ -1398,11 +1468,12 @@ int U_PMF_PENDATA_print(const char *contents){
\brief Print data from a U_PMF_PENOPTIONALDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
\param Flags PenData Flags that determine which optionaldata fields are present in the record.
EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
*/
-int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags){
+int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit){
U_PMF_TRANSFORMMATRIX Matrix;
int32_t StartCap;
int32_t EndCap;
@@ -1431,7 +1502,8 @@ int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags){
&Alignment,
&CmpndLineData,
&CSCapData,
- &CECapData);
+ &CECapData,
+ blimit);
if(status){
if(Flags & U_PD_Transform){ (void) U_PMF_TRANSFORMMATRIX2_print(&Matrix);}
if(Flags & U_PD_StartCap){ printf(" StartCap:%d", StartCap );}
@@ -1441,14 +1513,14 @@ int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags){
if(Flags & U_PD_LineStyle){ printf(" Style:%X", Style );}
if(Flags & U_PD_DLCap){ printf(" DLCap:%X", DLCap );}
if(Flags & U_PD_DLOffset){ printf(" DLOffset:%f", DLOffset );}
- if(Flags & U_PD_DLData){ (void) U_PMF_DASHEDLINEDATA_print(DLData );}
+ if(Flags & U_PD_DLData){ (void) U_PMF_DASHEDLINEDATA_print(DLData, blimit );}
if(Flags & U_PD_NonCenter){ printf(" Alignment:%d", Alignment );}
if(Flags & (U_PD_Transform | U_PD_StartCap | U_PD_EndCap |
U_PD_Join | U_PD_MiterLimit | U_PD_LineStyle |
U_PD_DLCap | U_PD_DLOffset |U_PD_DLData |U_PD_NonCenter)){ printf("\n"); }
- if(Flags & U_PD_CLData){ (void) U_PMF_COMPOUNDLINEDATA_print(CmpndLineData); }
- if(Flags & U_PD_CustomStartCap){ (void) U_PMF_CUSTOMSTARTCAPDATA_print(CSCapData); }
- if(Flags & U_PD_CustomEndCap){ (void) U_PMF_CUSTOMENDCAPDATA_print(CECapData); }
+ if(Flags & U_PD_CLData){ (void) U_PMF_COMPOUNDLINEDATA_print(CmpndLineData, blimit); }
+ if(Flags & U_PD_CustomStartCap){ (void) U_PMF_CUSTOMSTARTCAPDATA_print(CSCapData, blimit); }
+ if(Flags & U_PD_CustomEndCap){ (void) U_PMF_CUSTOMENDCAPDATA_print(CECapData, blimit); }
}
return(status);
}
@@ -1456,11 +1528,12 @@ int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags){
\brief Print data from a U_PMF_POINT object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
*/
-int U_PMF_POINT_print(const char **contents){
+int U_PMF_POINT_print(const char **contents, const char *blimit){
U_FLOAT X, Y;
- int status = U_PMF_POINT_get(contents, &X, &Y);
+ int status = U_PMF_POINT_get(contents, &X, &Y, blimit);
if(status){
printf("{%f,%f}", X, Y);
}
@@ -1483,11 +1556,12 @@ int U_PMF_POINT_S_print(U_PMF_POINT *Point){\
\brief Print data from a U_PMF_POINTF object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
*/
-int U_PMF_POINTF_print(const char **contents){
+int U_PMF_POINTF_print(const char **contents, const char *blimit){
U_FLOAT X, Y;
- int status = U_PMF_POINTF_get(contents, &X, &Y);
+ int status = U_PMF_POINTF_get(contents, &X, &Y, blimit);
if(status){
printf("{%f,%f}", X, Y);
}
@@ -1512,6 +1586,7 @@ int U_PMF_POINTF_S_print(U_PMF_POINTF *Point){
\param contents Pointer to next data to print
\param Xpos X coordinate for current point
\param Ypos Y coordinate for current point
+ \param blimit one byte past the end of data
On each call the next relative offset is extracted, the current
coordinates are modified with that offset, and the pointer is
@@ -1519,9 +1594,9 @@ int U_PMF_POINTF_S_print(U_PMF_POINTF *Point){
EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
*/
-int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos){
+int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit){
U_FLOAT X, Y;
- int status = U_PMF_POINTR_get(contents, &X, &Y);
+ int status = U_PMF_POINTR_get(contents, &X, &Y, blimit);
*Xpos += X;
*Ypos += Y;
if(status){
@@ -1534,11 +1609,12 @@ int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos){
\brief Print data from a U_PMF_RECT object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
*/
-int U_PMF_RECT_print(const char **contents){
+int U_PMF_RECT_print(const char **contents, const char *blimit){
int16_t X, Y, Width, Height;
- int status = U_PMF_RECT_get(contents, &X, &Y, &Width, &Height);
+ int status = U_PMF_RECT_get(contents, &X, &Y, &Width, &Height, blimit);
if(status){
printf("{UL{%d,%d},WH{%d,%d}}", X, Y, Width, Height);
}
@@ -1560,11 +1636,12 @@ int U_PMF_RECT_S_print(U_PMF_RECT *Rect){
\brief Print data from a U_PMF_RECTF object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
*/
-int U_PMF_RECTF_print(const char **contents){
+int U_PMF_RECTF_print(const char **contents, const char *blimit){
U_FLOAT X, Y, Width, Height;
- int status = U_PMF_RECTF_get(contents, &X, &Y, &Width, &Height);
+ int status = U_PMF_RECTF_get(contents, &X, &Y, &Width, &Height, blimit);
if(status){
printf("{UL{%f,%f},WH{%f,%f}}", X, Y, Width, Height);
}
@@ -1587,27 +1664,28 @@ int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect){
\return size on success, 0 on error
\param contents Record from which to print data
\param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object
*/
-int U_PMF_REGIONNODE_print(const char *contents, int Level){
+int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit){
int len=4; /* Type will always be present */
uint32_t Type;
const char *Data;
- int status = U_PMF_REGIONNODE_get(contents, &Type, &Data);
+ int status = U_PMF_REGIONNODE_get(contents, &Type, &Data, blimit);
if(status){
printf("\n + RegionNode(Level:%d) { Type:%X(",Level,Type);
U_PMF_NODETYPE_print(Type);
printf(")");
if(Type >= U_RNDT_And && Type <= U_RNDT_Complement){
- len += U_PMF_REGIONNODECHILDNODES_print(Data, Level+1);
+ len += U_PMF_REGIONNODECHILDNODES_print(Data, Level+1, blimit);
}
else if(Type == U_RNDT_Rect){
len += sizeof(U_PMF_RECTF);
- (void) U_PMF_RECTF_print(&Data);
+ (void) U_PMF_RECTF_print(&Data, blimit);
printf("\n");
}
else if(Type == U_RNDT_Path){
- len += U_PMF_REGIONNODEPATH_print(Data);
+ len += U_PMF_REGIONNODEPATH_print(Data, blimit);
}
/* U_RNDT_Empty and U_RNDT_Infinite do not change the length */
else if(Type == U_RNDT_Empty ){ printf(" Empty" ); }
@@ -1624,18 +1702,19 @@ int U_PMF_REGIONNODE_print(const char *contents, int Level){
\return size on success, 0 on error
\param contents Record from which to print data
\param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object
*/
-int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level){
+int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit){
uint32_t size,rsize;
printf(" RegionNodeChildNodes:\n");
printf(" + RNCN__Left(Level:%d) {", Level);
- size = U_PMF_REGIONNODE_print(contents, Level);
+ size = U_PMF_REGIONNODE_print(contents, Level, blimit);
printf(" + RNCN__Left(Level:%d) },\n", Level);
if(size){
contents += size;
printf(" + RNCN_Right(Level:%d) {", Level);
- rsize = U_PMF_REGIONNODE_print(contents, Level);
+ rsize = U_PMF_REGIONNODE_print(contents, Level, blimit);
size += rsize;
printf(" + RNCN_Right(Level:%d) },\n",Level);
}
@@ -1646,15 +1725,16 @@ int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level){
\brief Print data from a U_PMF_REGIONNODEPATH object
\return Size of data on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object
*/
-int U_PMF_REGIONNODEPATH_print(const char *contents){
+int U_PMF_REGIONNODEPATH_print(const char *contents, const char * blimit){
int32_t Size;
const char *Data;
- int status = U_PMF_REGIONNODEPATH_get(contents, &Size, &Data);
+ int status = U_PMF_REGIONNODEPATH_get(contents, &Size, &Data, blimit);
if(status){
printf(" RegionNodePath: \n");
- (void) U_PMF_PATH_print(Data);
+ (void) U_PMF_PATH_print(Data, blimit);
status = Size + 4; /* data sizee + the 4 bytes encoding the size */
}
return(status);
@@ -1665,11 +1745,12 @@ int U_PMF_REGIONNODEPATH_print(const char *contents){
\brief Print data from a U_PMF_SOLIDBRUSHDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
*/
-int U_PMF_SOLIDBRUSHDATA_print(const char *contents){
+int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit){
U_PMF_ARGB Color;
- int status = U_PMF_SOLIDBRUSHDATA_get(contents, &Color);
+ int status = U_PMF_SOLIDBRUSHDATA_get(contents, &Color, blimit);
if(status){
printf(" SolidBrushData: ");
(void) U_PMF_ARGB_print((char *) &Color);
@@ -1683,12 +1764,13 @@ int U_PMF_SOLIDBRUSHDATA_print(const char *contents){
\param contents Record from which to print data
\param TabStopCount Entries in TabStop array
\param RangeCount Entries in CharRange array
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
*/
-int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount){
+int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit){
const U_FLOAT *TabStops;
const U_PMF_CHARACTERRANGE *CharRange;
- int status = U_PMF_STRINGFORMATDATA_get(contents, TabStopCount, RangeCount, &TabStops, &CharRange);
+ int status = U_PMF_STRINGFORMATDATA_get(contents, TabStopCount, RangeCount, &TabStops, &CharRange, blimit);
if(status){
printf(" SFdata: TabStopCount:%u RangeCount:%u\n", TabStopCount, RangeCount);
@@ -1708,13 +1790,14 @@ int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, ui
\brief Print data from a U_PMF_TEXTUREBRUSHDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object
*/
-int U_PMF_TEXTUREBRUSHDATA_print(const char *contents){
+int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit){
uint32_t Flags;
int32_t WrapMode;
const char *Data;
- int status = U_PMF_TEXTUREBRUSHDATA_get(contents, &Flags, &WrapMode, &Data);
+ int status = U_PMF_TEXTUREBRUSHDATA_get(contents, &Flags, &WrapMode, &Data, blimit);
if(status){
printf(" + TBdata: Flags:%X WrapMode:%d", Flags, WrapMode);
}
@@ -1725,18 +1808,23 @@ int U_PMF_TEXTUREBRUSHDATA_print(const char *contents){
\brief Print data from a U_PMF_TEXTUREBRUSHOPTIONALDATA object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param HasMatrix True if the record contains a matrix.
\param HasImage True if the record contains an image.
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
*/
-int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasImage){
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit){
U_PMF_TRANSFORMMATRIX Matrix;
+ U_PMF_TRANSFORMMATRIX *pMatrix;
const char *Image;
- int status = U_PMF_TEXTUREBRUSHOPTIONALDATA_get(contents, HasImage, &Matrix, &Image);
+ if(HasMatrix){ pMatrix = &Matrix; }
+ else { pMatrix = NULL; }
+ int status = U_PMF_TEXTUREBRUSHOPTIONALDATA_get(contents, HasImage, pMatrix, &Image, blimit);
if(status){
printf(" + TBOptdata: Image:%c", (HasImage ? 'Y' : 'N'));
(void) U_PMF_TRANSFORMMATRIX2_print(&Matrix);
- (void) U_PMF_IMAGE_print(Image);
+ (void) U_PMF_IMAGE_print(Image, blimit);
}
return(status);
}
@@ -1745,11 +1833,12 @@ int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasImage){
\brief Print data from a U_PMF_TRANSFORMMATRIX object stored in file byte order.
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
*/
-int U_PMF_TRANSFORMMATRIX_print(const char *contents){
+int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit){
U_PMF_TRANSFORMMATRIX Tm;
- int status = U_PMF_TRANSFORMMATRIX_get(contents, &Tm);
+ int status = U_PMF_TRANSFORMMATRIX_get(contents, &Tm, blimit);
if(status){
U_PMF_TRANSFORMMATRIX2_print(&Tm);
}
@@ -1782,12 +1871,13 @@ int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Rm){
\brief Print data from a U_PMF_IE_BLUR object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object
*/
-int U_PMF_IE_BLUR_print(const char *contents){
+int U_PMF_IE_BLUR_print(const char *contents, const char *blimit){
U_FLOAT Radius;
uint32_t ExpandEdge;
- int status = U_PMF_IE_BLUR_get(contents, &Radius, &ExpandEdge);
+ int status = U_PMF_IE_BLUR_get(contents, &Radius, &ExpandEdge, blimit);
if(status){
printf("BlurEffect Radius:%f ExpandEdge:%u\n", Radius, ExpandEdge);
}
@@ -1798,11 +1888,12 @@ int U_PMF_IE_BLUR_print(const char *contents){
\brief Print data from a U_PMF_IE_BRIGHTNESSCONTRAST object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object
*/
-int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents){
+int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit){
int32_t Brightness, Contrast;
- int status = U_PMF_IE_BRIGHTNESSCONTRAST_get(contents, &Brightness, &Contrast);
+ int status = U_PMF_IE_BRIGHTNESSCONTRAST_get(contents, &Brightness, &Contrast, blimit);
if(status){
printf("BrightnessContrastEffect Brightness:%d Contrast:%d\n", Brightness, Contrast);
}
@@ -1813,11 +1904,12 @@ int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents){
\brief Print data from a U_PMF_IE_COLORBALANCE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object
*/
-int U_PMF_IE_COLORBALANCE_print(const char *contents){
+int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit){
int32_t CyanRed, MagentaGreen, YellowBlue;
- int status = U_PMF_IE_COLORBALANCE_get(contents, &CyanRed, &MagentaGreen, &YellowBlue);
+ int status = U_PMF_IE_COLORBALANCE_get(contents, &CyanRed, &MagentaGreen, &YellowBlue, blimit);
if(status){
printf("ColorBalanceEffect CyanRed:%d MagentaGreen:%d YellowBlue:%d\n", CyanRed, MagentaGreen, YellowBlue);
}
@@ -1828,12 +1920,13 @@ int U_PMF_IE_COLORBALANCE_print(const char *contents){
\brief Print data from a U_PMF_IE_COLORCURVE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
*/
-int U_PMF_IE_COLORCURVE_print(const char *contents){
+int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit){
uint32_t Adjust, Channel;
int32_t Intensity;
- int status = U_PMF_IE_COLORCURVE_get(contents, &Adjust, &Channel, &Intensity);
+ int status = U_PMF_IE_COLORCURVE_get(contents, &Adjust, &Channel, &Intensity, blimit);
if(status){
printf("ColorBalanceEffect Adjust:%u Channel:%u Intensity:%d\n", Adjust, Channel, Intensity);
}
@@ -1844,11 +1937,12 @@ int U_PMF_IE_COLORCURVE_print(const char *contents){
\brief Print data from a U_PMF_IE_COLORLOOKUPTABLE object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object
*/
-int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents){
+int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit){
const uint8_t *BLUT, *GLUT, *RLUT, *ALUT;
- int status = U_PMF_IE_COLORLOOKUPTABLE_get(contents, &BLUT, &GLUT, &RLUT, &ALUT);
+ int status = U_PMF_IE_COLORLOOKUPTABLE_get(contents, &BLUT, &GLUT, &RLUT, &ALUT, blimit);
if(status){
printf("ColorLookupTableEffect \n");
U_PMF_UINT8_ARRAY_print(" BLUT:", BLUT, 256, "\n");
@@ -1863,12 +1957,13 @@ int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents){
\brief Print data from a U_PMF_IE_COLORMATRIX object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object
*/
-int U_PMF_IE_COLORMATRIX_print(const char *contents){
+int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit){
U_PMF_IE_COLORMATRIX Matrix;
int i,j;
- int status = U_PMF_IE_COLORMATRIX_get(contents, &Matrix);
+ int status = U_PMF_IE_COLORMATRIX_get(contents, &Matrix, blimit);
if(status){
printf("ColorMatrixEffect\n");
for(i=0;i<5;i++){
@@ -1885,11 +1980,12 @@ int U_PMF_IE_COLORMATRIX_print(const char *contents){
\brief Print data from a U_PMF_IE_HUESATURATIONLIGHTNESS object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object
*/
-int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents){
+int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit){
int32_t Hue, Saturation, Lightness;
- int status = U_PMF_IE_HUESATURATIONLIGHTNESS_get(contents, &Hue, &Saturation, &Lightness);
+ int status = U_PMF_IE_HUESATURATIONLIGHTNESS_get(contents, &Hue, &Saturation, &Lightness, blimit);
if(status){
printf("HueSaturationLightnessEffect Hue:%d Saturation:%d Lightness:%d\n", Hue, Saturation, Lightness);
}
@@ -1900,11 +1996,12 @@ int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents){
\brief Print data from a U_PMF_IE_LEVELS object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object
*/
-int U_PMF_IE_LEVELS_print(const char *contents){
+int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit){
int32_t Highlight, Midtone, Shadow;
- int status = U_PMF_IE_LEVELS_get(contents, &Highlight, &Midtone, &Shadow);
+ int status = U_PMF_IE_LEVELS_get(contents, &Highlight, &Midtone, &Shadow, blimit);
if(status){
printf("LevelEffect Highlight:%d Midtone:%d Shadow:%d\n", Highlight, Midtone, Shadow);
}
@@ -1915,12 +2012,13 @@ int U_PMF_IE_LEVELS_print(const char *contents){
\brief Print data from a U_PMF_IE_REDEYECORRECTION object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object
*/
-int U_PMF_IE_REDEYECORRECTION_print(const char *contents){
+int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit){
int32_t Elements;
U_RECTL *Rects;
- int status = U_PMF_IE_REDEYECORRECTION_get(contents, &Elements, &Rects);
+ int status = U_PMF_IE_REDEYECORRECTION_get(contents, &Elements, &Rects, blimit);
if(status){
printf("RedEyeCorrectionEffect Elements:%u", Elements);
for(; Elements; Elements--, Rects++){
@@ -1935,13 +2033,14 @@ int U_PMF_IE_REDEYECORRECTION_print(const char *contents){
/**
\brief Print data from a U_PMF_IE_SHARPEN object
\return 1 on success, 0 on error
+ \param blimit one byte past the end of data
\param contents Record from which to print data
EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object
*/
-int U_PMF_IE_SHARPEN_print(const char *contents){
+int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit){
U_FLOAT Radius;
int32_t Sharpen;
- int status = U_PMF_IE_SHARPEN_get(contents, &Radius, &Sharpen);
+ int status = U_PMF_IE_SHARPEN_get(contents, &Radius, &Sharpen, blimit);
if(status){
printf("SharpenEffect Radius:%f Sharpen:%u\n", Radius, Sharpen);
}
@@ -1952,11 +2051,12 @@ int U_PMF_IE_SHARPEN_print(const char *contents){
\brief Print data from a U_PMF_IE_TINT object
\return 1 on success, 0 on error
\param contents Record from which to print data
+ \param blimit one byte past the end of data
EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object
*/
-int U_PMF_IE_TINT_print(const char *contents){
+int U_PMF_IE_TINT_print(const char *contents, const char *blimit){
int32_t Hue, Amount;
- int status = U_PMF_IE_TINT_get(contents, &Hue, &Amount);
+ int status = U_PMF_IE_TINT_get(contents, &Hue, &Amount, blimit);
if(status){
printf("TintEffect Hue:%d Amount:%d\n", Hue, Amount);
}
@@ -1981,6 +2081,9 @@ int U_PMR_OFFSETCLIP_print(const char *contents){
if(status){
printf(" + dx:%f dy:%f\n",dX,dY);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2007,6 +2110,9 @@ int U_PMR_SETCLIPPATH_print(const char *contents){
if(status){
printf(" + PathID:%u CMenum:%d\n",PathID,CMenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2027,6 +2133,9 @@ int U_PMR_SETCLIPRECT_print(const char *contents){
U_PMF_RECTF_S_print(&Rect);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2045,6 +2154,9 @@ int U_PMR_SETCLIPREGION_print(const char *contents){
U_PMF_COMBINEMODEENUMERATION_print(CMenum);
printf(")\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2061,6 +2173,11 @@ int U_PMR_COMMENT_print(const char *contents){
unsigned int i=0;
int status = U_PMR_COMMENT_get(contents, &Header, &Data);
if(status){
+ const char *blimit = contents + Header.Size;
+ if(IS_MEM_UNSAFE(Data, Header.DataSize, blimit)){
+ printf(" corrupt record\n");
+ return(0);
+ }
/* try to print it, but only ASCII, bail on anything that is not ASCII */
printf(" + Data:");
for(i=0; i< Header.DataSize; i++,Data++){
@@ -2070,6 +2187,9 @@ int U_PMR_COMMENT_print(const char *contents){
}
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2107,9 +2227,12 @@ int U_PMR_HEADER_print(const char *contents){
if(status){
/* try to print it, but only ASCII, bail on anything that is not ASCII */
printf(" + ");
- (void) U_PMF_GRAPHICSVERSION_print((char *) &Version);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
printf(" IsDual:%c IsVideo:%d LogicalDpiX,y:{%u,%u}\n",(IsDual ? 'Y' : 'N'),IsVideo,LogicalDpiX, LogicalDpiY);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2127,6 +2250,9 @@ int U_PMR_CLEAR_print(const char *contents){
printf(" + Color:");
(void) U_PMF_ARGB_print((char *) &Color);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2147,6 +2273,9 @@ int U_PMR_DRAWARC_print(const char *contents){
(void) U_PMF_VARRECTF_S_print(&Rect, 1);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2167,6 +2296,9 @@ int U_PMR_DRAWBEZIERS_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2194,6 +2326,9 @@ int U_PMR_DRAWCLOSEDCURVE_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2221,6 +2356,9 @@ int U_PMR_DRAWCURVE_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2269,7 +2407,9 @@ int U_PMR_DRAWDRIVERSTRING_print(const char *contents){
free(Matrix);
printf("\n");
}
-
+ }
+ else {
+ printf(" corrupt record\n");
}
return(status);
}
@@ -2290,6 +2430,9 @@ int U_PMR_DRAWELLIPSE_print(const char *contents){
(void) U_PMF_VARRECTF_S_print(&Rect, 1);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2313,6 +2456,9 @@ int U_PMR_DRAWIMAGE_print(const char *contents){
(void) U_PMF_RECTF_S_print(&DstRect);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2339,6 +2485,9 @@ int U_PMR_DRAWIMAGEPOINTS_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2360,6 +2509,9 @@ int U_PMR_DRAWLINES_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2375,6 +2527,9 @@ int U_PMR_DRAWPATH_print(const char *contents){
if(status){
printf(" + PathIdx:%d PenIdx:%d\n", PathIdx, PenIdx);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2395,6 +2550,9 @@ int U_PMR_DRAWPIE_print(const char *contents){
(void) U_PMF_VARRECTF_S_print(&Rect, 1);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2402,10 +2560,9 @@ int U_PMR_DRAWPIE_print(const char *contents){
\brief Print data from a U_PMR_DRAWRECTS record
\return size of record in bytes on success, 0 on error
\param contents Record from which to print data
- \param blimit One byte past the last record in memory.
EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B
*/
-int U_PMR_DRAWRECTS_print(const char *contents, const char *blimit){
+int U_PMR_DRAWRECTS_print(const char *contents){
uint32_t PenID;
int ctype;
uint32_t Elements;
@@ -2413,11 +2570,13 @@ int U_PMR_DRAWRECTS_print(const char *contents, const char *blimit){
U_PMF_CMN_HDR hdr;
int status = U_PMR_DRAWRECTS_get(contents, &hdr, &PenID, &ctype, &Elements, &Rects);
if(status){
- if(contents + hdr.Size >= blimit)return(0);
printf(" + PenID:%u ctype:%d Elements:%u Rect:", PenID,ctype,Elements);
(void) U_PMF_VARRECTF_S_print(Rects, Elements);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
if(Rects)free(Rects);
return(status);
}
@@ -2452,6 +2611,9 @@ int U_PMR_DRAWSTRING_print(const char *contents){
printf(" String(as_UTF8):(none)\n");
}
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2477,6 +2639,9 @@ int U_PMR_FILLCLOSEDCURVE_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2498,6 +2663,9 @@ int U_PMR_FILLELLIPSE_print(const char *contents){
(void) U_PMF_VARRECTF_S_print(&Rect, 1);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2516,6 +2684,9 @@ int U_PMR_FILLPATH_print(const char *contents){
(void) U_PMF_VARBRUSHID_print(btype, BrushID);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2537,6 +2708,9 @@ int U_PMR_FILLPIE_print(const char *contents){
(void) U_PMF_VARRECTF_S_print(&Rect, 1);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2558,6 +2732,9 @@ int U_PMR_FILLPOLYGON_print(const char *contents){
U_PMF_VARPOINTF_S_print(Points, Elements);
free(Points);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2565,23 +2742,24 @@ int U_PMR_FILLPOLYGON_print(const char *contents){
\brief Print data from a U_PMR_FILLRECTS record
\return size of record in bytes on success, 0 on error
\param contents Record from which to print data
- \param blimit One byte past the last record in memory.
EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A
*/
-int U_PMR_FILLRECTS_print(const char *contents, const char *blimit){
+int U_PMR_FILLRECTS_print(const char *contents){
int btype, ctype;
uint32_t BrushID, Elements;
U_PMF_RECTF *Rects;
U_PMF_CMN_HDR hdr;
int status = U_PMR_FILLRECTS_get(contents, &hdr, &btype,&ctype, &BrushID, &Elements, &Rects);
if(status){
- if(contents + hdr.Size >= blimit)return(0);
printf(" + btype:%d ctype:%d Elements:%u",btype,ctype,Elements);
(void) U_PMF_VARBRUSHID_print(btype, BrushID);
(void) U_PMF_VARRECTF_S_print(Rects, Elements);
free(Rects);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2600,6 +2778,9 @@ int U_PMR_FILLREGION_print(const char *contents){
(void) U_PMF_VARBRUSHID_print(btype, BrushID);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2611,6 +2792,10 @@ int U_PMR_FILLREGION_print(const char *contents){
\param ObjCont Structure that holds accumulated object.
\param term Flag used when an abnormal termination of a series of continuation records is encountered.
EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+
+ This is the ONLY EMF+ record type which needs an explicit blimit passed in. Since it glues
+ together multiple records, and calls itself recursively, the initial caller cannot determine
+ that all of the sizes will be OK from the first record's header.
*/
int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term){
U_PMF_CMN_HDR Header;
@@ -2641,8 +2826,11 @@ int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *Ob
/* In a corrupt EMF+ file we might hit a new type of record before all the continuation records
expected have been found. If that happens terminate whatever we have accumulated so far, and then go on
to emit the new (unexpected) record. */
- if(contents + Header.Size >= blimit)return(0);
- if(!status)return(status);
+ if(IS_MEM_UNSAFE(contents, Header.Size, blimit))return(0);
+ if(!status){
+ printf(" corrupt record\n");
+ return(status);
+ }
if((ObjCont->used > 0) && (U_OA_append(ObjCont, NULL, 0, otype, ObjID) < 0)){
U_PMR_OBJECT_print(contents, blimit, ObjCont, 1);
}
@@ -2665,16 +2853,17 @@ int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *Ob
ttype = otype;
}
if(status){
+ blimit = ObjCont->accum + ObjCont->used; /* more restrictive blimit, just to end of object */
switch(ttype){
- case U_OT_Brush: (void) U_PMF_BRUSH_print(ObjCont->accum); break;
- case U_OT_Pen: (void) U_PMF_PEN_print(ObjCont->accum); break;
- case U_OT_Path: (void) U_PMF_PATH_print(ObjCont->accum); break;
- case U_OT_Region: (void) U_PMF_REGION_print(ObjCont->accum); break;
- case U_OT_Image: (void) U_PMF_IMAGE_print(ObjCont->accum); break;
- case U_OT_Font: (void) U_PMF_FONT_print(ObjCont->accum); break;
- case U_OT_StringFormat: (void) U_PMF_STRINGFORMAT_print(ObjCont->accum); break;
- case U_OT_ImageAttributes: (void) U_PMF_IMAGEATTRIBUTES_print(ObjCont->accum); break;
- case U_OT_CustomLineCap: (void) U_PMF_CUSTOMLINECAP_print(ObjCont->accum,""); break;
+ case U_OT_Brush: (void) U_PMF_BRUSH_print(ObjCont->accum, blimit); break;
+ case U_OT_Pen: (void) U_PMF_PEN_print(ObjCont->accum, blimit); break;
+ case U_OT_Path: (void) U_PMF_PATH_print(ObjCont->accum, blimit); break;
+ case U_OT_Region: (void) U_PMF_REGION_print(ObjCont->accum, blimit); break;
+ case U_OT_Image: (void) U_PMF_IMAGE_print(ObjCont->accum, blimit); break;
+ case U_OT_Font: (void) U_PMF_FONT_print(ObjCont->accum, blimit); break;
+ case U_OT_StringFormat: (void) U_PMF_STRINGFORMAT_print(ObjCont->accum, blimit); break;
+ case U_OT_ImageAttributes: (void) U_PMF_IMAGEATTRIBUTES_print(ObjCont->accum, blimit); break;
+ case U_OT_CustomLineCap: (void) U_PMF_CUSTOMLINECAP_print(ObjCont->accum,"", blimit); break;
case U_OT_Invalid:
default:
printf("INVALID OBJECT TYPE!!!!\n");
@@ -2707,24 +2896,27 @@ int U_PMR_SERIALIZABLEOBJECT_print(const char *contents){
printf("\n + Effect:");
free(string);
switch(iee){
- case U_IEE_Unknown: printf("(undefined)\n"); break;
- case U_IEE_BlurEffectGuid: U_PMF_IE_BLUR_print(Data); break;
- case U_IEE_BrightnessContrastEffectGuid: U_PMF_IE_BRIGHTNESSCONTRAST_print(Data); break;
- case U_IEE_ColorBalanceEffectGuid: U_PMF_IE_COLORBALANCE_print(Data); break;
- case U_IEE_ColorCurveEffectGuid: U_PMF_IE_COLORCURVE_print(Data); break;
- case U_IEE_ColorLookupTableEffectGuid: U_PMF_IE_COLORLOOKUPTABLE_print(Data); break;
- case U_IEE_ColorMatrixEffectGuid: U_PMF_IE_COLORMATRIX_print(Data); break;
- case U_IEE_HueSaturationLightnessEffectGuid: U_PMF_IE_HUESATURATIONLIGHTNESS_print(Data); break;
- case U_IEE_LevelsEffectGuid: U_PMF_IE_LEVELS_print(Data); break;
- case U_IEE_RedEyeCorrectionEffectGuid: U_PMF_IE_REDEYECORRECTION_print(Data); break;
- case U_IEE_SharpenEffectGuid: U_PMF_IE_SHARPEN_print(Data); break;
- case U_IEE_TintEffectGuid: U_PMF_IE_TINT_print(Data); break;
+ case U_IEE_Unknown: printf("(undefined)\n"); break;
+ case U_IEE_BlurEffectGuid: U_PMF_IE_BLUR_print(Data, Data + sizeof(U_PMF_IE_BLUR)); break;
+ case U_IEE_BrightnessContrastEffectGuid: U_PMF_IE_BRIGHTNESSCONTRAST_print(Data, Data + sizeof(U_PMF_IE_BRIGHTNESSCONTRAST)); break;
+ case U_IEE_ColorBalanceEffectGuid: U_PMF_IE_COLORBALANCE_print(Data, Data + sizeof(U_PMF_IE_COLORBALANCE)); break;
+ case U_IEE_ColorCurveEffectGuid: U_PMF_IE_COLORCURVE_print(Data, Data + sizeof(U_PMF_IE_COLORCURVE)); break;
+ case U_IEE_ColorLookupTableEffectGuid: U_PMF_IE_COLORLOOKUPTABLE_print(Data, Data + sizeof(U_PMF_IE_COLORLOOKUPTABLE)); break;
+ case U_IEE_ColorMatrixEffectGuid: U_PMF_IE_COLORMATRIX_print(Data, Data + sizeof(U_PMF_IE_COLORMATRIX)); break;
+ case U_IEE_HueSaturationLightnessEffectGuid: U_PMF_IE_HUESATURATIONLIGHTNESS_print(Data, Data + sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS)); break;
+ case U_IEE_LevelsEffectGuid: U_PMF_IE_LEVELS_print(Data, Data + sizeof(U_PMF_IE_LEVELS)); break;
+ case U_IEE_RedEyeCorrectionEffectGuid: U_PMF_IE_REDEYECORRECTION_print(Data, Data + sizeof(U_PMF_IE_REDEYECORRECTION)); break;
+ case U_IEE_SharpenEffectGuid: U_PMF_IE_SHARPEN_print(Data, Data + sizeof(U_PMF_IE_SHARPEN)); break;
+ case U_IEE_TintEffectGuid: U_PMF_IE_TINT_print(Data, Data + sizeof(U_PMF_IE_TINT)); break;
}
}
else {
printf(" + GUID:ERROR Size:%u\n",Size);
}
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2740,6 +2932,9 @@ int U_PMR_SETANTIALIASMODE_print(const char *contents){
if(status){
printf(" + SMenum:%d AntiAlias:%c\n",SMenum,(aatype ? 'Y' : 'N'));
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2755,6 +2950,9 @@ int U_PMR_SETCOMPOSITINGMODE_print(const char *contents){
if(status){
printf(" + CMenum:%d\n",CMenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2770,6 +2968,9 @@ int U_PMR_SETCOMPOSITINGQUALITY_print(const char *contents){
if(status){
printf(" + CQenum:%d\n",CQenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2785,6 +2986,9 @@ int U_PMR_SETINTERPOLATIONMODE_print(const char *contents){
if(status){
printf(" + IMenum:%d\n",IMenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2800,6 +3004,9 @@ int U_PMR_SETPIXELOFFSETMODE_print(const char *contents){
if(status){
printf(" + POMenum:%d\n",POMenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2815,6 +3022,9 @@ int U_PMR_SETRENDERINGORIGIN_print(const char *contents){
if(status){
printf(" + X:%d Y:%d\n", X, Y);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2830,6 +3040,9 @@ int U_PMR_SETTEXTCONTRAST_print(const char *contents){
if(status){
printf(" + GC:%d\n", GC);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2845,6 +3058,9 @@ int U_PMR_SETTEXTRENDERINGHINT_print(const char *contents){
if(status){
printf(" + TRHenum:%d\n",TRHenum);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2865,6 +3081,9 @@ int U_PMR_BEGINCONTAINER_print(const char *contents){
printf(" SrcRect:"); (void) U_PMF_RECTF_S_print(&SrcRect);
printf(" StackID:%u\n", StackID);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2880,6 +3099,9 @@ int U_PMR_BEGINCONTAINERNOPARAMS_print(const char *contents){
if(status){
printf(" + StackID:%u\n", StackID);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2895,6 +3117,9 @@ int U_PMR_ENDCONTAINER_print(const char *contents){
if(status){
printf(" + StackID:%u\n", StackID);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2910,6 +3135,9 @@ int U_PMR_RESTORE_print(const char *contents){
if(status){
printf(" + StackID:%u\n", StackID);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2925,6 +3153,9 @@ int U_PMR_SAVE_print(const char *contents){
if(status){
printf(" + StackID:%u\n", StackID);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2945,6 +3176,9 @@ int U_PMR_SETTSCLIP_print(const char *contents){
free(Rects);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2967,6 +3201,7 @@ int U_PMR_SETTSGRAPHICS_print(const char *contents){
&RenderOriginX, &RenderOriginY, &TextContrast, &FilterType,
&PixelOffset, &WorldToDevice, &Data);
if(status){
+ const char *blimit = contents + status;
printf(" + vgatype:%d pptype:%u",vgatype,pptype);
printf(" AntiAliasMode:%u TextRenderHint:%u CompositingMode:%u CompositingQuality:%u",
AntiAliasMode, TextRenderHint, CompositingMode, CompositingQuality);
@@ -2974,9 +3209,12 @@ int U_PMR_SETTSGRAPHICS_print(const char *contents){
printf(" TextContrast:%u",TextContrast);
printf(" WorldToDevice:");
U_PMF_TRANSFORMMATRIX2_print(&WorldToDevice);
- if(pptype){ (void) U_PMF_PALETTE_print(Data); }
+ if(pptype && !U_PMF_PALETTE_print(Data, blimit))return(0);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -2996,6 +3234,9 @@ int U_PMR_MULTIPLYWORLDTRANSFORM_print(const char *contents){
U_PMF_TRANSFORMMATRIX2_print(&Matrix);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -3022,6 +3263,9 @@ int U_PMR_ROTATEWORLDTRANSFORM_print(const char *contents){
if(status){
printf(" + xmtype:%d Multiply:%s Angle:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Angle);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -3038,6 +3282,9 @@ int U_PMR_SCALEWORLDTRANSFORM_print(const char *contents){
if(status){
printf(" + xmtype:%d Multiply:%s ScaleX:%f ScaleY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Sx, Sy);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -3054,6 +3301,9 @@ int U_PMR_SETPAGETRANSFORM_print(const char *contents){
if(status){
printf(" + UTenum:%d Scale:%f\n",UTenum, Scale);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -3071,6 +3321,9 @@ int U_PMR_SETWORLDTRANSFORM_print(const char *contents){
U_PMF_TRANSFORMMATRIX2_print(&Matrix);
printf("\n");
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
@@ -3087,6 +3340,9 @@ int U_PMR_TRANSLATEWORLDTRANSFORM_print(const char *contents){
if(status){
printf(" + xmtype:%d Multiply:%s TranslateX:%f TranlateY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Dx, Dy);
}
+ else {
+ printf(" corrupt record\n");
+ }
return(status);
}
diff --git a/src/libuemf/upmf_print.h b/src/libuemf/upmf_print.h
index 3ba6694eb..fe1c57d60 100644
--- a/src/libuemf/upmf_print.h
+++ b/src/libuemf/upmf_print.h
@@ -6,11 +6,11 @@
/*
File: upmf_print.h
-Version: 0.0.2
-Date: 17-OCT-2013
+Version: 0.0.4
+Date: 24-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
-Copyright: 2013 David Mathog and California Institute of Technology (Caltech)
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
*/
#ifndef _UPMF_PRINT_
@@ -33,77 +33,78 @@ int U_PMF_PX_FMT_ENUM_print(int pfe);
int U_PMF_NODETYPE_print(int Type);
/* prototypes for objects used in PMR records */
-int U_PMF_BRUSH_print(const char *contents);
-int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which);
-int U_PMF_FONT_print(const char *contents);
-int U_PMF_IMAGE_print(const char *contents);
-int U_PMF_IMAGEATTRIBUTES_print(const char *contents);
-int U_PMF_PATH_print(const char *contents);
-int U_PMF_PEN_print(const char *contents);
-int U_PMF_REGION_print(const char *contents);
-int U_PMF_STRINGFORMAT_print(const char *contents);
+int U_PMF_BRUSH_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit);
+int U_PMF_FONT_print(const char *contents, const char *blimit);
+int U_PMF_IMAGE_print(const char *contents, const char *blimit);
+int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit);
+int U_PMF_PATH_print(const char *contents, const char *blimit);
+int U_PMF_PEN_print(const char *contents, const char *blimit);
+int U_PMF_REGION_print(const char *contents, const char *blimit);
+int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit);
int U_PMF_ARGB_print(const char *contents);
-int U_PMF_BITMAP_print(const char *contents);
-int U_PMF_BITMAPDATA_print(const char *contents);
-int U_PMF_BLENDCOLORS_print(const char *contents);
-int U_PMF_BLENDFACTORS_print(const char *contents, const char *type);
-int U_PMF_BOUNDARYPATHDATA_print(const char *contents);
-int U_PMF_BOUNDARYPOINTDATA_print(const char *contents);
-int U_PMF_CHARACTERRANGE_print(const char *contents);
-int U_PMF_COMPOUNDLINEDATA_print(const char *contents);
-int U_PMF_COMPRESSEDIMAGE_print(const char *contents);
-int U_PMF_CUSTOMENDCAPDATA_print(const char *contents);
-int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents);
-int U_PMF_CUSTOMLINECAPDATA_print(const char *contents);
-int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags);
-int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents);
-int U_PMF_DASHEDLINEDATA_print(const char *contents);
-int U_PMF_FILLPATHOBJ_print(const char *contents);
-int U_PMF_FOCUSSCALEDATA_print(const char *contents);
-int U_PMF_GRAPHICSVERSION_print(const char *contents);
-int U_PMF_HATCHBRUSHDATA_print(const char *contents);
+int U_PMF_BITMAP_print(const char *contents, const char *blimit);
+int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit);
+int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit);
+int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char *blimit);
+int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit);
+int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit);
+int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit);
+int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit);
+int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit);
+int U_PMF_FILLPATHOBJ_print(const char *contents, const char *blimit);
+int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit);
+int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents);
+int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit);
+int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit);
int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId);
-int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents);
-int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag);
-int U_PMF_LINEPATH_print(const char *contents);
-int U_PMF_METAFILE_print(const char *contents);
-int U_PMF_PALETTE_print(const char *contents);
-int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents);
-int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag);
-int U_PMF_PATHPOINTTYPE_print(const char *contents);
-int U_PMF_PATHPOINTTYPERLE_print(const char *contents);
-int U_PMF_PENDATA_print(const char *contents);
-int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags);
-int U_PMF_POINT_print(const char **contents);
-int U_PMF_POINTF_print(const char **contents);
-int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos);
+int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit);
+int U_PMF_LINEPATH_print(const char *contents, const char *blimit);
+int U_PMF_METAFILE_print(const char *contents, const char *blimit);
+int U_PMF_PALETTE_print(const char *contents, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit);
+int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit);
+int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit);
+int U_PMF_PENDATA_print(const char *contents, const char *blimit);
+int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit);
+int U_PMF_POINT_print(const char **contents, const char *blimit);
+int U_PMF_POINTF_print(const char **contents, const char *blimit);
+int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit);
int U_PMF_POINT_S_print(U_PMF_POINT *Point);
int U_PMF_POINTF_S_print(U_PMF_POINTF *Point);
-int U_PMF_RECT_print(const char **contents);
-int U_PMF_RECTF_print(const char **contents);
+int U_PMF_RECT_print(const char **contents, const char *blimit);
+int U_PMF_RECTF_print(const char **contents, const char *blimit);
int U_PMF_RECT_S_print(U_PMF_RECT *Rect);
int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect);
-int U_PMF_REGIONNODE_print(const char *contents, int Level);
-int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level);
-int U_PMF_REGIONNODEPATH_print(const char *contents);
-int U_PMF_SOLIDBRUSHDATA_print(const char *contents);
-int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount);
-int U_PMF_TEXTUREBRUSHDATA_print(const char *contents);
-int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasImage);
-int U_PMF_TRANSFORMMATRIX_print(const char *contents);
+int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit);
+int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit);
+int U_PMF_REGIONNODEPATH_print(const char *contents, const char *blimit);
+int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit);
+int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit);
+int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit);
int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Matrix);
int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Matrix);
-int U_PMF_IE_BLUR_print(const char *contents);
-int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents);
-int U_PMF_IE_COLORBALANCE_print(const char *contents);
-int U_PMF_IE_COLORCURVE_print(const char *contents);
-int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents);
-int U_PMF_IE_COLORMATRIX_print(const char *contents);
-int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents);
-int U_PMF_IE_LEVELS_print(const char *contents);
-int U_PMF_IE_REDEYECORRECTION_print(const char *contents);
-int U_PMF_IE_SHARPEN_print(const char *contents);
-int U_PMF_IE_TINT_print(const char *contents);
+int U_PMF_IE_BLUR_print(const char *contents, const char *blimit);
+int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit);
+int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit);
+int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit);
+int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit);
+int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit);
+int U_PMF_IE_TINT_print(const char *contents, const char *blimit);
/* prototypes for PMR records */
int U_PMR_OFFSETCLIP_print(const char *contents);
@@ -127,14 +128,14 @@ int U_PMR_DRAWIMAGEPOINTS_print(const char *contents);
int U_PMR_DRAWLINES_print(const char *contents);
int U_PMR_DRAWPATH_print(const char *contents);
int U_PMR_DRAWPIE_print(const char *contents);
-int U_PMR_DRAWRECTS_print(const char *contents, const char *blimit);
+int U_PMR_DRAWRECTS_print(const char *contents);
int U_PMR_DRAWSTRING_print(const char *contents);
int U_PMR_FILLCLOSEDCURVE_print(const char *contents);
int U_PMR_FILLELLIPSE_print(const char *contents);
int U_PMR_FILLPATH_print(const char *contents);
int U_PMR_FILLPIE_print(const char *contents);
int U_PMR_FILLPOLYGON_print(const char *contents);
-int U_PMR_FILLRECTS_print(const char *contents, const char *blimit);
+int U_PMR_FILLRECTS_print(const char *contents);
int U_PMR_FILLREGION_print(const char *contents);
int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term);
int U_PMR_SERIALIZABLEOBJECT_print(const char *contents);
diff --git a/src/libuemf/uwmf.c b/src/libuemf/uwmf.c
index b378e587f..35d38f69a 100644
--- a/src/libuemf/uwmf.c
+++ b/src/libuemf/uwmf.c
@@ -19,8 +19,8 @@
/*
File: uwmf.c
-Version: 0.0.15
-Date: 11-APR-2014
+Version: 0.0.16
+Date: 25-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -47,6 +47,7 @@ extern "C" {
#endif
#include "uwmf.h"
#include "uwmf_endian.h"
+#include "uemf_safe.h"
/**
\brief Look up the full numeric type of a WMR record by type.
@@ -671,6 +672,51 @@ const char *U_wmr_escnames(int idx){
/* one prototype from uwmf_endian. Put it here because end user should never need to see it, so
not in uemf.h or uwmf_endian.h */
void U_swap2(void *ul, unsigned int count);
+
+/**
+ \brief Check that the bitmap in the specified packed DIB is compatible with the record size
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param blimit one byte past the end of the record.
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+
+ This should not be called directly by end user code.
+*/
+int packed_DIB_safe(
+ const char *record,
+ const char *blimit
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record
+ uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert);
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the WMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(px, usedbytes, blimit))return(0);
+ }
+ return(1);
+}
+
//! \endcond
/**
@@ -4439,9 +4485,7 @@ size_t U_WMRRECSAFE_get(
memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4), 4);
size = 2*Size16;
/* Record is not self consistent - described size past the end of WMF in memory */
- if(size < U_SIZE_METARECORD ||
- contents + size - 1 >= blimit ||
- contents + size - 1 < contents)size=0;
+ if(size < U_SIZE_METARECORD || IS_MEM_UNSAFE(contents, size, blimit))size=0;
return(size);
}
@@ -4826,20 +4870,21 @@ int wmfheader_get(
){
uint32_t Key;
int size=0;
- if(!Placeable || !Header || contents + 4 >= blimit)return(0);
+ if(!contents || !Placeable || !Header || !blimit)return(0);
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4);
if(Key == 0x9AC6CDD7){
size += U_SIZE_WMRPLACEABLE;
- if(contents + size >= blimit)return(0);
+ if(IS_MEM_UNSAFE(contents, size, blimit))return(0);
memcpy(Placeable, contents, U_SIZE_WMRPLACEABLE);
contents += U_SIZE_WMRPLACEABLE;
}
else {
memset(Placeable, 0, U_SIZE_WMRPLACEABLE);
}
- if(contents + size + U_SIZE_WMRHEADER >= blimit)return(0);
+ if(IS_MEM_UNSAFE(contents, size + U_SIZE_WMRHEADER, blimit))return(0);
size += 2* (*(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)));
- if(contents + size >= blimit)return(0);
+ if(IS_MEM_UNSAFE(contents, size, blimit))return(0);
memcpy(Header, contents, U_SIZE_WMRHEADER);
return(size);
}
@@ -5512,7 +5557,11 @@ int U_WMRPOLYGON_get(
uint16_t *Length,
const char **Data
){
- return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data);
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data);
+ if(size){
+ if(IS_MEM_UNSAFE(*Data, (*Length)*sizeof(U_POINT16), contents+size))return(0);
+ }
+ return size;
}
/**
@@ -5527,7 +5576,11 @@ int U_WMRPOLYLINE_get(
uint16_t *Length,
const char **Data
){
- return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYLINE), NULL, Length, Data);
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data);
+ if(size){
+ if(IS_MEM_UNSAFE(*Data, (*Length)*sizeof(U_POINT16), contents+size))return(0);
+ }
+ return size;
}
/**
@@ -5550,7 +5603,11 @@ int U_WMRESCAPE_get(
uint16_t *Length,
const char **Data
){
- return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data);
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data);
+ if(size){
+ if(IS_MEM_UNSAFE(*Data, *Length, contents+size))return(0);
+ }
+ return size;
}
/**
@@ -5787,6 +5844,7 @@ int U_WMRSETDIBTODEV_get(
Dst->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, yDst ));
Dst->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xDst ));
*dib = ( contents + offsetof(U_WMRSETDIBTODEV, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
return(size);
}
@@ -5948,6 +6006,7 @@ int U_WMRDIBBITBLT_get(
Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, yDst ));
Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xDst ));
*dib = ( contents + offsetof(U_WMRDIBBITBLT_PX, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
}
return(size);
}
@@ -5999,6 +6058,7 @@ int U_WMRDIBSTRETCHBLT_get(
cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hDst ));
cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wDst ));
*dib = ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
}
return(size);
}
@@ -6040,11 +6100,13 @@ int U_WMRDIBCREATEPATTERNBRUSH_get(
if(TmpBm16.Width <= 0 || TmpBm16.Height <= 0 || TmpBm16.Planes != 1 || TmpBm16.BitsPixel == 0){
*Bm16 = NULL;
*dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
}
}
else { /* from DIB */
*Bm16 = NULL;
*dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
}
return(size);
}
@@ -6085,6 +6147,7 @@ int U_WMRSTRETCHDIB_get(
Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, yDst ));
Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xDst ));
*dib = ( contents + offsetof(U_WMRSTRETCHDIB, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
return(size);
}
@@ -6914,7 +6977,12 @@ int U_WMRCREATEFONTINDIRECT_get(
const char *contents,
const char **font
){
- return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEFONTINDIRECT), NULL, NULL, font);
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEFONTINDIRECT), NULL, NULL, font);
+ if(size){
+ if(IS_MEM_UNSAFE(*font, U_SIZE_FONT_CORE, contents+size))return(0);
+ if(contents + size - *font > U_SIZE_FONT_CORE + 32)return(0); // font name must fit in a 32 bit field
+ }
+ return size;
}
/**
@@ -6927,6 +6995,7 @@ int U_WMRCREATEBRUSHINDIRECT_get(
const char *contents,
const char **brush
){
+ // U_SIZE_WMRCREATEBRUSHINDIRECT is everything, no variable part, so the test below is sufficient
return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEBRUSHINDIRECT), NULL, NULL, brush);
}
@@ -6947,16 +7016,19 @@ int U_WMRCREATEBITMAP_get(void){
\return length of the U_WMRCREATEREGION record in bytes, or 0 on error
\param contents record to extract data from
\param Region pointer to U_REGION structure in memory. Pointer may not be aligned properly for structure.
+
+ Caller must check at the returned Region does not extend outside of the record!
*/
int U_WMRCREATEREGION_get(
const char *contents,
const char **Region
){
- return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEREGION), NULL, NULL, Region);
+ return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEREGION), NULL, NULL, Region);
}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/libuemf/uwmf.h b/src/libuemf/uwmf.h
index 54f7f36fe..2237d2221 100644
--- a/src/libuemf/uwmf.h
+++ b/src/libuemf/uwmf.h
@@ -36,8 +36,8 @@
/*
File: uwmf.h
-Version: 0.0.10
-Date: 24-MAR-2014
+Version: 0.0.11
+Date: 23-APR-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -728,6 +728,7 @@ enum U_WMR_TYPES{
#define U_SIZE_WMRCREATEFONTINDIRECT 26 /**< X 28 */
#define U_SIZE_WMRCREATEBRUSHINDIRECT 14 /**< X 16 */
#define U_SIZE_WMRCREATEREGION 26 /**< X 28 */
+#define U_SIZE_WMRCREATEREGION_CORE 24 /**< X 28 Like U_SIZE_WMRCREATEREGION minus the variable part */
/** @} */
diff --git a/src/libuemf/uwmf_print.c b/src/libuemf/uwmf_print.c
index 0e089a5cd..dd460b2b0 100644
--- a/src/libuemf/uwmf_print.c
+++ b/src/libuemf/uwmf_print.c
@@ -319,7 +319,7 @@ void scan_print(
\param dh void pointer to DIB header
A DIB header in an WMF may be either a BitmapCoreHeader or BitmapInfoHeader.
*/
-void dibheader_print(const void *dh){
+void dibheader_print(const char *dh, const char *blimit){
uint32_t Size;
memcpy(&Size, dh, 4); /* may not be aligned */
if(Size == 0xC ){
@@ -330,7 +330,7 @@ void dibheader_print(const void *dh){
}
else {
printf(" (BitmapInfoHeader) ");
- bitmapinfo_print(dh); /* may not be aligned, called routine must handle it */
+ bitmapinfo_print(dh, blimit); /* may not be aligned, called routine must handle it */
}
}
@@ -922,7 +922,7 @@ void U_WMRSETDIBTODEV_print(const char *contents){
printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y );
printf(" W,H:%d,%d\n", cwh.x, cwh.y );
printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
- printf(" DIB:"); dibheader_print(dib); printf("\n");
+ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n");
}
}
@@ -993,7 +993,7 @@ void U_WMRDIBBITBLT_print(const char *contents){
printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
printf(" W,H:%d,%d\n", cwh.x, cwh.y );
printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
- if(dib){ printf(" DIB:"); dibheader_print(dib); printf("\n"); }
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
else { printf(" DIB: none\n"); }
}
}
@@ -1009,7 +1009,7 @@ void U_WMRDIBSTRETCHBLT_print(const char *contents){
printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y );
printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
- if(dib){ printf(" DIB:"); dibheader_print(dib); printf("\n"); }
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
else { printf(" DIB: none\n"); }
}
}
@@ -1028,7 +1028,7 @@ void U_WMRDIBCREATEPATTERNBRUSH_print(const char *contents){
printf(" Src:Bitmap16:"); bitmap16_print(Bm16); printf("\n");
}
else { /* from DIB */
- printf(" Src:DIB:"); dibheader_print(dib); printf("\n");
+ printf(" Src:DIB:"); dibheader_print(dib, dib+size); printf("\n");
}
}
}
@@ -1046,7 +1046,7 @@ void U_WMRSTRETCHDIB_print(const char *contents){
printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y );
printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
- if(dib){ printf(" DIB:"); dibheader_print(dib); printf("\n"); }
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
else { printf(" DIB: none\n"); }
}
}
diff --git a/src/libuemf/uwmf_print.h b/src/libuemf/uwmf_print.h
index 8daee0feb..54dfe9c9c 100644
--- a/src/libuemf/uwmf_print.h
+++ b/src/libuemf/uwmf_print.h
@@ -37,7 +37,7 @@ void bitmapcoreheader_print(U_BITMAPCOREHEADER ch);
void logbrushw_print(U_WLOGBRUSH lb);
void polypolygon_print(uint16_t nPolys, const uint16_t *aPolyCounts, const char *Points);
void scan_print(U_SCAN sc);
-void dibheader_print(const void *dh);
+void dibheader_print(const char *dh, const char *blimit);
/* prototypes for WMF records */
int wmfheader_print(const char *contents, const char *blimit);