changeset 5577:9e74e761b108 find-refactoring

integration mainline->find-refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 26 Apr 2024 17:43:22 +0200
parents 5a13483d12c5 (current diff) 3a6d6d35193c (diff)
children 77570cce8855
files NEWS OrthancServer/CMakeLists.txt OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h
diffstat 22 files changed, 541 insertions(+), 289 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Apr 26 16:32:18 2024 +0200
+++ b/NEWS	Fri Apr 26 17:43:22 2024 +0200
@@ -36,10 +36,12 @@
 * Housekeeper plugin: Added an option "LimitMainDicomTagsReconstructLevel"
   (allowed values: "Patient", "Study", "Series", "Instance").  This can greatly speed
   up the housekeeper process e.g. if you have only update the Study level ExtraMainDicomTags.
-* SDK: added OrthancPluginLogMessage that is a new primitive for plugins to log messages.
-  This new primitive will display the plugin name, plugin file name and plugin line number
-  in the logs.  If they are using the OrthancFramework, plugins should now use LOG(INFO),
-  LOG(WARNING) and LOG(ERROR) to log their messages.
+* SDK: added OrthancPluginLogMessage() that is a new primitive for
+  plugins to log messages.  This new primitive will display the plugin
+  name, the plugin file name, and the plugin line number in the
+  logs. If they are not using the LOG() facilities provided by the
+  OrthancFramework, plugins should now use ORTHANC_PLUGINS_LOG_INFO(),
+  ORTHANC_PLUGINS_LOG_WARNING(), and ORTHANC_PLUGINS_LOG_ERROR().
 
 
 Version 1.12.3 (2024-01-31)
--- a/OrthancFramework/Sources/Logging.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancFramework/Sources/Logging.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -525,6 +525,7 @@
 
 #include "Enumerations.h"
 #include "SystemToolbox.h"
+#include "Toolbox.h"
 
 #include <fstream>
 #include <boost/filesystem.hpp>
@@ -560,7 +561,8 @@
 static boost::mutex                             loggingStreamsMutex_;
 static Orthanc::Logging::NullStream             nullStream_;
 static OrthancPluginContext*                    pluginContext_ = NULL;    // this is != NULL only when running from a plugin
-static const char*                              pluginName_ = NULL;       // this is != NULL only when running from a plugin
+static std::string                              pluginName_;              // this string can only be non-empty if running from a plugin
+static bool                                     hasOrthancAdvancedLogging_ = false;  // Whether the Orthanc runtime is >= 1.12.4
 static boost::recursive_mutex                   threadNamesMutex_;
 static std::map<boost::thread::id, std::string> threadNames_;
 static bool                                     enableThreadNames_ = true;
@@ -784,14 +786,23 @@
     {
       assert(sizeof(_OrthancPluginService) == sizeof(int32_t));
 
+      if (pluginContext == NULL)
+      {
+        throw OrthancException(ErrorCode_NullPointer);
+      }
+
       boost::mutex::scoped_lock lock(loggingStreamsMutex_);
       loggingStreamsContext_.reset(NULL);
       pluginContext_ = reinterpret_cast<OrthancPluginContext*>(pluginContext);
 
+      // The value "hasOrthancAdvancedLogging_" is cached to avoid computing it on every logged message
+      hasOrthancAdvancedLogging_ = Toolbox::IsVersionAbove(pluginContext_->orthancVersion, 1, 12, 4);
+
       EnableInfoLevel(true);  // allow the plugin to log at info level (but the Orthanc Core still decides of the level)
     }
 
-    void InitializePluginContext(void* pluginContext, const char* pluginName)
+
+    void InitializePluginContext(void* pluginContext, const std::string& pluginName)
     {
       InitializePluginContext(pluginContext);
       pluginName_ = pluginName;
@@ -870,10 +881,17 @@
     }
 
 
-    void InternalLogger::Setup(LogCategory category,
-                               const char* pluginName,
-                               const char* file,
-                               int line)
+    InternalLogger::InternalLogger(LogLevel level,
+                                   LogCategory category,
+                                   const char* pluginName,
+                                   const char* file,
+                                   int line) :
+      lock_(loggingStreamsMutex_, boost::defer_lock_t()),
+      level_(level),
+      stream_(&nullStream_),  // By default, logging to "/dev/null" is simulated
+      category_(category),
+      file_(file),
+      line_(line)
     {
       if (pluginContext_ != NULL)
       {
@@ -913,7 +931,9 @@
       
           if (loggingStreamsContext_.get() == NULL)
           {
-            fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine (or did you forgot to initialize it ?)\n"); // have you called Orthanc::Logging::InitializePluginContext ?
+            // Have you called Orthanc::Logging::InitializePluginContext()?
+            fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine "
+                    "(or did you forgot to initialize it?)\n");
             lock_.unlock();
             return;
           }
@@ -963,50 +983,6 @@
     }
 
 
-    InternalLogger::InternalLogger(LogLevel level,
-                                   LogCategory category,
-                                   const char* file,
-                                   int line) :
-      lock_(loggingStreamsMutex_, boost::defer_lock_t()),
-      level_(level),
-      stream_(&nullStream_),  // By default, logging to "/dev/null" is simulated
-      category_(category),
-      file_(file),
-      line_(line)
-    {
-      Setup(category, NULL, file, line);
-    }
-
-    InternalLogger::InternalLogger(LogLevel level,
-                                   LogCategory category,
-                                   const char* pluginName,
-                                   const char* file,
-                                   int line) :
-      lock_(loggingStreamsMutex_, boost::defer_lock_t()),
-      level_(level),
-      stream_(&nullStream_),  // By default, logging to "/dev/null" is simulated
-      category_(category),
-      file_(file),
-      line_(line)
-    {
-      Setup(category, pluginName, file, line);
-    }
-
-
-
-    InternalLogger::InternalLogger(LogLevel level,
-                                   const char* file,
-                                   int line) :
-      lock_(loggingStreamsMutex_, boost::defer_lock_t()),
-      level_(level),
-      stream_(&nullStream_),  // By default, logging to "/dev/null" is simulated
-      category_(LogCategory_GENERIC),
-      file_(file),
-      line_(line)
-    {
-      Setup(LogCategory_GENERIC, NULL, file, line);
-    }
-
 
     InternalLogger::~InternalLogger()
     {
@@ -1018,14 +994,15 @@
 
         if (pluginContext_ != NULL)
         {
-          if (pluginName_ != NULL) // this shall happen only if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4)
+          if (!pluginName_.empty() &&
+              hasOrthancAdvancedLogging_)
           {
             _OrthancPluginLogMessage m;
             m.category = category_;
             m.level = level_;
             m.file = file_;
             m.line = line_;
-            m.plugin = pluginName_;
+            m.plugin = pluginName_.c_str();
             m.message = message.c_str();
             pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogMessage, &m);
           }
--- a/OrthancFramework/Sources/Logging.h	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancFramework/Sources/Logging.h	Fri Apr 26 17:43:22 2024 +0200
@@ -80,8 +80,8 @@
     // "pluginContext" must be of type "OrthancPluginContext"
     ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext);
 
-    // note: this variant shall be called only from a plugin and only if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4)
-    ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext, const char* pluginName);
+    ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext,
+                                                const std::string& pluginName);
 
     ORTHANC_PUBLIC void Initialize();
 
