https://git.reactos.org/?p=reactos.git;a=commitdiff;h=70e05170cf8a260326f9bcbd2909fba711df2500

commit 70e05170cf8a260326f9bcbd2909fba711df2500
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Wed Aug 9 08:17:07 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Wed Aug 9 08:17:07 2023 +0900

    [MSPAINT][ATL] Delete deprecated functions (#5542)
    
    - Rewrite CImageDx to reduce improper dependency with CImage.
    - Check if the filename extension is supported before saving the files.
    - Delete deprecated functions in CImage.
    CORE-19094
---
 base/applications/mspaint/atlimagedx.h | 331 ++++++++++++++++++++++++++-------
 base/applications/mspaint/dib.cpp      |  14 +-
 base/applications/mspaint/precomp.h    |   1 -
 base/applications/mspaint/winproc.cpp  |  10 +
 sdk/lib/atl/atlimage.h                 |  55 ------
 5 files changed, 287 insertions(+), 124 deletions(-)

diff --git a/base/applications/mspaint/atlimagedx.h 
b/base/applications/mspaint/atlimagedx.h
index 735d4716dc7..6469e9d471b 100644
--- a/base/applications/mspaint/atlimagedx.h
+++ b/base/applications/mspaint/atlimagedx.h
@@ -7,135 +7,340 @@
 
 #pragma once
 
-class CImageDx : public CImage
+#include <atlimage.h>
+
+namespace GPDE = Gdiplus::DllExports;
+
+class CImageDx
 {
+protected:
+    HBITMAP m_hBitmap = NULL;
+
 public:
-    CImageDx() : CImage()
+    CImageDx()
     {
-        GetImageHorizontalResolution = NULL;
-        GetImageVerticalResolution = NULL;
-        BitmapSetResolution = NULL;
+        _shared()->AddRef();
     }
 
-    BOOL GetResolution(Gdiplus::GpImage *pImage, float *pxDpi, float *pyDpi)
+    ~CImageDx()
     {
-        *pxDpi = 96;
-        *pyDpi = 96;
+        if (m_hBitmap)
+            ::DeleteObject(m_hBitmap);
+
+        _shared()->Release();
+    }
+
+    void Attach(HBITMAP hbm)
+    {
+        if (m_hBitmap)
+            ::DeleteObject(m_hBitmap);
+        m_hBitmap = hbm;
+    }
+
+    HBITMAP Detach()
+    {
+        HBITMAP hbmOld = m_hBitmap;
+        m_hBitmap = NULL;
+        return hbmOld;
+    }
 
-        if (GetImageHorizontalResolution == NULL || GetImageVerticalResolution 
== NULL)
+    BOOL GetResolution(Gdiplus::GpImage *pImage, float *pxDpi, float *pyDpi)
+    {
+        if (!get_fn(_shared()->m_GetImageHorizontalResolution, 
"GdipGetImageHorizontalResolution") ||
+            !get_fn(_shared()->m_GetImageVerticalResolution, 
"GdipGetImageVerticalResolution"))
         {
-            GetImageHorizontalResolution =
-                
AddrOf<GETIMAGEHORIZONTALRESOLUTION>("GdipGetImageHorizontalResolution");
-            GetImageVerticalResolution =
-                
AddrOf<GETIMAGEVERTICALRESOLUTION>("GdipGetImageVerticalResolution");
+            return FALSE;
         }
 
-        if (GetImageHorizontalResolution == NULL || GetImageVerticalResolution 
== NULL)
-            return FALSE;
+        if (pxDpi)
+            _shared()->m_GetImageHorizontalResolution(pImage, pxDpi);
+        if (pyDpi)
+            _shared()->m_GetImageVerticalResolution(pImage, pyDpi);
 
-        GetImageHorizontalResolution(pImage, pxDpi);
-        GetImageVerticalResolution(pImage, pyDpi);
         return TRUE;
     }
 
-    BOOL SetResolution(Gdiplus::GpBitmap *pBitmap, float xDpi, float yDpi) 
const
+    BOOL SetResolution(Gdiplus::GpBitmap *pBitmap, float xDpi, float yDpi)
     {
-        if (BitmapSetResolution == NULL)
-            BitmapSetResolution = 
AddrOf<BITMAPSETRESOLUTION>("GdipBitmapSetResolution");
-
-        if (BitmapSetResolution == NULL)
+        if (!get_fn(_shared()->m_BitmapSetResolution, 
"GdipBitmapSetResolution"))
             return FALSE;
 
-        BitmapSetResolution(pBitmap, xDpi, yDpi);
+        _shared()->m_BitmapSetResolution(pBitmap, xDpi, yDpi);
         return TRUE;
     }
 
     HRESULT LoadDx(LPCTSTR pszFileName, float *pxDpi, float *pyDpi) throw()
     {
-        // convert the file name string into Unicode
-        CStringW pszNameW(pszFileName);
+        using namespace Gdiplus;
+
+        _shared()->AddRef();
+
+        if (!get_fn(_shared()->m_CreateBitmapFromFile, 
"GdipCreateBitmapFromFile") ||
+            !get_fn(_shared()->m_CreateHBITMAPFromBitmap, 
"GdipCreateHBITMAPFromBitmap") ||
+            !get_fn(_shared()->m_DisposeImage, "GdipDisposeImage"))
+        {
+            _shared()->Release();
+            return E_FAIL;
+        }
 
         // create a GpBitmap object from file
-        using namespace Gdiplus;
         GpBitmap *pBitmap = NULL;
-        if (GetCommon().CreateBitmapFromFile(pszNameW, &pBitmap) != Ok)
+        if (_shared()->m_CreateBitmapFromFile(pszFileName, &pBitmap) != Ok)
         {
+            _shared()->Release();
             return E_FAIL;
         }
 
-        // get bitmap handle
+        // get an HBITMAP
         HBITMAP hbm = NULL;
         Color color(0xFF, 0xFF, 0xFF);
-        Gdiplus::Status status;
-        status = GetCommon().CreateHBITMAPFromBitmap(pBitmap, &hbm, 
color.GetValue());
+        Status status = _shared()->m_CreateHBITMAPFromBitmap(pBitmap, &hbm, 
color.GetValue());
 
         // get the resolution
-        GetResolution((Gdiplus::GpImage*)pBitmap, pxDpi, pyDpi);
+        if (pxDpi || pyDpi)
+            GetResolution((GpImage*)pBitmap, pxDpi, pyDpi);
 
         // delete GpBitmap
-        GetCommon().DisposeImage(pBitmap);
+        _shared()->m_DisposeImage(pBitmap);
 
         // attach it
         if (status == Ok)
             Attach(hbm);
+
+        _shared()->Release();
         return (status == Ok ? S_OK : E_FAIL);
     }
 
     HRESULT SaveDx(LPCTSTR pszFileName, REFGUID guidFileType = GUID_NULL,
-                   float xDpi = 0, float yDpi = 0) const throw()
+                   float xDpi = 0, float yDpi = 0) throw()
     {
         using namespace Gdiplus;
-        ATLASSERT(m_hbm);
-
-        // TODO & FIXME: set parameters (m_rgbTransColor etc.)
 
-        // convert the file name string into Unicode
-        CStringW pszNameW(pszFileName);
+        _shared()->AddRef();
 
-        // if the file type is null, get the file type from extension
-        const GUID *FileType = &guidFileType;
-        if (::IsEqualGUID(guidFileType, GUID_NULL))
+        if (!get_fn(_shared()->m_CreateBitmapFromHBITMAP, 
"GdipCreateBitmapFromHBITMAP") ||
+            !get_fn(_shared()->m_SaveImageToFile, "GdipSaveImageToFile") ||
+            !get_fn(_shared()->m_DisposeImage, "GdipDisposeImage"))
         {
-            LPCWSTR pszExt = GetFileExtension(pszNameW);
-            FileType = FileTypeFromExtension(pszExt);
-        }
-
-        // get CLSID from file type
-        CLSID clsid;
-        if (!GetClsidFromFileType(&clsid, FileType))
+            _shared()->Release();
             return E_FAIL;
+        }
 
         // create a GpBitmap from HBITMAP
         GpBitmap *pBitmap = NULL;
-        GetCommon().CreateBitmapFromHBITMAP(m_hbm, NULL, &pBitmap);
+        _shared()->m_CreateBitmapFromHBITMAP(m_hBitmap, NULL, &pBitmap);
 
         // set the resolution
         SetResolution(pBitmap, xDpi, yDpi);
 
+        // Get encoders
+        UINT cEncoders = 0;
+        ImageCodecInfo* pEncoders = GetAllEncoders(cEncoders);
+
+        // if the file type is null, get the file type from extension
+        CLSID clsid;
+        if (::IsEqualGUID(guidFileType, GUID_NULL))
+        {
+            CString strExt(PathFindExtension(pszFileName));
+            clsid = FindCodecForExtension(strExt, pEncoders, cEncoders);
+        }
+        else
+        {
+            clsid = FindCodecForFileType(guidFileType, pEncoders, cEncoders);
+        }
+
+        delete[] pEncoders;
+
         // save to file
-        Status status;
-        status = GetCommon().SaveImageToFile(pBitmap, pszNameW, &clsid, NULL);
+        Status status = _shared()->m_SaveImageToFile(pBitmap, pszFileName, 
&clsid, NULL);
 
         // destroy GpBitmap
-        GetCommon().DisposeImage(pBitmap);
+        _shared()->m_DisposeImage(pBitmap);
+
+        _shared()->Release();
 
         return (status == Ok ? S_OK : E_FAIL);
     }
 
