Rect(Integer members) version for GdipEnumerateMetafileSrcRectDestRect
Signed-off-by: Dongwan Kim kdw6485@gmail.com --- dlls/gdiplus/gdiplus.spec | 2 +- dlls/gdiplus/metafile.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index bda8bd56a3f..15d9b5d81e8 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -201,7 +201,7 @@ 201 stdcall GdipEnumerateMetafileSrcRectDestPoints(ptr ptr ptr long ptr long ptr ptr ptr) 202 stub GdipEnumerateMetafileSrcRectDestPointsI 203 stdcall GdipEnumerateMetafileSrcRectDestRect(ptr ptr ptr ptr long ptr ptr ptr) -204 stub GdipEnumerateMetafileSrcRectDestRectI +204 stdcall GdipEnumerateMetafileSrcRectDestRectI(ptr ptr ptr ptr long ptr ptr ptr) 205 stdcall GdipFillClosedCurve2(ptr ptr ptr long float long) 206 stdcall GdipFillClosedCurve2I(ptr ptr ptr long float long) 207 stdcall GdipFillClosedCurve(ptr ptr ptr long) diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c index f4824d4257b..d79c939218c 100644 --- a/dlls/gdiplus/metafile.c +++ b/dlls/gdiplus/metafile.c @@ -3666,6 +3666,25 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestRect( GpGraphics *graphics, return GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, points, 3, src, srcUnit, callback, cb_data, attrs); } +GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestRectI( GpGraphics * graphics, + GDIPCONST GpMetafile *metafile, GDIPCONST Rect *destRect, + GDIPCONST Rect *srcRect, Unit srcUnit, EnumerateMetafileProc callback, + VOID *cb_data, GDIPCONST GpImageAttributes *attrs ) +{ + GpRectF destRectF, srcRectF; + + destRectF.X = destRect->X; + destRectF.Y = destRect->Y; + destRectF.Width = destRect->Width; + destRectF.Height = destRect->Height; + + srcRectF.X = srcRect->X; + srcRectF.Y = srcRect->Y; + srcRectF.Width = srcRect->Width; + srcRectF.Height = srcRect->Height; + + return GdipEnumerateMetafileSrcRectDestRect( graphics, metafile, &destRectF, &srcRectF, srcUnit, callback, cb_data, attrs); +}
GpStatus WINGDIPAPI GdipEnumerateMetafileDestRect(GpGraphics *graphics, GDIPCONST GpMetafile *metafile, GDIPCONST GpRectF *dest,
We should check if destRect or srcRect are NULL before dereferencing them. Based on the float version, a NULL destRect should result in an InvalidParameter return, and a NULL srcRect should be passed through as NULL.
Thanks. That's a good point. In Windows, GdipEnumerateMetafileSrcRectDestRectI is defined in gdiplusflat.h as : GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestRectI( GpGraphics * graphics, GDIPCONST GpMetafile * metafile, GDIPCONST Rect & destRect, GDIPCONST Rect & srcRect, Unit srcUnit, EnumerateMetafileProc callback, VOID * callbackData, GDIPCONST GpImageAttributes * imageAttributes);
it means the arguments normally cannot be null because the compiler would block. We could call the function with null value of two arguments when we use GetProcAddress. In that case, the program gets a crash in Windows. if a developer made a SEH block, the program should go to the exception handler. So, I think we should not check for null pointers to make it work the same.
2021년 5월 17일 (월) 오전 1:06, Esme Povirk (they/them) esme@codeweavers.com님이 작성:
We should check if destRect or srcRect are NULL before dereferencing them. Based on the float version, a NULL destRect should result in an InvalidParameter return, and a NULL srcRect should be passed through as NULL.
The API isn't only callable from C++. In C or other languages, a NULL pointer could be passed in.
The only way to know for sure is to test, but usually gdiplus does not crash on NULL inputs.
You can find the result with below simple code :
#include <windows.h> #include <iostream>
#include <gdiplusenums.h> #include <gdiplustypes.h>
#include <gdiplusgpstubs.h> #include <gdiplusmetaheader.h>
#include <gdipluspixelformats.h> #include <gdipluscolor.h> #include <gdipluscolormatrix.h> #include <gdiplusimaging.h> struct IDirectDrawSurface7; #include <gdiplusflat.h>
#pragma comment(lib,"gdiplus")
typedef GpStatus (*pfnGdipEnumerateMetafileSrcRectDestRectI)( GpGraphics* graphics, GDIPCONST GpMetafile* metafile, GDIPCONST Rect* destRect, GDIPCONST Rect* srcRect, Unit srcUnit, EnumerateMetafileProc callback, VOID* callbackData, GDIPCONST GpImageAttributes* imageAttributes );
int main() {
pfnGdipEnumerateMetafileSrcRectDestRectI pfunc = (pfnGdipEnumerateMetafileSrcRectDestRectI)GetProcAddress(GetModuleHandleA("gdiplus"), "GdipEnumerateMetafileSrcRectDestRectI"); __try {
pfunc(0, 0, 0, 0, UnitDisplay, 0, 0, 0); printf("ok\n"); } __except (EXCEPTION_EXECUTE_HANDLER) { printf("Executing SEH __except block\r\n"); } system("pause");
return 0; }
I have tested in win7, win10 and the program goes to the exception handler in both environments.
Thanks.
You forgot the calling convention on your prototype, so I'm not sure this calls the function correctly. Building it as a Wine test, or making a call first that returns without crashing, would make this easier to determine.
I fixed my prototype and made the first call succeed.
#include <windows.h> #include <iostream>
#include <gdiplusenums.h> #include <gdiplustypes.h>
#include <gdiplusgpstubs.h> #include <gdiplusmetaheader.h>
#include <gdipluspixelformats.h> #include <gdipluscolor.h> #include <gdipluscolormatrix.h> #include <gdiplusimaging.h> struct IDirectDrawSurface7; #include <gdiplusflat.h>
#pragma comment(lib,"gdiplus")
typedef GpStatus (WINGDIPAPI *pfnGdipEnumerateMetafileSrcRectDestRectI)( GpGraphics* graphics, GDIPCONST GpMetafile* metafile, GDIPCONST Rect* destRect, GDIPCONST Rect* srcRect, Unit srcUnit, EnumerateMetafileProc callback, VOID* callbackData, GDIPCONST GpImageAttributes* imageAttributes );
int main() {
Rect s{}, d{}; auto m = LoadLibraryA("gdiplus.dll"); pfnGdipEnumerateMetafileSrcRectDestRectI pfunc = (pfnGdipEnumerateMetafileSrcRectDestRectI)GetProcAddress(m, "GdipEnumerateMetafileSrcRectDestRectI"); __try { pfunc(0, 0, &s, &d, UnitDisplay, 0, 0, 0); printf("ok\n"); pfunc(0, 0, 0, 0, UnitDisplay, 0, 0, 0); printf("ok\n"); } __except (EXCEPTION_EXECUTE_HANDLER) { printf("Executing SEH __except block\r\n"); } system("pause"); }
And the result is printed as below :
ok Executing SEH __except block
Thanks.