@@ -181,15 +181,22 @@
 
 #  define LOG(level)     ::Orthanc::Logging::InternalLogger             \
   (::Orthanc::Logging::LogLevel_ ## level,                              \
-   ::Orthanc::Logging::LogCategory_GENERIC, __ORTHANC_FILE__, __LINE__)
+   ::Orthanc::Logging::LogCategory_GENERIC, NULL /* no plugin */,       \
+   __ORTHANC_FILE__, __LINE__)
+
 #  define VLOG(unused)   ::Orthanc::Logging::InternalLogger             \
   (::Orthanc::Logging::LogLevel_TRACE,                                  \
-   ::Orthanc::Logging::LogCategory_GENERIC, __ORTHANC_FILE__, __LINE__)
+   ::Orthanc::Logging::LogCategory_GENERIC, NULL /* no plugin */,       \
+   __ORTHANC_FILE__, __LINE__)
+
 #  define CLOG(level, category) ::Orthanc::Logging::InternalLogger      \
   (::Orthanc::Logging::LogLevel_ ## level,                              \
-   ::Orthanc::Logging::LogCategory_ ## category, __ORTHANC_FILE__, __LINE__)
-#  define LOG_FROM_PLUGIN(level, category, pluginName, file, line)  ::Orthanc::Logging::InternalLogger      \
-  (level, category, pluginName, file, line)
+   ::Orthanc::Logging::LogCategory_ ## category, NULL /* no plugin */,  \
+   __ORTHANC_FILE__, __LINE__)
+
+#  define LOG_FROM_PLUGIN(level, category, pluginName, file, line)      \
+  ::Orthanc::Logging::InternalLogger(level, category, pluginName, file, line)
+
 #endif
 
 
@@ -270,28 +277,13 @@
       const char*                         file_;
       uint32_t                            line_;
 
-      void Setup(LogCategory category,
-                 const char* pluginName,
-                 const char* file,
-                 int line);
-
     public:
       InternalLogger(LogLevel level,
                      LogCategory category,
-                     const char* file,
-                     int line);
-
-      InternalLogger(LogLevel level,
-                     LogCategory category,
                      const char* pluginName,
                      const char* file,
                      int line);
 
-      // For backward binary compatibility with Orthanc Framework <= 1.8.0
-      InternalLogger(LogLevel level,
-                     const char* file,
-                     int line);
-
       ~InternalLogger();
       
       template <typename T>
--- a/OrthancFramework/Sources/Toolbox.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancFramework/Sources/Toolbox.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -2676,6 +2676,139 @@
   }
 
 
+  bool Toolbox::ParseVersion(unsigned int& major,
+                             unsigned int& minor,
+                             unsigned int& revision,
+                             const char* version)
+  {
+    if (version == NULL)
+    {
+      throw OrthancException(ErrorCode_NullPointer);
+    }
+
+#ifdef _MSC_VER
+#define ORTHANC_SCANF sscanf_s
+#else
+#define ORTHANC_SCANF sscanf
+#endif
+
+    int a, b, c;
+    if (ORTHANC_SCANF(version, "%4d.%4d.%4d", &a, &b, &c) == 3)
+    {
+      if (a >= 0 &&
+          b >= 0 &&
+          c >= 0)
+      {
+        major = static_cast<unsigned int>(a);
+        minor = static_cast<unsigned int>(b);
+        revision = static_cast<unsigned int>(c);
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+    else if (ORTHANC_SCANF(version, "%4d.%4d", &a, &b) == 2)
+    {
+      if (a >= 0 &&
+          b >= 0)
+      {
+        major = static_cast<unsigned int>(a);
+        minor = static_cast<unsigned int>(b);
+        revision = 0;
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+    else if (ORTHANC_SCANF(version, "%4d", &a) == 1 &&
+             a >= 0)
+    {
+      if (a >= 0)
+      {
+        major = static_cast<unsigned int>(a);
+        minor = 0;
+        revision = 0;
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+
+  bool Toolbox::IsVersionAbove(const char* version,
+                               unsigned int major,
+                               unsigned int minor,
+                               unsigned int revision)
+  {
+    /**
+     * Note: Similar standalone functions are implemented in
+     * "OrthancCPlugin.h" and "OrthancPluginCppWrapper.cpp".
+     **/
+
+    unsigned int actualMajor, actualMinor, actualRevision;
+
+    if (version == NULL)
+    {
+      throw OrthancException(ErrorCode_NullPointer);
+    }
+    else if (!strcmp(version, "mainline"))
+    {
+      // Assume compatibility with the mainline
+      return true;
+    }
+    else if (ParseVersion(actualMajor, actualMinor, actualRevision, version))
+    {
+      if (actualMajor > major)
+      {
+        return true;
+      }
+
+      if (actualMajor < major)
+      {
+        return false;
+      }
+
+      // Check the minor version number
+      assert(actualMajor == major);
+
+      if (actualMinor > minor)
+      {
+        return true;
+      }
+
+      if (actualMinor < minor)
+      {
+        return false;
+      }
+
+      // Check the patch level version number
+      assert(actualMajor == major);
+
+      if (actualRevision >= revision)
+      {
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange, "Not a valid version: " + std::string(version));
+    }
+  }
 }
 
 
--- a/OrthancFramework/Sources/Toolbox.h	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancFramework/Sources/Toolbox.h	Fri Apr 26 17:43:22 2024 +0200
@@ -416,6 +416,15 @@
 
     static std::string GetHumanTransferSpeed(bool full, uint64_t sizeInBytes, uint64_t durationInNanoseconds);
 
+    static bool ParseVersion(unsigned int& major,
+                             unsigned int& minor,
+                             unsigned int& revision,
+                             const char* version);
+
+    static bool IsVersionAbove(const char* version,
+                               unsigned int major,
+                               unsigned int minor,
+                               unsigned int revision);
   };
 }
 
--- a/OrthancFramework/UnitTestsSources/FrameworkTests.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancFramework/UnitTestsSources/FrameworkTests.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -1602,3 +1602,53 @@
   }
 }
 #endif
+
+
+TEST(Toolbox, IsVersionAbove)
+{
+  unsigned int a, b, c;
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "nope"));
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "mainline"));
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, ""));
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "-1"));
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "1.-1"));
+  ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "1.1.-1"));
+
+  ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "14.17.20"));
+  ASSERT_EQ(14u, a);
+  ASSERT_EQ(17u, b);
+  ASSERT_EQ(20u, c);
+
+  ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "18.19"));
+  ASSERT_EQ(18u, a);
+  ASSERT_EQ(19u, b);
+  ASSERT_EQ(0u, c);
+
+  ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "78"));
+  ASSERT_EQ(78u, a);
+  ASSERT_EQ(0u, b);
+  ASSERT_EQ(0u, c);
+
+  ASSERT_TRUE(Toolbox::IsVersionAbove("mainline", 99, 99, 99));
+
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18", 17, 99, 99));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18", 18, 0, 0));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18", 18, 0, 1));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18", 18, 1, 0));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18", 19, 0, 0));
+
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 17, 99, 99));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 18, 18, 99));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 18, 19, 0));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 18, 19, 1));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 18, 20, 0));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 19, 0, 0));
+
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 17, 99, 99));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 18, 99));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 19));
+  ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 20));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 21));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 18, 20, 0));
+  ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 19, 0, 0));
+}
--- a/OrthancServer/CMakeLists.txt	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/CMakeLists.txt	Fri Apr 26 17:43:22 2024 +0200
@@ -500,10 +500,6 @@
     
     ${CMAKE_SOURCE_DIR}/../OrthancFramework/Resources/ThirdParty/base64/base64.cpp
     ${CMAKE_SOURCE_DIR}/../OrthancFramework/Resources/ThirdParty/md5/md5.c
-
-    # the orthanc framework sources
-    ${ORTHANC_CORE_SOURCES}
-
     Plugins/Samples/Common/OrthancPluginCppWrapper.cpp
     )
 
@@ -528,8 +524,6 @@
 
   DefineSourceBasenameForTarget(PluginsDependencies)
 
-  target_include_directories(PluginsDependencies PUBLIC ${CMAKE_SOURCE_DIR}/../OrthancFramework/Sources)
-
   # Add the "-fPIC" option as this static library must be embedded
   # inside shared libraries (important on UNIX)
   set_target_properties(
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -2090,6 +2090,8 @@
         sizeof(int32_t) != sizeof(OrthancPluginStorageCommitmentFailureReason) ||
         sizeof(int32_t) != sizeof(OrthancPluginReceivedInstanceAction) ||
         sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode) ||