+    static BOOL IsExtensionSupported(PWCHAR pchDotExt)
+    {
+        _shared()->AddRef();
+
+        UINT cEncoders;
+        Gdiplus::ImageCodecInfo* pEncoders = GetAllEncoders(cEncoders);
+
+        CLSID clsid = FindCodecForExtension(pchDotExt, pEncoders, cEncoders);
+        BOOL ret = !::IsEqualGUID(clsid, CLSID_NULL);
+        delete[] pEncoders;
+
+        _shared()->Release();
+        return ret;
+    }
+
 protected:
-    // get procedure address of the DLL
-    template <typename TYPE>
-    TYPE AddrOf(const char *name) const
+    using FN_Startup = decltype(&Gdiplus::GdiplusStartup);
+    using FN_Shutdown = decltype(&Gdiplus::GdiplusShutdown);
+    using FN_GetImageHorizontalResolution = 
decltype(&GPDE::GdipGetImageHorizontalResolution);
+    using FN_GetImageVerticalResolution = 
decltype(&GPDE::GdipGetImageVerticalResolution);
+    using FN_BitmapSetResolution = decltype(&GPDE::GdipBitmapSetResolution);
+    using FN_CreateBitmapFromHBITMAP = 
decltype(&GPDE::GdipCreateBitmapFromHBITMAP);
+    using FN_CreateBitmapFromFile = decltype(&GPDE::GdipCreateBitmapFromFile);
+    using FN_CreateHBITMAPFromBitmap = 
decltype(&GPDE::GdipCreateHBITMAPFromBitmap);
+    using FN_SaveImageToFile = decltype(&GPDE::GdipSaveImageToFile);
+    using FN_DisposeImage = decltype(&GPDE::GdipDisposeImage);
+    using FN_GetImageEncodersSize = decltype(&GPDE::GdipGetImageEncodersSize);
+    using FN_GetImageEncoders = decltype(&GPDE::GdipGetImageEncoders);
+
+    struct SHARED
+    {
+        HINSTANCE                       m_hGdiPlus                      = NULL;
+        LONG                            m_cRefs                         = 0;
+        ULONG_PTR                       m_dwToken                       = 0;
+        FN_Shutdown                     m_Shutdown                      = NULL;
+        FN_GetImageHorizontalResolution m_GetImageHorizontalResolution  = NULL;
+        FN_GetImageVerticalResolution   m_GetImageVerticalResolution    = NULL;
+        FN_BitmapSetResolution          m_BitmapSetResolution           = NULL;
+        FN_CreateBitmapFromHBITMAP      m_CreateBitmapFromHBITMAP       = NULL;
+        FN_CreateBitmapFromFile         m_CreateBitmapFromFile          = NULL;
+        FN_CreateHBITMAPFromBitmap      m_CreateHBITMAPFromBitmap       = NULL;
+        FN_SaveImageToFile              m_SaveImageToFile               = NULL;
+        FN_DisposeImage                 m_DisposeImage                  = NULL;
+        FN_GetImageEncodersSize         m_GetImageEncodersSize          = NULL;
+        FN_GetImageEncoders             m_GetImageEncoders              = NULL;
+
+        HINSTANCE Init()
+        {
+            if (m_hGdiPlus)
+                return m_hGdiPlus;
+
+            m_hGdiPlus = ::LoadLibraryW(L"gdiplus.dll");
+            if (!m_hGdiPlus)
+                return NULL;
+
+            FN_Startup Startup = (FN_Startup)GetProcAddress(m_hGdiPlus, 
"GdiplusStartup");
+            m_Shutdown = (FN_Shutdown)GetProcAddress(m_hGdiPlus, 
"GdiplusShutdown");
+            if (!Startup || !m_Shutdown)
+            {
+                ::FreeLibrary(m_hGdiPlus);
+                m_hGdiPlus = NULL;
+                return NULL;
+            }
+
+            Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+            Startup(&m_dwToken, &gdiplusStartupInput, NULL);
+
+            return m_hGdiPlus;
+        }
+
+        void Free()
+        {
+            ::FreeLibrary(m_hGdiPlus);
+            ZeroMemory(this, sizeof(*this));
+        }
+
+        LONG AddRef()
+        {
+            return ++m_cRefs;
+        }
+
+        LONG Release()
+        {
+            if (--m_cRefs == 0)
+            {
+                Free();
+                return 0;
+            }
+            return m_cRefs;
+        }
+    };
+
+    static SHARED* _shared()
+    {
+        static SHARED s_shared;
+        return &s_shared;
+    }
+
+    static Gdiplus::ImageCodecInfo* GetAllEncoders(UINT& cEncoders)
+    {
+        Gdiplus::ImageCodecInfo *ret = NULL;
+        UINT total_size;
+
+        if (!get_fn(_shared()->m_GetImageEncodersSize, 
"GdipGetImageEncodersSize") ||
+            !get_fn(_shared()->m_GetImageEncoders, "GdipGetImageEncoders"))
+        {
+            cEncoders = 0;
+            return NULL;
+        }
+
+        _shared()->m_GetImageEncodersSize(&cEncoders, &total_size);
+        if (total_size == 0)
+            return NULL;
+
+        ret = new Gdiplus::ImageCodecInfo[total_size / sizeof(ret[0])];
+        if (ret == NULL)
+        {
+            cEncoders = 0;
+            return NULL;
+        }
+
+        _shared()->m_GetImageEncoders(cEncoders, total_size, ret);
+
+        return ret; // needs delete[]
+    }
+
+    template <typename FN_T>
+    static bool get_fn(FN_T& fn, const char *name)
     {
-        FARPROC proc = ::GetProcAddress(GetCommon().hinstGdiPlus, name);
-        return reinterpret_cast<TYPE>(proc);
+        if (fn)
+            return true;
+        HINSTANCE hGdiPlus = _shared()->Init();
+        fn = reinterpret_cast<FN_T>(::GetProcAddress(hGdiPlus, name));
+        return fn != NULL;
     }
 
-    typedef St (WINGDIPAPI *GETIMAGEHORIZONTALRESOLUTION)(Im *, float*);
-    typedef St (WINGDIPAPI *GETIMAGEVERTICALRESOLUTION)(Im *, float*);
-    typedef St (WINGDIPAPI *BITMAPSETRESOLUTION)(Bm *, float, float);
+    // CImage::FindCodecForExtension is private. We have to duplicate it at 
here...
+    static CLSID
+    FindCodecForExtension(LPCTSTR dotext, const Gdiplus::ImageCodecInfo 
*pCodecs, UINT nCodecs)
+    {
+        for (UINT i = 0; i < nCodecs; ++i)
+        {
+            CString strSpecs(pCodecs[i].FilenameExtension);
+            int ichOld = 0, ichSep;
+            for (;;)
+            {
+                ichSep = strSpecs.Find(TEXT(';'), ichOld);
+
+                CString strSpec;
+                if (ichSep < 0)
+                    strSpec = strSpecs.Mid(ichOld);
+                else
+                    strSpec = strSpecs.Mid(ichOld, ichSep - ichOld);
+
+                int ichDot = strSpec.ReverseFind(TEXT('.'));
+                if (ichDot >= 0)
+                    strSpec = strSpec.Mid(ichDot);
+
+                if (!dotext || strSpec.CompareNoCase(dotext) == 0)
+                    return pCodecs[i].Clsid;
+
+                if (ichSep < 0)
+                    break;
+
+                ichOld = ichSep + 1;
+            }
+        }
+        return CLSID_NULL;
+    }
 