+        sizeof(int32_t) != sizeof(OrthancPluginLogLevel) ||
+        sizeof(int32_t) != sizeof(OrthancPluginLogCategory) ||
         static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeBinary) != static_cast<int>(DicomToJsonFlags_IncludeBinary) ||
         static_cast<int>(OrthancPluginDicomToJsonFlags_IncludePrivateTags) != static_cast<int>(DicomToJsonFlags_IncludePrivateTags) ||
         static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeUnknownTags) != static_cast<int>(DicomToJsonFlags_IncludeUnknownTags) ||
--- a/OrthancServer/Plugins/Engine/PluginsManager.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Engine/PluginsManager.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -162,16 +162,16 @@
         return OrthancPluginErrorCode_Success;
 
       case _OrthancPluginService_LogMessage:
-        {
-          const _OrthancPluginLogMessage& m = *reinterpret_cast<const _OrthancPluginLogMessage*>(params);
-          // we may convert directly from OrthancPluginLogLevel to LogLevel (and category) because the enum values must be identical 
-          // for Orthanc::Logging to work both in the core and in the plugins
-          Orthanc::Logging::LogLevel level = static_cast<Orthanc::Logging::LogLevel>(m.level);
-          Orthanc::Logging::LogCategory category = static_cast<Orthanc::Logging::LogCategory>(m.category);
+      {
+        const _OrthancPluginLogMessage& m = *reinterpret_cast<const _OrthancPluginLogMessage*>(params);
+        // We can convert directly from OrthancPluginLogLevel to LogLevel (and category) because the enum values must be identical 
+        // for Orthanc::Logging to work both in the core and in the plugins
+        Orthanc::Logging::LogLevel level = static_cast<Orthanc::Logging::LogLevel>(m.level);
+        Orthanc::Logging::LogCategory category = static_cast<Orthanc::Logging::LogCategory>(m.category);
           
-          LOG_FROM_PLUGIN(level, category, m.plugin, m.file, m.line) << m.message;
-          return OrthancPluginErrorCode_Success;
-        };
+        LOG_FROM_PLUGIN(level, category, m.plugin, m.file, m.line) << m.message;
+        return OrthancPluginErrorCode_Success;
+      }
 
       default:
         break;
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Fri Apr 26 17:43:22 2024 +0200
@@ -1087,6 +1087,43 @@
 
 
   /**
+   * The log levels supported by Orthanc.
+   *
+   * These values must match those of enumeration "LogLevel" in the
+   * Orthanc Core.
+   **/
+  typedef enum
+  {
+    OrthancPluginLogLevel_Error = 0,    /*!< Error log level */
+    OrthancPluginLogLevel_Warning = 1,  /*!< Warning log level */
+    OrthancPluginLogLevel_Info = 2,     /*!< Info log level */
+    OrthancPluginLogLevel_Trace = 3,    /*!< Trace log level */
+
+    _OrthancPluginLogLevel_INTERNAL = 0x7fffffff
+  } OrthancPluginLogLevel;
+
+
+  /**
+   * The log categories supported by Orthanc.
+   *
+   * These values must match those of enumeration "LogCategory" in the
+   * Orthanc Core.
+   **/
+  typedef enum
+  {
+    OrthancPluginLogCategory_Generic = (1 << 0),  /*!< Generic (default) category */
+    OrthancPluginLogCategory_Plugins = (1 << 1),  /*!< Plugin engine related logs (shall not be used by plugins) */
+    OrthancPluginLogCategory_Http    = (1 << 2),  /*!< HTTP related logs */
+    OrthancPluginLogCategory_Sqlite  = (1 << 3),  /*!< SQLite related logs (shall not be used by plugins) */
+    OrthancPluginLogCategory_Dicom   = (1 << 4),  /*!< DICOM related logs */
+    OrthancPluginLogCategory_Jobs    = (1 << 5),  /*!< jobs related logs */
+    OrthancPluginLogCategory_Lua     = (1 << 6),  /*!< Lua related logs (shall not be used by plugins) */
+
+    _OrthancPluginLogCategory_INTERNAL = 0x7fffffff
+  } OrthancPluginLogCategory;
+
+
+  /**
    * @brief A 32-bit memory buffer allocated by the core system of Orthanc.
    *
    * A memory buffer allocated by the core system of Orthanc. When the
@@ -1971,7 +2008,9 @@
         sizeof(int32_t) != sizeof(OrthancPluginMetricsType) ||
         sizeof(int32_t) != sizeof(OrthancPluginDicomWebBinaryMode) ||
         sizeof(int32_t) != sizeof(OrthancPluginStorageCommitmentFailureReason) ||
-        sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode))
+        sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode) ||
+        sizeof(int32_t) != sizeof(OrthancPluginLogLevel) ||
+        sizeof(int32_t) != sizeof(OrthancPluginLogCategory))
     {
       /* Mismatch in the size of the enumerations */
       return 0;
@@ -9480,37 +9519,10 @@
     return context->InvokeService(context, _OrthancPluginService_SetCurrentThreadName, threadName);
   }
 
-  typedef enum
-  {
-    // these values must match LogLevel in the Orthanc Core
-    OrthancPluginLogLevel_Error = 0,    /*!< Error log level */
-    OrthancPluginLogLevel_Warning = 1,  /*!< Warning log level */
-    OrthancPluginLogLevel_Info = 2,     /*!< Info log level */
-    OrthancPluginLogLevel_Trace = 3,    /*!< Trace log level */
-  
-    // Force the enum to be 32 bits
-    OrthancPluginLogLevel_INTERNAL = 0x7FFFFFFF
-  } OrthancPluginLogLevel;
-
-  typedef enum
-  {
-    // these values must match LogCategory in the Orthanc Core
-    OrthancPluginLogCategory_Generic = (1 << 0),  /*!< Generic (default) category */
-    OrthancPluginLogCategory_Plugins = (1 << 1),  /*!< Plugin engine related logs (shall not be used by plugins) */
-    OrthancPluginLogCategory_Http    = (1 << 2),  /*!< HTTP related logs */
-    OrthancPluginLogCategory_Sqlite  = (1 << 3),  /*!< SQLite related logs (shall not be used by plugins) */
-    OrthancPluginLogCategory_Dicom   = (1 << 4),  /*!< DICOM related logs */
-    OrthancPluginLogCategory_Jobs    = (1 << 5),  /*!< jobs related logs */
-    OrthancPluginLogCategory_Lua     = (1 << 6),  /*!< Lua related logs (shall not be used by plugins) */
-
-    // Force the enum to be 32 bits
-    OrthancPluginLogCategory_INTERNAL = 0x7FFFFFFF
-  } OrthancPluginLogCategory;
-
-
-  // note: this structure is also defined in Logging.h and it must be binary compatible
+
   typedef struct
   {
+    /* Note: This structure is also defined in Logging.h and it must be binary compatible */
     const char*               message;
     const char*               plugin;
     const char*               file;
@@ -9524,7 +9536,7 @@
    * @brief Log a message.
    *
    * Log a message using the Orthanc logging system.
-   * 
+   *
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param message The message to be logged.
    * @param plugin The plugin name.
@@ -9546,8 +9558,8 @@
     m.message = message;
     m.plugin = plugin;
     m.file = file;
+    m.line = line;
     m.category = category;
-    m.line = line;
     m.level = level;
     context->InvokeService(context, _OrthancPluginService_LogMessage, &m);
   }
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -61,6 +61,7 @@
 namespace OrthancPlugins
 {
   static OrthancPluginContext* globalContext_ = NULL;
+  static std::string pluginName_;
 
 
   void SetGlobalContext(OrthancPluginContext* context)
@@ -79,20 +80,19 @@
     }
   }
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4)
-  static const char* pluginName_ = NULL;
-
-  void SetGlobalContext(OrthancPluginContext* context, const char* pluginName)
+
+  void SetGlobalContext(OrthancPluginContext* context,
+                        const char* pluginName)
   {
     SetGlobalContext(context);
     pluginName_ = pluginName;
   }
-#endif
+
 
   void ResetGlobalContext()
   {
     globalContext_ = NULL;
-    pluginName_ = NULL;
+    pluginName_.clear();
   }
 
   bool HasGlobalContext()
@@ -113,6 +113,42 @@
     }
   }
 
+
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+  void LogMessage(OrthancPluginLogLevel level,
+                  const char* file,
+                  uint32_t line,
+                  const std::string& message)
+  {
+    if (HasGlobalContext())
+    {
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+      const char* pluginName = (pluginName_.empty() ? NULL : pluginName_.c_str());
+      OrthancPluginLogMessage(GetGlobalContext(), message.c_str(), pluginName, file, line, OrthancPluginLogCategory_Generic, level);
+#else
+      switch (level)
+      {
+        case OrthancPluginLogLevel_Error:
+          OrthancPluginLogError(GetGlobalContext(), message.c_str());
+          break;
+
+        case OrthancPluginLogLevel_Warning:
+          OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
+          break;
+
+        case OrthancPluginLogLevel_Info:
+          OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
+          break;
+
+        default:
+          ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+      }
+#endif
+    }
+  }
+#endif
+
+
   void LogError(const std::string& message)
   {
     if (HasGlobalContext())
@@ -138,30 +174,6 @@
   }
 
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4)
-  // This file does not have any dependencies on Logging.h, we must call the "native" plugin service
-
-  void _LogMessage(OrthancPluginLogLevel level, const char* file, uint32_t line, const std::string& message)
-  {
-    if (HasGlobalContext())
-    {
-      OrthancPluginLogMessage(GetGlobalContext(), message.c_str(), pluginName_, file, line, OrthancPluginLogCategory_Generic, level);
-    }
-  }
-
-  #define LOG_ERROR(msg) _LogMessage(OrthancPluginLogLevel_Error, __ORTHANC_FILE__, __LINE__, msg);
-  #define LOG_WARNING(msg) _LogMessage(OrthancPluginLogLevel_Warning, __ORTHANC_FILE__, __LINE__, msg);
-  #define LOG_INFO(msg) _LogMessage(OrthancPluginLogLevel_Info, __ORTHANC_FILE__, __LINE__, msg);
-
-#else
-
-  #define LOG_ERROR(msg) LogError(msg);
-  #define LOG_WARNING(msg) LogWarning(msg);
-  #define LOG_INFO(msg) LogInfo(msg);
-
-#endif
-
-
   void MemoryBuffer::Check(OrthancPluginErrorCode code)
   {
     if (code != OrthancPluginErrorCode_Success)
@@ -292,7 +304,7 @@
 
     if (!ReadJson(target, buffer_.data, buffer_.size))
     {
-      LOG_ERROR("Cannot convert some memory buffer to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert some memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
@@ -324,7 +336,7 @@
     explicit PluginHttpHeaders(const std::map<std::string, std::string>& httpHeaders)
     {
       for (std::map<std::string, std::string>::const_iterator
-           it = httpHeaders.begin(); it != httpHeaders.end(); ++it)
+             it = httpHeaders.begin(); it != httpHeaders.end(); ++it)
       {
         headersKeys_.push_back(it->first.c_str());
         headersValues_.push_back(it->second.c_str());
@@ -463,7 +475,7 @@
     }
     else
     {
-      LOG_ERROR("Cannot parse JSON: " + std::string(err));
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot parse JSON: " + std::string(err));
       return false;
     }
 #endif
@@ -624,13 +636,13 @@
   {
     if (str_ == NULL)
     {
-      LOG_ERROR("Cannot convert an empty memory buffer to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert an empty memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
     if (!ReadJson(target, str_))
     {
-      LOG_ERROR("Cannot convert some memory buffer to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert some memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
@@ -640,13 +652,13 @@
   {
     if (str_ == NULL)
     {
-      LOG_ERROR("Cannot convert an empty memory buffer to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert an empty memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
     if (!ReadJsonWithoutComments(target, str_))
     {
-      LOG_ERROR("Cannot convert some memory buffer to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert some memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
@@ -684,7 +696,7 @@
 
     if (body.size() > 0xffffffffu)
     {
-      LOG_ERROR("Cannot handle body size > 4GB");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -704,7 +716,7 @@
 
     if (body.size() > 0xffffffffu)
     {
-      LOG_ERROR("Cannot handle body size > 4GB");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -754,7 +766,7 @@
 
     if (str.GetContent() == NULL)
     {
-      LOG_ERROR("Cannot access the Orthanc configuration");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot access the Orthanc configuration");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -762,7 +774,7 @@
 
     if (configuration_.type() != Json::objectValue)
     {
-      LOG_ERROR("Unable to read the Orthanc configuration");
+      ORTHANC_PLUGINS_LOG_ERROR("Unable to read the Orthanc configuration");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
@@ -830,8 +842,8 @@
     {
       if (configuration_[key].type() != Json::objectValue)
       {
-        LOG_ERROR("The configuration section \"" + target.path_ +
-                  "\" is not an associative array as expected");
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration section \"" + target.path_ +
+                                  "\" is not an associative array as expected");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
       }
@@ -853,8 +865,8 @@
 
     if (configuration_[key].type() != Json::stringValue)
     {
-      LOG_ERROR("The configuration option \"" + GetPath(key) +
-                "\" is not a string as expected");
+      ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                "\" is not a string as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -885,8 +897,8 @@
         return true;
 
       default:
-        LOG_ERROR("The configuration option \"" + GetPath(key) +
-                  "\" is not an integer as expected");
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                  "\" is not an integer as expected");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -904,8 +916,8 @@
 
     if (tmp < 0)
     {
-      LOG_ERROR("The configuration option \"" + GetPath(key) +
-                "\" is not a positive integer as expected");
+      ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                "\" is not a positive integer as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -929,8 +941,8 @@
 
     if (configuration_[key].type() != Json::booleanValue)
     {
-      LOG_ERROR("The configuration option \"" + GetPath(key) +
-                "\" is not a Boolean as expected");
+      ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                "\" is not a Boolean as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -965,8 +977,8 @@
         return true;
 
       default:
-        LOG_ERROR("The configuration option \"" + GetPath(key) +
-                  "\" is not an integer as expected");
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                  "\" is not an integer as expected");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -1025,8 +1037,8 @@
         break;
     }
 
-    LOG_ERROR("The configuration option \"" + GetPath(key) +
-              "\" is not a list of strings as expected");
+    ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                              "\" is not a list of strings as expected");
 
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
@@ -1146,8 +1158,8 @@
 
     if (configuration_[key].type() != Json::objectValue)
     {
-      LOG_ERROR("The configuration option \"" + GetPath(key) +
-                "\" is not an object as expected");
+      ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                "\" is not an object as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -1164,8 +1176,8 @@
       }
       else
       {
-        LOG_ERROR("The configuration option \"" + GetPath(key) +
-                  "\" is not a dictionary mapping strings to strings");
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                  "\" is not a dictionary mapping strings to strings");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
       }
@@ -1187,7 +1199,7 @@
   {
     if (image_ == NULL)
     {
-      LOG_ERROR("Trying to access a NULL image");
+      ORTHANC_PLUGINS_LOG_ERROR("Trying to access a NULL image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -1213,7 +1225,7 @@
 
     if (image_ == NULL)
     {
-      LOG_ERROR("Cannot create an image");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot create an image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
@@ -1230,7 +1242,7 @@
 
     if (image_ == NULL)
     {
-      LOG_ERROR("Cannot create an image accessor");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot create an image accessor");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
@@ -1244,7 +1256,7 @@
 
     if (image_ == NULL)
     {
-      LOG_ERROR("Cannot uncompress a PNG image");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a PNG image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -1257,7 +1269,7 @@
     image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
     if (image_ == NULL)
     {
-      LOG_ERROR("Cannot uncompress a JPEG image");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a JPEG image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -1271,7 +1283,7 @@
     image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
     if (image_ == NULL)
     {
-      LOG_ERROR("Cannot uncompress a DICOM image");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot uncompress a DICOM image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -1685,13 +1697,13 @@
                                    unsigned int minor,
                                    unsigned int revision)
   {
-    LOG_ERROR("Your version of the Orthanc core (" +
-              std::string(GetGlobalContext()->orthancVersion) +
-              ") is too old to run this plugin (version " +
-              boost::lexical_cast<std::string>(major) + "." +
-              boost::lexical_cast<std::string>(minor) + "." +
-              boost::lexical_cast<std::string>(revision) +
-              " is required)");
+    ORTHANC_PLUGINS_LOG_ERROR("Your version of the Orthanc core (" +
+                              std::string(GetGlobalContext()->orthancVersion) +
+                              ") is too old to run this plugin (version " +
+                              boost::lexical_cast<std::string>(major) + "." +
+                              boost::lexical_cast<std::string>(minor) + "." +
+                              boost::lexical_cast<std::string>(revision) +
+                              " is required)");
   }
 
   bool CheckMinimalVersion(const char* version,
@@ -1715,9 +1727,9 @@
     int aa, bb, cc = 0;
     if ((ORTHANC_SCANF(version, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 &&
          ORTHANC_SCANF(version, "%4d.%4d", &aa, &bb) != 2) ||
-      aa < 0 ||
-      bb < 0 ||
-      cc < 0)
+        aa < 0 ||
+        bb < 0 ||
+        cc < 0)
     {
       return false;
     }
@@ -1771,7 +1783,7 @@
   {
     if (!HasGlobalContext())
     {
-      LOG_ERROR("Bad Orthanc context in the plugin");
+      ORTHANC_PLUGINS_LOG_ERROR("Bad Orthanc context in the plugin");
       return false;
     }
 
@@ -1808,7 +1820,7 @@
     }
     else
     {
-      LOG_ERROR("Inexistent peer: " + name);
+      ORTHANC_PLUGINS_LOG_ERROR("Inexistent peer: " + name);
       ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
     }
   }
@@ -2092,7 +2104,7 @@
 
     if (body.size() > 0xffffffffu)
     {
-      LOG_ERROR("Cannot handle body size > 4GB");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -2129,7 +2141,7 @@
 
     if (body.size() > 0xffffffffu)
     {
-      LOG_ERROR("Cannot handle body size > 4GB");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -2495,7 +2507,7 @@
 
     if (id == NULL)
     {
-      LOG_ERROR("Plugin cannot submit job");
+      ORTHANC_PLUGINS_LOG_ERROR("Plugin cannot submit job");
       OrthancPluginFreeJob(GetGlobalContext(), orthanc);
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
@@ -2564,7 +2576,7 @@
           throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
                                           status["ErrorDescription"].asString());
 #else
-          LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString());
+          ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString());
           ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
 #endif
         }
@@ -2589,7 +2601,7 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
                                       "Expected a JSON object in the body");
 #else
-      LOG_ERROR("Expected a JSON object in the body");
+      ORTHANC_PLUGINS_LOG_ERROR("Expected a JSON object in the body");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
 #endif
     }
@@ -2605,7 +2617,7 @@
                                         "Option \"" + std::string(KEY_SYNCHRONOUS) +
                                         "\" must be Boolean");
 #else
-        LOG_ERROR("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean");
+        ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_SYNCHRONOUS) + "\" must be Boolean");
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
 #endif
       }
@@ -2624,7 +2636,7 @@
                                         "Option \"" + std::string(KEY_ASYNCHRONOUS) +
                                         "\" must be Boolean");
 #else
-        LOG_ERROR("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean");
+        ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_ASYNCHRONOUS) + "\" must be Boolean");
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
 #endif
       }
@@ -2645,7 +2657,7 @@
                                         "Option \"" + std::string(KEY_PRIORITY) +
                                         "\" must be an integer");
 #else
-        LOG_ERROR("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer");
+        ORTHANC_PLUGINS_LOG_ERROR("Option \"" + std::string(KEY_PRIORITY) + "\" must be an integer");
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
 #endif
       }
@@ -3166,7 +3178,7 @@
 
     if (body.size() > 0xffffffffu)
     {
-      LOG_ERROR("Cannot handle body size > 4GB");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -3311,7 +3323,7 @@
     
     if (!ReadJson(answerBody, body))
     {
-      LOG_ERROR("Cannot convert HTTP answer body to JSON");
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot convert HTTP answer body to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Fri Apr 26 17:43:22 2024 +0200
@@ -127,6 +127,44 @@
 #  define HAS_ORTHANC_PLUGIN_WEBDAV  0
 #endif
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4)
+#  define HAS_ORTHANC_PLUGIN_LOG_MESSAGE  1
+#else
+#  define HAS_ORTHANC_PLUGIN_LOG_MESSAGE  0
+#endif
+
+
+// Macro to tag a function as having been deprecated
+#if (__cplusplus >= 201402L)  // C++14
+#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) [[deprecated]] f
+#elif defined(__GNUC__) || defined(__clang__)
+#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) f __attribute__((deprecated))
+#elif defined(_MSC_VER)
+#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) __declspec(deprecated) f
+#else
+#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED
+#endif
+
+
+#if !defined(__ORTHANC_FILE__)
+#  if defined(_MSC_VER)
+#    pragma message("Warning: Macro __ORTHANC_FILE__ is not defined, this will leak the full path of the source files in the binaries")
+#  else
+#    warning Warning: Macro __ORTHANC_FILE__ is not defined, this will leak the full path of the source files in the binaries
+#  endif
+#  define __ORTHANC_FILE__ __FILE__
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#  define ORTHANC_PLUGINS_LOG_ERROR(msg)   ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Error, __ORTHANC_FILE__, __LINE__, msg)
+#  define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Warning, __ORTHANC_FILE__, __LINE__, msg)
+#  define ORTHANC_PLUGINS_LOG_INFO(msg)    ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Info, __ORTHANC_FILE__, __LINE__, msg)
+#else
+#  define ORTHANC_PLUGINS_LOG_ERROR(msg)   ::OrthancPlugins::LogError(msg)
+#  define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogWarning(msg)
+#  define ORTHANC_PLUGINS_LOG_INFO(msg)    ::OrthancPlugins::LogInfo(msg)
+#endif
 
 
 namespace OrthancPlugins
@@ -137,9 +175,8 @@
 
   void SetGlobalContext(OrthancPluginContext* context);
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4)
-  void SetGlobalContext(OrthancPluginContext* context, const char* pluginName);
-#endif
+  void SetGlobalContext(OrthancPluginContext* context,
+                        const char* pluginName);
 
   void ResetGlobalContext();
 
@@ -641,11 +678,33 @@
   const char* AutodetectMimeType(const std::string& path);
 #endif
 
-  void LogError(const std::string& message);   // From Orthanc 1.12.4, use LOG(ERROR) to display the plugin name, file and line (First set a plugin name in Orthanc::Logging::InitializePluginContext)
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+  void LogMessage(OrthancPluginLogLevel level,
+                  const char* file,
+                  uint32_t line,
+                  const std::string& message);
+#endif
+
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+  // Use macro ORTHANC_PLUGINS_LOG_ERROR() instead
+  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogError(const std::string& message));
+#else
+  void LogError(const std::string& message);
+#endif
 
-  void LogWarning(const std::string& message); // From Orthanc 1.12.4, use LOG(WARNING) to display the plugin name, file and line (First set a plugin name in Orthanc::Logging::InitializePluginContext)
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+  // Use macro ORTHANC_PLUGINS_LOG_WARNING() instead
+  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogWarning(const std::string& message));
+#else
+  void LogWarning(const std::string& message);
+#endif
 
-  void LogInfo(const std::string& message);    // From Orthanc 1.12.4, use LOG(INFO) to display the plugin name, file and line (First set a plugin name in Orthanc::Logging::InitializePluginContext)
+#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+  // Use macro ORTHANC_PLUGINS_LOG_INFO() instead
+  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogInfo(const std::string& message));
+#else
+  void LogInfo(const std::string& message);
+#endif
 
   void ReportMinimalOrthancVersion(unsigned int major,
                                    unsigned int minor,
--- a/OrthancServer/Plugins/Samples/Housekeeper/Plugin.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/Housekeeper/Plugin.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -22,9 +22,8 @@
 
 #define HOUSEKEEPER_NAME "housekeeper"
 
+#include "../Common/OrthancPluginCppWrapper.h"
 #include "../../../../OrthancFramework/Sources/Compatibility.h"
-#include "../../../../OrthancFramework/Sources/Logging.h"
-#include "../Common/OrthancPluginCppWrapper.h"
 
 #include <boost/thread.hpp>
 #include <boost/algorithm/string.hpp>
@@ -92,7 +91,7 @@
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: invalid schedule: unknown 'day': " << weekday;
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: invalid schedule: unknown 'day': " + weekday);
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
 
@@ -404,12 +403,12 @@
   {
     if (triggerOnUnnecessaryDicomAsJsonFiles_)
     {
-      LOG(WARNING) << "Housekeeper: your storage might still contain some dicom-as-json files -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: your storage might still contain some dicom-as-json files -> will perform housekeeping");
       needsReconstruct = true;  // the default reconstruct removes the dicom-as-json
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: your storage might still contain some dicom-as-json files but the trigger has been disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: your storage might still contain some dicom-as-json files but the trigger has been disabled");
     }
   }
 
@@ -417,12 +416,12 @@
   {
     if (triggerOnMainDicomTagsChange_)
     {
-      LOG(WARNING) << "Housekeeper: Patient main dicom tags have changed, -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Patient main dicom tags have changed, -> will perform housekeeping");
       needsReconstruct = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: Patient main dicom tags have changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Patient main dicom tags have changed but the trigger is disabled");
     }
   }
 
@@ -430,12 +429,12 @@
   {
     if (triggerOnMainDicomTagsChange_)
     {
-      LOG(WARNING) << "Housekeeper: Study main dicom tags have changed, -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Study main dicom tags have changed, -> will perform housekeeping");
       needsReconstruct = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: Study main dicom tags have changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Study main dicom tags have changed but the trigger is disabled");
     }
   }
 
@@ -443,12 +442,12 @@
   {
     if (triggerOnMainDicomTagsChange_)
     {
-      LOG(WARNING) << "Housekeeper: Series main dicom tags have changed, -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Series main dicom tags have changed, -> will perform housekeeping");
       needsReconstruct = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: Series main dicom tags have changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Series main dicom tags have changed but the trigger is disabled");
     }
   }
 
@@ -456,12 +455,12 @@
   {
     if (triggerOnMainDicomTagsChange_)
     {
-      LOG(WARNING) << "Housekeeper: Instance main dicom tags have changed, -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Instance main dicom tags have changed, -> will perform housekeeping");
       needsReconstruct = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: Instance main dicom tags have changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: Instance main dicom tags have changed but the trigger is disabled");
     }
   }
 
@@ -471,18 +470,18 @@
     {
       if (current.storageCompressionEnabled)
       {
-        LOG(WARNING) << "Housekeeper: storage compression is now enabled -> will perform housekeeping";
+        ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: storage compression is now enabled -> will perform housekeeping");
       }
       else
       {
-        LOG(WARNING) << "Housekeeper: storage compression is now disabled -> will perform housekeeping";
+        ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: storage compression is now disabled -> will perform housekeeping");
       }
       
       needsReingest = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: storage compression has changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: storage compression has changed but the trigger is disabled");
     }
   }
 
@@ -490,13 +489,13 @@
   {
     if (triggerOnIngestTranscodingChange_)
     {
-      LOG(WARNING) << "Housekeeper: ingest transcoding has changed -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: ingest transcoding has changed -> will perform housekeeping");
       
       needsReingest = true;
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: ingest transcoding has changed but the trigger is disabled";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: ingest transcoding has changed but the trigger is disabled");
     }
   }
 