-    GETIMAGEHORIZONTALRESOLUTION    GetImageHorizontalResolution;
-    GETIMAGEVERTICALRESOLUTION      GetImageVerticalResolution;
-    mutable BITMAPSETRESOLUTION     BitmapSetResolution;
+    // CImage::FindCodecForFileType is private. We have to duplicate it at 
here...
+    static CLSID
+    FindCodecForFileType(REFGUID guidFileType, const Gdiplus::ImageCodecInfo 
*pCodecs, UINT nCodecs)
+    {
+        for (UINT iInfo = 0; iInfo < nCodecs; ++iInfo)
+        {
+            if (::IsEqualGUID(pCodecs[iInfo].FormatID, guidFileType))
+                return pCodecs[iInfo].Clsid;
+        }
+        return CLSID_NULL;
+    }
 };
diff --git a/base/applications/mspaint/dib.cpp 
b/base/applications/mspaint/dib.cpp
index ea5ead7427a..a5b3f0b7896 100644
--- a/base/applications/mspaint/dib.cpp
+++ b/base/applications/mspaint/dib.cpp
@@ -262,7 +262,7 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCWSTR name, BOOL 
fIsMainFile)
 
     // load the image
     CImageDx img;
-    float xDpi, yDpi;
+    float xDpi = 0, yDpi = 0;
     HRESULT hr = img.LoadDx(name, &xDpi, &yDpi);
     if (FAILED(hr))
     {
@@ -274,12 +274,16 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCWSTR name, BOOL 
fIsMainFile)
     if (!fIsMainFile)
         return hBitmap;
 