@@ -506,7 +505,7 @@
     {
       if (triggerOnDicomWebCacheChange_)
       {
-        LOG(WARNING) << "Housekeeper: DicomWEB plugin is enabled and the housekeeper has never run, you might miss series metadata cache -> will perform housekeeping";
+        ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: DicomWEB plugin is enabled and the housekeeper has never run, you might miss series metadata cache -> will perform housekeeping");
       }
       needsDicomWebCaching = triggerOnDicomWebCacheChange_;
     }
@@ -518,12 +517,12 @@
       {
         if (triggerOnDicomWebCacheChange_)
         {
-          LOG(WARNING) << "Housekeeper: DicomWEB plugin might miss series metadata cache -> will perform housekeeping";
+          ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: DicomWEB plugin might miss series metadata cache -> will perform housekeeping");
           needsDicomWebCaching = true;
         }
         else
         {
-          LOG(WARNING) << "Housekeeper: DicomWEB plugin might miss series metadata cache but the trigger has been disabled";
+          ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: DicomWEB plugin might miss series metadata cache but the trigger has been disabled");
         }
       }
     }
@@ -660,7 +659,7 @@
 
   if (!needsProcessing)
   {
-    LOG(WARNING) << "Housekeeper: everything has been processed already !";
+    ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: everything has been processed already !");
     return;
   }
 
@@ -668,11 +667,11 @@
   {
     if (force_)
     {
-      LOG(WARNING) << "Housekeeper: forcing execution -> will perform housekeeping";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: forcing execution -> will perform housekeeping");
     }
     else
     {
-      LOG(WARNING) << "Housekeeper: the DB configuration has changed since last run, will reprocess the whole DB !";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: the DB configuration has changed since last run, will reprocess the whole DB !");
     }
     
     Json::Value changes;
@@ -688,7 +687,7 @@
   }
   else
   {
-    LOG(WARNING) << "Housekeeper: the DB configuration has not changed since last run, will continue processing changes";
+    ORTHANC_PLUGINS_LOG_WARNING("Housekeeper: the DB configuration has not changed since last run, will continue processing changes");
   }
 
   bool completed = false;
@@ -710,7 +709,8 @@
       {
         boost::recursive_mutex::scoped_lock lock(pluginStatusMutex_);
     
-        LOG(INFO) << "Housekeeper: processed changes " << pluginStatus_.lastProcessedChange << " / " << pluginStatus_.lastChangeToProcess;
+        ORTHANC_PLUGINS_LOG_INFO("Housekeeper: processed changes " + boost::lexical_cast<std::string>(pluginStatus_.lastProcessedChange) +
+                                 " / " + boost::lexical_cast<std::string>(pluginStatus_.lastChangeToProcess));
         
         boost::this_thread::sleep(boost::posix_time::milliseconds(throttleDelay_ * 100));  // wait 1/10 of the delay between changes
       }
@@ -721,7 +721,7 @@
     {
       if (!loggedNotRightPeriodChangeMessage)
       {
-        LOG(INFO) << "Housekeeper: entering quiet period";
+        ORTHANC_PLUGINS_LOG_INFO("Housekeeper: entering quiet period");
         loggedNotRightPeriodChangeMessage = true;
       }
 
@@ -796,7 +796,6 @@
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
   {
     OrthancPlugins::SetGlobalContext(c, HOUSEKEEPER_NAME);
-    Orthanc::Logging::InitializePluginContext(c, HOUSEKEEPER_NAME);
 
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(c) == 0)
@@ -807,7 +806,7 @@
       return -1;
     }
 