+    if (xDpi <= 0 || yDpi <= 0)
+    {
+        HDC hDC = ::GetDC(NULL);
+        xDpi = ::GetDeviceCaps(hDC, LOGPIXELSX);
+        yDpi = ::GetDeviceCaps(hDC, LOGPIXELSY);
+        ::ReleaseDC(NULL, hDC);
+    }
+
     g_xDpi = xDpi;
     g_yDpi = yDpi;
-    if (g_xDpi <= 0)
-        g_xDpi = 96;
-    if (g_yDpi <= 0)
-        g_yDpi = 96;
 
     SetBitmapAndInfo(hBitmap, name, &find, TRUE);
     return hBitmap;
diff --git a/base/applications/mspaint/precomp.h 
b/base/applications/mspaint/precomp.h
index 368ce304461..385cc985a4f 100644
--- a/base/applications/mspaint/precomp.h
+++ b/base/applications/mspaint/precomp.h
@@ -13,7 +13,6 @@
 #include <tchar.h>
 #include <atlbase.h>
 #include <atlcom.h>
-#include <atlimage.h>
 #include <atlpath.h>
 #include <atlstr.h>
 #include <atlwin.h>
diff --git a/base/applications/mspaint/winproc.cpp 
b/base/applications/mspaint/winproc.cpp
index a15e6dd3d6b..de22a406243 100644
--- a/base/applications/mspaint/winproc.cpp
+++ b/base/applications/mspaint/winproc.cpp
@@ -141,6 +141,16 @@ void CMainWindow::saveImage(BOOL overwrite)
 {
     canvasWindow.finishDrawing();
 
+    // Is the extension not supported?
+    PWCHAR pchDotExt = PathFindExtensionW(g_szFileName);
+    if (pchDotExt && *pchDotExt && !CImageDx::IsExtensionSupported(pchDotExt))
+    {
+        // Remove the extension
+        PathRemoveExtensionW(g_szFileName);
+        // No overwrite
+        overwrite = FALSE;
+    }
+
     if (g_isAFile && overwrite)
     {
         imageModel.SaveImage(g_szFileName);
diff --git a/sdk/lib/atl/atlimage.h b/sdk/lib/atl/atlimage.h
index bbf7dc6a115..462b63b1e92 100644
--- a/sdk/lib/atl/atlimage.h
+++ b/sdk/lib/atl/atlimage.h
@@ -1056,50 +1056,6 @@ protected:
         return CLSID_NULL;
     }
 
-    // Deprecated. Don't use this
-    static const GUID *FileTypeFromExtension(LPCTSTR dotext)
-    {
-        CImage dummy; // HACK: Initialize common
-        UINT cEncoders = 0;
-        Gdiplus::ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
-
-        for (UINT i = 0; i < cEncoders; ++i)
-        {
-            CString strSpecs(pEncoders[i].FilenameExtension);
-            int ichOld = 0, ichSep;
-            for (;;)
-            {
-                ichSep = strSpecs.Find(TEXT(';'), ichOld);
-
-                CString strSpec;
-                if (ichSep < 0)
-                    strSpec = strSpecs.Mid(ichOld);
-                else
-                    strSpec = strSpecs.Mid(ichOld, ichSep - ichOld);
-
-                int ichDot = strSpec.ReverseFind(TEXT('.'));
-                if (ichDot >= 0)
-                    strSpec = strSpec.Mid(ichDot);
-
-                if (!dotext || strSpec.CompareNoCase(dotext) == 0)
-                {
-                    static GUID s_guid;
-                    s_guid = pEncoders[i].FormatID;
-                    delete[] pEncoders;
-                    return &s_guid;
-                }
-
-                if (ichSep < 0)
-                    break;
-
-                ichOld = ichSep + 1;
-            }
-        }
-
-        delete[] pEncoders;
-        return NULL;
-    }
-
     static CLSID
     FindCodecForFileType(REFGUID guidFileType, const Gdiplus::ImageCodecInfo 
*pCodecs, UINT nCodecs)
     {
@@ -1111,17 +1067,6 @@ protected:
         return CLSID_NULL;
     }
 
-    // Deprecated. Don't use this
-    static bool GetClsidFromFileType(CLSID *clsid, const GUID *guid)
-    {
-        CImage dummy; // HACK: Initialize common
-        UINT cEncoders = 0;
-        Gdiplus::ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
-        *clsid = FindCodecForFileType(*guid, pEncoders, cEncoders);
-        delete[] pEncoders;
-        return true;
-    }
-
     static Gdiplus::ImageCodecInfo* _getAllEncoders(UINT& cEncoders)
     {
         UINT total_size = 0;

Reply via email to