-    LOG(WARNING) << "Housekeeper plugin is initializing";
+    ORTHANC_PLUGINS_LOG_WARNING("Housekeeper plugin is initializing");
     OrthancPluginSetDescription2(c, HOUSEKEEPER_NAME, "Optimizes your DB and storage.");
 
     OrthancPlugins::OrthancConfiguration orthancConfiguration;
@@ -891,7 +890,7 @@
       if (limitMainDicomTagsReconstructLevel_ != "Patient" && limitMainDicomTagsReconstructLevel_ != "Study"
         && limitMainDicomTagsReconstructLevel_ != "Series" && limitMainDicomTagsReconstructLevel_ != "Instance")
       {
-        LOG(ERROR) << "Housekeeper invalid value for 'LimitMainDicomTagsReconstructLevel': '" << limitMainDicomTagsReconstructLevel_ << "'";
+        ORTHANC_PLUGINS_LOG_ERROR("Housekeeper invalid value for 'LimitMainDicomTagsReconstructLevel': '" + limitMainDicomTagsReconstructLevel_ + "'");
       }
       else if (limitMainDicomTagsReconstructLevel_ == "Patient")
       {
@@ -925,7 +924,7 @@
     }
     else
     {
-      LOG(WARNING) << "Housekeeper plugin is disabled by the configuration file";
+      ORTHANC_PLUGINS_LOG_WARNING("Housekeeper plugin is disabled by the configuration file");
     }
 
     return 0;
@@ -934,7 +933,7 @@
 
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
-    LOG(WARNING) << "Housekeeper plugin is finalizing";
+    ORTHANC_PLUGINS_LOG_WARNING("Housekeeper plugin is finalizing");
   }
 
 
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/CMakeLists.txt	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/ModalityWorklists/CMakeLists.txt	Fri Apr 26 17:43:22 2024 +0200
@@ -40,6 +40,8 @@
   ${BOOST_SOURCES}
   )
 
+DefineSourceBasenameForTarget(ModalityWorklists)
+
 message("Setting the version of the plugin to ${MODALITY_WORKLISTS_VERSION}")
 add_definitions(
   -DMODALITY_WORKLISTS_VERSION="${MODALITY_WORKLISTS_VERSION}"
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -23,7 +23,6 @@
 #define MODALITY_WORKLISTS_NAME "worklists"
 
 #include "../../../../OrthancFramework/Sources/Compatibility.h"
-#include "../../../../OrthancFramework/Sources/Logging.h"
 #include "../Common/OrthancPluginCppWrapper.h"
 
 #include <boost/filesystem.hpp>
@@ -55,7 +54,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      LOG(ERROR) << "Error while adding an answer to a worklist request";
+      ORTHANC_PLUGINS_LOG_ERROR("Error while adding an answer to a worklist request");
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
     }
 
@@ -78,7 +77,8 @@
   dicom.DicomToJson(json, OrthancPluginDicomToJsonFormat_Short,
                     static_cast<OrthancPluginDicomToJsonFlags>(0), 0);
 
-  LOG(INFO) << "Received worklist query from remote modality " << issuerAet << ":\n" + json.toStyledString();
+  ORTHANC_PLUGINS_LOG_INFO("Received worklist query from remote modality " +
+                           std::string(issuerAet) + ":\n" + json.toStyledString());
 
   if (!filterIssuerAet_)
   {
@@ -185,19 +185,19 @@
                 return OrthancPluginErrorCode_Success;
               }
               
-              LOG(INFO) << "Worklist matched: " << it->path().string();
+              ORTHANC_PLUGINS_LOG_INFO("Worklist matched: " + it->path().string());
               matchedWorklistCount++;
             }
           }
         }
       }
 
-      LOG(INFO) << "Worklist C-Find: parsed " << parsedFilesCount
-                << " files, found " << matchedWorklistCount << " match(es)";
+      ORTHANC_PLUGINS_LOG_INFO("Worklist C-Find: parsed " + boost::lexical_cast<std::string>(parsedFilesCount) +
+                               " files, found " + boost::lexical_cast<std::string>(matchedWorklistCount) + " match(es)");
     }
     catch (fs::filesystem_error&)
     {
-      LOG(ERROR) << "Inexistent folder while scanning for worklists: " << source.string();
+      ORTHANC_PLUGINS_LOG_ERROR("Inexistent folder while scanning for worklists: " + source.string());
       return OrthancPluginErrorCode_DirectoryExpected;
     }
 
@@ -214,7 +214,6 @@
 {
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
   {
-    Orthanc::Logging::InitializePluginContext(c, MODALITY_WORKLISTS_NAME);
     OrthancPlugins::SetGlobalContext(c, MODALITY_WORKLISTS_NAME);
 
     /* Check the version of the Orthanc core */
@@ -226,7 +225,7 @@
       return -1;
     }
 
-    LOG(WARNING) << "Sample worklist plugin is initializing";
+    ORTHANC_PLUGINS_LOG_WARNING("Sample worklist plugin is initializing");
     OrthancPluginSetDescription2(c, MODALITY_WORKLISTS_NAME, "Serve DICOM modality worklists from a folder with Orthanc.");
 
     OrthancPlugins::OrthancConfiguration configuration;
@@ -239,12 +238,12 @@
     {
       if (worklists.LookupStringValue(folder_, "Database"))
       {
-        LOG(WARNING) << "The database of worklists will be read from folder: " << folder_;
+        ORTHANC_PLUGINS_LOG_WARNING("The database of worklists will be read from folder: " + folder_);
         OrthancPluginRegisterWorklistCallback(OrthancPlugins::GetGlobalContext(), Callback);
       }
       else
       {
-        LOG(ERROR) << "The configuration option \"Worklists.Database\" must contain a path";
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"Worklists.Database\" must contain a path");
         return -1;
       }
 
@@ -253,7 +252,7 @@
     }
     else
     {
-      LOG(WARNING) << "Worklist server is disabled by the configuration file";
+      ORTHANC_PLUGINS_LOG_WARNING("Worklist server is disabled by the configuration file");
     }
 
     return 0;
@@ -262,7 +261,7 @@
 
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
-    LOG(WARNING) << "Sample worklist plugin is finalizing";
+    ORTHANC_PLUGINS_LOG_WARNING("Sample worklist plugin is finalizing");
   }
 
 
--- a/OrthancServer/Plugins/Samples/Sanitizer/Plugin.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/Sanitizer/Plugin.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -70,7 +70,7 @@
       return -1;
     }
     
-    OrthancPlugins::LogWarning("Sanitizer plugin is initializing");
+    ORTHANC_PLUGINS_LOG_WARNING("Sanitizer plugin is initializing");
     OrthancPlugins::SetDescription(ORTHANC_PLUGIN_NAME, "Sample plugin to sanitize incoming DICOM instances.");
 
     OrthancPluginRegisterReceivedInstanceCallback(c, ReceivedInstanceCallback);
@@ -81,7 +81,7 @@
 
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
-    OrthancPlugins::LogWarning("Sanitizer plugin is finalizing");
+    ORTHANC_PLUGINS_LOG_WARNING("Sanitizer plugin is finalizing");
     Orthanc::FinalizeFramework();
   }
 
--- a/OrthancServer/Plugins/Samples/ServeFolders/CMakeLists.txt	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/ServeFolders/CMakeLists.txt	Fri Apr 26 17:43:22 2024 +0200
@@ -40,6 +40,8 @@
   ${BOOST_SOURCES}
   )
 
+DefineSourceBasenameForTarget(ServeFolders)
+
 add_definitions(-DHAS_ORTHANC_EXCEPTION=0)
 
 message("Setting the version of the plugin to ${SERVE_FOLDERS_VERSION}")
--- a/OrthancServer/Plugins/Samples/ServeFolders/Plugin.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/ServeFolders/Plugin.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -23,7 +23,6 @@
 #define SERVE_FOLDERS_NAME "serve-folders"
 
 #include "../Common/OrthancPluginCppWrapper.h"
-#include "../../../OrthancFramework/Sources/Logging.h"
 
 #include <json/value.h>
 #include <boost/filesystem.hpp>
@@ -95,7 +94,7 @@
   }
   else
   {
-    LOG(WARNING) << "ServeFolders: Unknown MIME type for extension \"" << extension << "\"";
+    ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: Unknown MIME type for extension \"" + extension + "\"");
     return "application/octet-stream";
   }
 }
@@ -110,7 +109,7 @@
   std::map<std::string, std::string>::const_iterator found = folders_.find(uri);
   if (found == folders_.end())
   {
-    LOG(ERROR) << "Unknown URI in plugin server-folders: " << uri;
+    ORTHANC_PLUGINS_LOG_ERROR("Unknown URI in plugin server-folders: " + uri);
     OrthancPluginSendHttpStatusCode(OrthancPlugins::GetGlobalContext(), output, 404);
     return false;
   }
@@ -266,7 +265,7 @@
 {
   if (folders.type() != Json::objectValue)
   {
-    LOG(ERROR) << "The list of folders to be served is badly formatted (must be a JSON object)";
+    ORTHANC_PLUGINS_LOG_ERROR("The list of folders to be served is badly formatted (must be a JSON object)");
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
 
@@ -278,8 +277,8 @@
   {
     if (folders[*it].type() != Json::stringValue)
     {
-      LOG(ERROR) << "The folder to be served \"" << *it << 
-                    "\" must be associated with a string value (its mapped URI)";
+      ORTHANC_PLUGINS_LOG_ERROR("The folder to be served \"" + *it + 
+                                "\" must be associated with a string value (its mapped URI)");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
 
@@ -300,7 +299,7 @@
 
     if (baseUri.empty())
     {
-      LOG(ERROR) << "The URI of a folder to be served cannot be empty";
+      ORTHANC_PLUGINS_LOG_ERROR("The URI of a folder to be served cannot be empty");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
 
@@ -308,7 +307,7 @@
     const std::string folder = folders[*it].asString();
     if (!boost::filesystem::is_directory(folder))
     {
-      LOG(ERROR) << "Trying to serve an inexistent folder: " + folder;
+      ORTHANC_PLUGINS_LOG_ERROR("Trying to serve an inexistent folder: " + folder);
       ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentFile);
     }
 
@@ -327,7 +326,7 @@
 {
   if (extensions.type() != Json::objectValue)
   {
-    LOG(ERROR) << "The list of extensions is badly formatted (must be a JSON object)";
+    ORTHANC_PLUGINS_LOG_ERROR("The list of extensions is badly formatted (must be a JSON object)");
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
 
@@ -338,8 +337,8 @@
   {
     if (extensions[*it].type() != Json::stringValue)
     {
-      LOG(ERROR) << "The file extension \"" << *it << 
-                    "\" must be associated with a string value (its MIME type)";
+      ORTHANC_PLUGINS_LOG_ERROR("The file extension \"" + *it + 
+                                "\" must be associated with a string value (its MIME type)");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
 
@@ -357,11 +356,13 @@
 
     if (mime.empty())
     {
-      LOG(WARNING) << "ServeFolders: Removing MIME type for file extension \"." << name << "\"";
+      ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: Removing MIME type for file extension \"." +
+                                  name + "\"");
     }
     else
     {
-      LOG(WARNING) << "ServeFolders: Associating file extension \"." << name << "\" with MIME type \"" << mime << "\"";
+      ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: Associating file extension \"." + name +
+                                  "\" with MIME type \"" + mime + "\"");
     }
   }  
 }
@@ -391,13 +392,16 @@
     if (configuration.LookupBooleanValue(tmp, "AllowCache"))
     {
       allowCache_ = tmp;
-      LOG(WARNING) << "ServeFolders: Requesting the HTTP client to " << (tmp ? "enable" : "disable") << " its caching mechanism";
+      ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: Requesting the HTTP client to " +
+                                  std::string(tmp ? "enable" : "disable") +
+                                  " its caching mechanism");
     }
 
     if (configuration.LookupBooleanValue(tmp, "GenerateETag"))
     {
       generateETag_ = tmp;
-      LOG(WARNING) << "ServeFolders: The computation of an ETag for the served resources is " << (tmp ? "enabled" : "disabled");
+      ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: The computation of an ETag for the served resources is " +
+                                  std::string(tmp ? "enabled" : "disabled"));
     }
 
     OrthancPlugins::OrthancConfiguration extensions;
@@ -407,7 +411,7 @@
 
   if (folders_.empty())
   {
-    LOG(WARNING) << "ServeFolders: Empty configuration file: No additional folder will be served!";
+    ORTHANC_PLUGINS_LOG_WARNING("ServeFolders: Empty configuration file: No additional folder will be served!");
   }
 }
 
@@ -417,7 +421,6 @@
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
   {
     OrthancPlugins::SetGlobalContext(context, SERVE_FOLDERS_NAME);
-    Orthanc::Logging::InitializePluginContext(context, SERVE_FOLDERS_NAME);
 
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(context) == 0)
@@ -439,7 +442,8 @@
     }
     catch (OrthancPlugins::PluginException& e)
     {
-      LOG(ERROR) << "Error while initializing the ServeFolders plugin: " << e.What(context);
+      ORTHANC_PLUGINS_LOG_ERROR("Error while initializing the ServeFolders plugin: " +
+                                std::string(e.What(context)));
     }
 
     return 0;
--- a/OrthancServer/Plugins/Samples/StorageCommitmentScp/CMakeLists.txt	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/StorageCommitmentScp/CMakeLists.txt	Fri Apr 26 17:43:22 2024 +0200
@@ -40,6 +40,8 @@
   ${BOOST_SOURCES}
   )
 
+DefineSourceBasenameForTarget(StorageCommitmentScp)
+
 message("Setting the version of the plugin to ${PLUGIN_VERSION}")
 add_definitions(
   -DPLUGIN_VERSION="${PLUGIN_VERSION}"
--- a/OrthancServer/Plugins/Samples/WebDavFilesystem/CMakeLists.txt	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/WebDavFilesystem/CMakeLists.txt	Fri Apr 26 17:43:22 2024 +0200
@@ -40,3 +40,5 @@
   ${JSONCPP_SOURCES}
   ${BOOST_SOURCES}
   )
+
+DefineSourceBasenameForTarget(WebDavFilesystem)
--- a/OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -164,7 +164,7 @@
 
     if (content_.find(name) != content_.end())
     {
-      OrthancPlugins::LogError("Already existing: " + name);
+      ORTHANC_PLUGINS_LOG_ERROR("Already existing: " + name);
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadRequest);
     }
     else
@@ -177,7 +177,7 @@
   {
     if (content_.find(name) != content_.end())
     {
-      OrthancPlugins::LogError("Already existing: " + name);
+      ORTHANC_PLUGINS_LOG_ERROR("Already existing: " + name);
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadRequest);
     }
     else
@@ -192,7 +192,7 @@
 
     if (found == content_.end())
     {
-      OrthancPlugins::LogError("Cannot delete inexistent path: " + name);
+      ORTHANC_PLUGINS_LOG_ERROR("Cannot delete inexistent path: " + name);
       ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentItem);
     }
     else
@@ -215,7 +215,7 @@
   {
     if (path.empty())
     {
-      OrthancPlugins::LogError("Empty path");
+      ORTHANC_PLUGINS_LOG_ERROR("Empty path");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
     else
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp	Fri Apr 26 16:32:18 2024 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp	Fri Apr 26 17:43:22 2024 +0200
@@ -600,7 +600,7 @@
 
     ServerContext& context = OrthancRestApi::GetContext(call);
     bool transcode = false;
-    DicomTransferSyntax transferSyntax;
+    DicomTransferSyntax transferSyntax = DicomTransferSyntax_LittleEndianImplicit;  // Initialize variable to avoid warnings
 
     if (call.HasArgument(TRANSCODE))
     {