changeset 344:5e371cc50483

sync
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 18 Aug 2026 10:31:33 +0200
parents 47e6b454ef43
children f2ae8fe9933c
files CMakeLists.txt Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Resources/Orthanc/CMake/DownloadPackage.cmake Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Resources/Orthanc/Plugins/OrthancPluginException.h
diffstat 6 files changed, 240 insertions(+), 191 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Aug 10 10:18:23 2026 +0200
+++ b/CMakeLists.txt	Tue Aug 18 10:31:33 2026 +0200
@@ -27,7 +27,7 @@
   set(ORTHANC_FRAMEWORK_VERSION "mainline")
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg")
 else()
-  set(ORTHANC_FRAMEWORK_VERSION "1.12.9")
+  set(ORTHANC_FRAMEWORK_VERSION "1.13.0")
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web")
 endif()
 
--- a/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake	Mon Aug 10 10:18:23 2026 +0200
+++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake	Tue Aug 18 10:31:33 2026 +0200
@@ -177,6 +177,10 @@
         set(ORTHANC_FRAMEWORK_MD5 "66b5a2ee60706c4a502896083b9e1a01")
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.10")
         set(ORTHANC_FRAMEWORK_MD5 "d5e1ba442104c89a24013cb859a9d6bf")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.11")
+        set(ORTHANC_FRAMEWORK_MD5 "389b273b64b513ba8fc3233f34201cc1")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.13.0")
+        set(ORTHANC_FRAMEWORK_MD5 "cc95d3e509612b541e10e91c831fbfe3")
 
       # Below this point are development snapshots that were used to
       # release some plugin, before an official release of the Orthanc
@@ -236,6 +240,11 @@
         # for HttpClient that returns the answer body in case of HTTP error
         set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
         set(ORTHANC_FRAMEWORK_MD5 "665f8aa70d7c5091bc20da37cf664910")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "004b351797fe")
+        # PixelsMasker 0.1.2 (framework post-1.12.11)
+        # for ScopedThreadNameSetter
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "f078ca997217b831ab3f6741f08a8c07")
       endif()
     endif()
   endif()
--- a/Resources/Orthanc/CMake/DownloadPackage.cmake	Mon Aug 10 10:18:23 2026 +0200
+++ b/Resources/Orthanc/CMake/DownloadPackage.cmake	Tue Aug 18 10:31:33 2026 +0200
@@ -92,7 +92,7 @@
 
   set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}")
   if (NOT EXISTS "${TMP_PATH}")
-    message("Downloading ${Url}")
+    message("Downloading ${Url} since the file was not found in ${TMP_PATH}")
 
     # This fixes issue 6: "I think cmake shouldn't download the
     # packages which are not in the system, it should stop and let
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Mon Aug 10 10:18:23 2026 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Tue Aug 18 10:31:33 2026 +0200
@@ -28,7 +28,7 @@
 #include <boost/move/unique_ptr.hpp>
 #include <boost/thread.hpp>
 #include <boost/algorithm/string/join.hpp>
-
+#include <limits>
 
 #include <json/reader.h>
 #include <json/version.h>
@@ -61,6 +61,13 @@
 #endif
 
 
+#ifdef _MSC_VER
+#  define ORTHANC_SCANF sscanf_s
+#else
+#  define ORTHANC_SCANF sscanf
+#endif
+
+
 namespace OrthancPlugins
 {
   static OrthancPluginContext* globalContext_ = NULL;
@@ -117,7 +124,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_LOG_MESSAGE == 1
   void LogMessage(OrthancPluginLogLevel level,
                   const char* file,
                   uint32_t line,
@@ -125,7 +132,7 @@
   {
     if (HasGlobalContext())
     {
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_LOG_MESSAGE == 1
       const char* pluginName = (pluginName_.empty() ? NULL : pluginName_.c_str());
       OrthancPluginLogMessage(GetGlobalContext(), message.c_str(), pluginName, file, line, OrthancPluginLogCategory_Generic, level);
 #else
@@ -184,7 +191,7 @@
       // Prevent using garbage information
       buffer_.data = NULL;
       buffer_.size = 0;
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 
@@ -209,7 +216,7 @@
     }
     else
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 
@@ -227,7 +234,7 @@
     {
       Clear();
     }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) // NOLINT(bugprone-empty-catch)
     {
       // Don't throw exceptions in destructors
     }
@@ -264,7 +271,7 @@
     }
     else
     {
-      if (size > 0)
+      if (buffer != NULL && size > 0)
       {
         memcpy(buffer_.data, buffer, size);
       }
@@ -365,7 +372,7 @@
   }
 
 
-#if (HAS_ORTHANC_PLUGIN_PEERS == 1) || (HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1) || (HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1)
+#if (HAS_ORTHANC_PLUGINS_PEERS == 1) || (HAS_ORTHANC_PLUGINS_HTTP_CLIENT == 1) || (HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1)
   static void DecodeHttpHeaders(HttpHeaders& target,
                                 const MemoryBuffer& source)
   {
@@ -465,7 +472,7 @@
     }
   }
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
 
   bool MemoryBuffer::RestApiPost(const std::string& uri,
                                  const void* body,
@@ -675,7 +682,7 @@
     {
       Clear();
     }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) // NOLINT(bugprone-empty-catch)
     {
       // Don't throw exceptions in destructors
     }
@@ -839,7 +846,7 @@
     }
     else
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(error);
     }
   }
 
@@ -977,7 +984,15 @@
         return true;
 
       case Json::uintValue:
-        target = configuration_[key].asUInt();
+        if (configuration_[key].asUInt() > static_cast<unsigned int>(std::numeric_limits<int>::max()))
+        {
+          ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"" + GetPath(key) +
+                                    "\" is too large to fit in an integer");
+
+          ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);          
+        }
+
+        target = static_cast<int>(configuration_[key].asUInt());
         return true;
 
       default:
@@ -1338,7 +1353,7 @@
     {
       Clear();
     }
-    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&) // NOLINT(bugprone-empty-catch)
     {
       // Don't throw exceptions in destructors
     }
@@ -1473,7 +1488,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
+#if HAS_ORTHANC_PLUGINS_FIND_MATCHER == 1
   FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
     matcher_(NULL),
     worklist_(worklist)
@@ -1542,18 +1557,18 @@
     }
   }
 
-#endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */
+#endif /* HAS_ORTHANC_PLUGINS_FIND_MATCHER == 1 */
 
   static void CheckAnswerSizeIsLessThan4GB(const std::string& answer)
   {
     if (answer.size() > static_cast<size_t>(std::numeric_limits<uint32_t>::max()))
     {
-  #if HAS_ORTHANC_EXCEPTION == 1
+#if HAS_ORTHANC_EXCEPTION == 1
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "Cannot send HTTP response larger than 4GB");
-  #else
+#else
       ORTHANC_PLUGINS_LOG_ERROR("Cannot send HTTP response larger than 4GB");
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);          
-  #endif
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+#endif
     }
   }
 
@@ -1726,7 +1741,7 @@
     }
   }
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   bool RestApiPost(Json::Value& result,
                    const std::string& uri,
                    const Json::Value& body,
@@ -1821,7 +1836,7 @@
     }
     else
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(error);
     }
   }
 
@@ -1850,12 +1865,6 @@
       return true;
     }
 
-#ifdef _MSC_VER
-#define ORTHANC_SCANF sscanf_s
-#else
-#define ORTHANC_SCANF sscanf
-#endif
-
     // Parse the version
     int aa, bb, cc = 0;
     if ((ORTHANC_SCANF(version, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 &&
@@ -1943,7 +1952,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
+#if HAS_ORTHANC_PLUGINS_PEERS == 1
   size_t OrthancPeers::GetPeerIndex(const std::string& name) const
   {
     size_t index;
@@ -1967,7 +1976,7 @@
 
     if (peers_ == NULL)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
 
     uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
@@ -1978,7 +1987,7 @@
       if (name == NULL)
       {
         OrthancPluginFreePeers(GetGlobalContext(), peers_);
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
       }
 
       index_[name] = i;
@@ -2016,14 +2025,14 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
     else
     {
       const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
       if (s == NULL)
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
       }
       else
       {
@@ -2037,14 +2046,14 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
     else
     {
       const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
       if (s == NULL)
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
       }
       else
       {
@@ -2066,7 +2075,7 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
     else
     {
@@ -2099,7 +2108,7 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
 
     OrthancPlugins::MemoryBuffer answer;
@@ -2297,7 +2306,7 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
 
     if (body.size() > 0xffffffffu)
@@ -2337,7 +2346,7 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
 
     if (body.size() > 0xffffffffu)
@@ -2383,7 +2392,7 @@
   {
     if (index >= index_.size())
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
 
     OrthancPlugins::MemoryBuffer answer;
@@ -2424,7 +2433,7 @@
    ** JOBS
    ******************************************************************/
 
-#if HAS_ORTHANC_PLUGIN_JOB == 1
+#if HAS_ORTHANC_PLUGINS_JOB == 1
   void OrthancJob::CallbackFinalize(void* job)
   {
     if (job != NULL)
@@ -2622,7 +2631,7 @@
 
     if (content.type() != Json::objectValue)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
     }
     else
     {
@@ -2642,7 +2651,7 @@
   {
     if (serialized.type() != Json::objectValue)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_BadFileFormat);
     }
     else
     {
@@ -2657,7 +2666,7 @@
     if (progress < 0 ||
         progress > 1)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
     }
 
     progress_ = progress;
@@ -2677,7 +2686,7 @@
   {
     if (job == NULL)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
     }
 
     OrthancPluginJob* orthanc =
@@ -2692,7 +2701,7 @@
 
     if (orthanc == NULL)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
     else
     {
@@ -2706,7 +2715,7 @@
   {
     if (job == NULL)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
     }
 
     OrthancPluginJob* orthanc = Create(job);
@@ -2717,7 +2726,7 @@
     {
       ORTHANC_PLUGINS_LOG_ERROR("Plugin cannot submit job");
       OrthancPluginFreeJob(GetGlobalContext(), orthanc);
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
     else
     {
@@ -2745,7 +2754,7 @@
           !status.isMember("State") ||
           status["State"].type() != Json::stringValue)
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InexistentItem);        
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_InexistentItem);
       }
 
       const std::string state = status["State"].asString();
@@ -2774,30 +2783,30 @@
         if (!status.isMember("ErrorCode") ||
             status["ErrorCode"].type() != Json::intValue)
         {
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
+          ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_InternalError);
         }
         else
         {
           if (!status.isMember("ErrorDescription") ||
               status["ErrorDescription"].type() != Json::stringValue)
           {
-            ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());
+            ORTHANC_PLUGINS_THROW_ERROR_CODE(status["ErrorCode"].asInt());
           }
           else
           {
-  #if HAS_ORTHANC_EXCEPTION == 1
+#if HAS_ORTHANC_EXCEPTION == 1
             throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
                                             status["ErrorDescription"].asString());
-  #else
+#else
             ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString());
-            ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
-  #endif
+            ORTHANC_PLUGINS_THROW_ERROR_CODE(status["ErrorCode"].asInt());
+#endif
           }
         }
       }
       else
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(OrthancPluginErrorCode_InternalError);
       }
     }
   }
@@ -2914,7 +2923,7 @@
    ** METRICS
    ******************************************************************/
 
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
+#if HAS_ORTHANC_PLUGINS_METRICS == 1
   MetricsTimer::MetricsTimer(const char* name) :
     name_(name)
   {
@@ -2937,7 +2946,7 @@
    ** HTTP CLIENT
    ******************************************************************/
 
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_HTTP_CLIENT == 1
   class HttpClient::RequestBodyWrapper : public boost::noncopyable
   {
   private:
@@ -3001,7 +3010,7 @@
   };
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
   static OrthancPluginErrorCode AnswerAddHeaderCallback(void* answer,
                                                         const char* key,
                                                         const char* value)
@@ -3025,7 +3034,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
   static OrthancPluginErrorCode AnswerAddChunkCallback(void* answer,
                                                        const void* data,
                                                        uint32_t size)
@@ -3289,7 +3298,7 @@
     };
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
     class MemoryAnswer : public HttpClient::IAnswer
     {
     private:
@@ -3323,7 +3332,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
   void HttpClient::ExecuteWithStream(uint16_t& httpStatus,
                                      IAnswer& answer,
                                      IRequestBody& body) const
@@ -3379,7 +3388,7 @@
 
     if (error != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(error);
     }
   }
 #endif    
@@ -3421,7 +3430,7 @@
 
     if (error != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(error);
     }
 
     DecodeHttpHeaders(answerHeaders, answerHeadersBuffer);
@@ -3431,7 +3440,7 @@
 
   void HttpClient::Execute(IAnswer& answer)
   {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
     if (allowChunkedTransfers_)
     {
       if (chunkedBody_ != NULL)
@@ -3472,7 +3481,7 @@
   void HttpClient::Execute(HttpHeaders& answerHeaders /* out */,
                            std::string& answerBody /* out */)
   {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
     if (allowChunkedTransfers_)
     {
       MemoryAnswer answer;
@@ -3530,7 +3539,7 @@
     Execute(answerHeaders, body);
   }
 
-#endif  /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */
+#endif  /* HAS_ORTHANC_PLUGINS_HTTP_CLIENT == 1 */
 
 
 
@@ -3555,7 +3564,7 @@
     }
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_SERVER == 1
 
     OrthancPluginErrorCode ChunkedRequestReaderAddChunk(
       OrthancPluginServerChunkedRequestReader* reader,
@@ -3750,7 +3759,7 @@
       }
       catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
       {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
+#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGINS_EXCEPTION_DETAILS == 1
         if (HasGlobalContext() &&
             e.HasDetails())
         {
@@ -3777,7 +3786,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
+#if HAS_ORTHANC_PLUGINS_STORAGE_COMMITMENT_SCP == 1
   OrthancPluginErrorCode IStorageCommitmentScpHandler::Lookup(
     OrthancPluginStorageCommitmentFailureReason* target,
     void* rawHandler,
@@ -3805,7 +3814,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
+#if HAS_ORTHANC_PLUGINS_STORAGE_COMMITMENT_SCP == 1
   void IStorageCommitmentScpHandler::Destructor(void* rawHandler)
   {
     assert(rawHandler != NULL);
@@ -3929,7 +3938,7 @@
     }
     else
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
@@ -3966,7 +3975,7 @@
     }
     else
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
@@ -4015,7 +4024,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static std::vector<std::string> WebDavConvertPath(uint32_t pathSize,
                                                     const char* const*  pathItems)
   {
@@ -4031,7 +4040,7 @@
 #endif
   
     
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavIsExistingFolder(uint8_t*            isExisting,
                                                        uint32_t            pathSize,
                                                        const char* const*  pathItems,
@@ -4056,7 +4065,7 @@
 #endif
 
   
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavListFolder(uint8_t*                        isExisting,
                                                  OrthancPluginWebDavCollection*  collection,
                                                  OrthancPluginWebDavAddFile      addFile,
@@ -4120,7 +4129,7 @@
 #endif    
 
 
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavRetrieveFile(OrthancPluginWebDavCollection*   collection,
                                                    OrthancPluginWebDavRetrieveFile  retrieveFile,
                                                    uint32_t                         pathSize,
@@ -4156,7 +4165,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavStoreFileCallback(uint8_t*            isReadOnly, /* out */
                                                         uint32_t            pathSize,
                                                         const char* const*  pathItems,
@@ -4189,7 +4198,7 @@
 #endif
 
   
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavCreateFolderCallback(uint8_t*            isReadOnly, /* out */
                                                            uint32_t            pathSize,
                                                            const char* const*  pathItems,
@@ -4214,7 +4223,7 @@
 #endif
   
   
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   static OrthancPluginErrorCode WebDavDeleteItemCallback(uint8_t*            isReadOnly, /* out */
                                                          uint32_t            pathSize,
                                                          const char* const*  pathItems,
@@ -4239,7 +4248,7 @@
 #endif
 
   
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   void IWebDavCollection::Register(const std::string& uri,
                                    IWebDavCollection& collection)
   {
@@ -4249,7 +4258,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
@@ -4339,7 +4348,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   RestApiClient::RestApiClient() :
     method_(OrthancPluginHttpMethod_Get),
     path_("/"),
@@ -4373,7 +4382,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   void RestApiClient::AddRequestHeader(const std::string& key,
                                        const std::string& value)
   {
@@ -4389,7 +4398,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   void RestApiClient::SetRequestHeader(const std::string& key,
                                        const std::string& value)
   {
@@ -4398,7 +4407,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   bool RestApiClient::Execute()
   {
     if (requestBody_.size() > 0xffffffffu)
@@ -4440,7 +4449,7 @@
       }
       else
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+        ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
       }
     }
   }
@@ -4481,7 +4490,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   uint16_t RestApiClient::GetHttpStatus() const
   {
     if (httpStatus_ == 0)
@@ -4496,7 +4505,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   bool RestApiClient::LookupAnswerHeader(std::string& value,
                                          const std::string& key) const
   {
@@ -4521,7 +4530,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   const std::string& RestApiClient::GetAnswerBody() const
   {
     if (httpStatus_ == 0)
@@ -4536,7 +4545,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   KeyValueStore::Iterator::Iterator(OrthancPluginKeysValuesIterator  *iterator) :
     iterator_(iterator)
   {
@@ -4548,7 +4557,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   KeyValueStore::Iterator::~Iterator()
   {
     OrthancPluginFreeKeysValuesIterator(OrthancPlugins::GetGlobalContext(), iterator_);
@@ -4556,7 +4565,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   bool KeyValueStore::Iterator::Next()
   {
     uint8_t done;
@@ -4564,7 +4573,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else
     {
@@ -4574,7 +4583,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   std::string KeyValueStore::Iterator::GetKey() const
   {
     const char* s = OrthancPluginKeysValuesIteratorGetKey(OrthancPlugins::GetGlobalContext(), iterator_);
@@ -4590,7 +4599,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   void KeyValueStore::Iterator::GetValue(std::string& value) const
   {
     OrthancPlugins::MemoryBuffer valueBuffer;
@@ -4598,7 +4607,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else
     {
@@ -4608,7 +4617,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   void KeyValueStore::Store(const std::string& key,
                             const void* value,
                             size_t valueSize)
@@ -4622,13 +4631,13 @@
                                                              key.c_str(), value, static_cast<uint32_t>(valueSize));
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   bool KeyValueStore::GetValue(std::string& value,
                                const std::string& key)
   {
@@ -4639,7 +4648,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else if (found)
     {
@@ -4654,7 +4663,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   void KeyValueStore::DeleteKey(const std::string& key)
   {
     OrthancPluginErrorCode code = OrthancPluginDeleteKeyValue(OrthancPlugins::GetGlobalContext(),
@@ -4662,13 +4671,13 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   KeyValueStore::Iterator* KeyValueStore::CreateIterator()
   {
     return new Iterator(OrthancPluginCreateKeysValuesIterator(OrthancPlugins::GetGlobalContext(), storeId_.c_str()));
@@ -4676,7 +4685,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+#if HAS_ORTHANC_PLUGINS_QUEUES == 1
   void Queue::Enqueue(const void* value,
                       size_t valueSize)
   {
@@ -4690,13 +4699,13 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
   }
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+#if HAS_ORTHANC_PLUGINS_QUEUES == 1
   bool Queue::DequeueInternal(std::string& value,
                               OrthancPluginQueueOrigin origin)
   {
@@ -4711,7 +4720,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else if (found)
     {
@@ -4726,7 +4735,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+#if HAS_ORTHANC_PLUGINS_QUEUES == 1
   uint64_t Queue::GetSize()
   {
     uint64_t size = 0;
@@ -4734,7 +4743,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else
     {
@@ -4744,7 +4753,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout)
   {
     uint8_t found = false;
@@ -4755,7 +4764,7 @@
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+      ORTHANC_PLUGINS_THROW_ERROR_CODE(code);
     }
     else if (found)
     {
@@ -4770,7 +4779,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
   {
     return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Back, releaseTimeout);
@@ -4778,7 +4787,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
   {
     return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Front, releaseTimeout);
@@ -4786,7 +4795,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
   void Queue::Acknowledge(uint64_t valueId)
   {
     OrthancPluginAcknowledgeQueueValue(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), valueId);
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Mon Aug 10 10:18:23 2026 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Tue Aug 18 10:31:33 2026 +0200
@@ -27,7 +27,6 @@
 
 #include <orthanc/OrthancCPlugin.h>
 #include <boost/noncopyable.hpp>
-#include <boost/lexical_cast.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <json/value.h>
@@ -67,98 +66,98 @@
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0)
 // The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  1
+#  define HAS_ORTHANC_PLUGINS_FIND_MATCHER  1
 #else
-#  define HAS_ORTHANC_PLUGIN_FIND_MATCHER  0
+#  define HAS_ORTHANC_PLUGINS_FIND_MATCHER  0
 #endif
 
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 4, 2)
-#  define HAS_ORTHANC_PLUGIN_PEERS  1
-#  define HAS_ORTHANC_PLUGIN_JOB    1
+#  define HAS_ORTHANC_PLUGINS_PEERS  1
+#  define HAS_ORTHANC_PLUGINS_JOB    1
 #else
-#  define HAS_ORTHANC_PLUGIN_PEERS  0
-#  define HAS_ORTHANC_PLUGIN_JOB    0
+#  define HAS_ORTHANC_PLUGINS_PEERS  0
+#  define HAS_ORTHANC_PLUGINS_JOB    0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 0)
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  1
+#  define HAS_ORTHANC_PLUGINS_EXCEPTION_DETAILS  1
 #else
-#  define HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS  0
+#  define HAS_ORTHANC_PLUGINS_EXCEPTION_DETAILS  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
-#  define HAS_ORTHANC_PLUGIN_METRICS  1
+#  define HAS_ORTHANC_PLUGINS_METRICS  1
 #else
-#  define HAS_ORTHANC_PLUGIN_METRICS  0
+#  define HAS_ORTHANC_PLUGINS_METRICS  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 1, 0)
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  1
+#  define HAS_ORTHANC_PLUGINS_HTTP_CLIENT  1
 #else
-#  define HAS_ORTHANC_PLUGIN_HTTP_CLIENT  0
+#  define HAS_ORTHANC_PLUGINS_HTTP_CLIENT  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  1
+#  define HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT  1
 #else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT  0
+#  define HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7)
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  1
+#  define HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_SERVER  1
 #else
-#  define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER  0
+#  define HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_SERVER  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 6, 0)
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  1
+#  define HAS_ORTHANC_PLUGINS_STORAGE_COMMITMENT_SCP  1
 #else
-#  define HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP  0
+#  define HAS_ORTHANC_PLUGINS_STORAGE_COMMITMENT_SCP  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2)
-#  define HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API  1
+#  define HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API  1
 #else
-#  define HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API  0
+#  define HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 10, 1)
-#  define HAS_ORTHANC_PLUGIN_WEBDAV  1
+#  define HAS_ORTHANC_PLUGINS_WEBDAV  1
 #else
-#  define HAS_ORTHANC_PLUGIN_WEBDAV  0
+#  define HAS_ORTHANC_PLUGINS_WEBDAV  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4)
-#  define HAS_ORTHANC_PLUGIN_LOG_MESSAGE  1
+#  define HAS_ORTHANC_PLUGINS_LOG_MESSAGE  1
 #else
-#  define HAS_ORTHANC_PLUGIN_LOG_MESSAGE  0
+#  define HAS_ORTHANC_PLUGINS_LOG_MESSAGE  0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 8)
-#  define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES  1
-#  define HAS_ORTHANC_PLUGIN_QUEUES            1
+#  define HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES  1
+#  define HAS_ORTHANC_PLUGINS_QUEUES            1
 #else
-#  define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES  0
-#  define HAS_ORTHANC_PLUGIN_QUEUES            0
+#  define HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES  0
+#  define HAS_ORTHANC_PLUGINS_QUEUES            0
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 10)
-#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   1
+#  define HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE   1
 #else
-#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   0
+#  define HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE   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
+#  define ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(f) [[deprecated]] f
 #elif defined(__GNUC__) || defined(__clang__)
-#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) f __attribute__((deprecated))
+#  define ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(f) f __attribute__((deprecated))
 #elif defined(_MSC_VER)
-#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) __declspec(deprecated) f
+#  define ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(f) __declspec(deprecated) f
 #else
-#  define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED
+#  define ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED
 #endif
 
 
@@ -172,7 +171,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_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)
@@ -297,7 +296,7 @@
                      const Json::Value& body,
                      bool applyPlugins);
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
     bool RestApiPost(const std::string& uri,
                      const Json::Value& body,
                      const HttpHeaders& httpHeaders,
@@ -396,7 +395,7 @@
     void ToJson(Json::Value& target) const;
   
     void ToJsonWithoutComments(Json::Value& target) const;
-};
+  };
 
 
   class OrthancConfiguration : public boost::noncopyable
@@ -535,7 +534,7 @@
   };
 
 
-#if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
+#if HAS_ORTHANC_PLUGINS_FIND_MATCHER == 1
   class FindMatcher : public boost::noncopyable
   {
   private:
@@ -622,7 +621,7 @@
                    size_t bodySize,
                    bool applyPlugins);
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   bool RestApiPost(Json::Value& result,
                    const std::string& uri,
                    const Json::Value& body,
@@ -701,30 +700,30 @@
   const char* AutodetectMimeType(const std::string& path);
 #endif
 
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_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
+#if HAS_ORTHANC_PLUGINS_LOG_MESSAGE == 1
   // Use macro ORTHANC_PLUGINS_LOG_ERROR() instead
-  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogError(const std::string& message));
+  ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(void LogError(const std::string& message));
 #else
   void LogError(const std::string& message);
 #endif
 
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_LOG_MESSAGE == 1
   // Use macro ORTHANC_PLUGINS_LOG_WARNING() instead
-  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogWarning(const std::string& message));
+  ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(void LogWarning(const std::string& message));
 #else
   void LogWarning(const std::string& message);
 #endif
 
-#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1
+#if HAS_ORTHANC_PLUGINS_LOG_MESSAGE == 1
   // Use macro ORTHANC_PLUGINS_LOG_INFO() instead
-  ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogInfo(const std::string& message));
+  ORTHANC_PLUGINS_CPP_WRAPPER_DEPRECATED(void LogInfo(const std::string& message));
 #else
   void LogInfo(const std::string& message);
 #endif
@@ -756,7 +755,7 @@
       }
       catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
       {
-#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1
+#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGINS_EXCEPTION_DETAILS == 1
         if (HasGlobalContext() &&
             e.HasDetails())
         {
@@ -799,7 +798,7 @@
   }
 
 
-#if HAS_ORTHANC_PLUGIN_PEERS == 1
+#if HAS_ORTHANC_PLUGINS_PEERS == 1
   class OrthancPeers : public boost::noncopyable
   {
   private:
@@ -944,7 +943,7 @@
 
 
 
-#if HAS_ORTHANC_PLUGIN_JOB == 1
+#if HAS_ORTHANC_PLUGINS_JOB == 1
   class OrthancJob : public boost::noncopyable
   {
   private:
@@ -1023,7 +1022,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
+#if HAS_ORTHANC_PLUGINS_METRICS == 1
   inline void SetMetricsValue(const char* name,
                               float value)
   {
@@ -1043,7 +1042,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_METRICS == 1
+#if HAS_ORTHANC_PLUGINS_METRICS == 1
   class MetricsTimer : public boost::noncopyable
   {
   private:
@@ -1058,7 +1057,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_HTTP_CLIENT == 1
   class HttpClient : public boost::noncopyable
   {
   public:
@@ -1106,7 +1105,7 @@
     IRequestBody*            chunkedBody_;
     bool                     allowChunkedTransfers_;
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_CLIENT == 1
     void ExecuteWithStream(uint16_t& httpStatus,  // out
                            IAnswer& answer,       // out
                            IRequestBody& body) const;
@@ -1236,11 +1235,11 @@
                                                    const OrthancPluginHttpRequest* request);
 
 
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_SERVER == 1
     template <ChunkedRestCallback Callback>
     static OrthancPluginErrorCode ChunkedProtect(OrthancPluginServerChunkedRequestReader** reader,
-                                                const char* url,
-                                                const OrthancPluginHttpRequest* request)
+                                                 const char* url,
+                                                 const OrthancPluginHttpRequest* request)
     {
       try
       {
@@ -1328,7 +1327,7 @@
   public:
     static void Apply(const std::string& uri)
     {
-#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1
+#if HAS_ORTHANC_PLUGINS_CHUNKED_HTTP_SERVER == 1
       OrthancPluginRegisterChunkedRestCallback(
         GetGlobalContext(), uri.c_str(),
         GetHandler == Internals::NullRestCallback         ? NULL : Internals::Protect<GetHandler>,
@@ -1348,7 +1347,7 @@
 
   
 
-#if HAS_ORTHANC_PLUGIN_STORAGE_COMMITMENT_SCP == 1
+#if HAS_ORTHANC_PLUGINS_STORAGE_COMMITMENT_SCP == 1
   class IStorageCommitmentScpHandler : public boost::noncopyable
   {
   public:
@@ -1461,15 +1460,15 @@
   };
 
 // helper method to convert Http headers from the plugin SDK to a std::map
-void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request);
+  void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request);
 
 // helper method to re-serialize the get arguments from the SDK into a string
-void SerializeGetArguments(std::string& output, const OrthancPluginHttpRequest* request);
+  void SerializeGetArguments(std::string& output, const OrthancPluginHttpRequest* request);
 
 // helper method to convert Get arguments from the plugin SDK to a std::map
-void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request);
+  void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request);
 
-#if HAS_ORTHANC_PLUGIN_WEBDAV == 1
+#if HAS_ORTHANC_PLUGINS_WEBDAV == 1
   class IWebDavCollection : public boost::noncopyable
   {
   public:
@@ -1580,7 +1579,7 @@
                              const std::string& javascript);
 
 
-#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+#if HAS_ORTHANC_PLUGINS_GENERIC_CALL_REST_API == 1
   class RestApiClient : public boost::noncopyable
   {
   private:
@@ -1680,7 +1679,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+#if HAS_ORTHANC_PLUGINS_KEY_VALUE_STORES == 1
   class KeyValueStore : public boost::noncopyable
   {
   public:
@@ -1735,7 +1734,7 @@
 #endif
 
 
-#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+#if HAS_ORTHANC_PLUGINS_QUEUES == 1
   class Queue : public boost::noncopyable
   {
   private:
@@ -1743,7 +1742,7 @@
 
     bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin);
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     bool ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout);
 #endif
 
@@ -1766,7 +1765,7 @@
       Enqueue(value.empty() ? NULL : value.c_str(), value.size());
     }
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     // Use ReserveBack() instead
     ORTHANC_PLUGIN_DEPRECATED
 #endif
@@ -1775,7 +1774,7 @@
       return DequeueInternal(value, OrthancPluginQueueOrigin_Back);
     }
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     // Use ReserveFront() instead
     ORTHANC_PLUGIN_DEPRECATED
 #endif
@@ -1786,15 +1785,15 @@
 
     uint64_t GetSize();
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     bool ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
 #endif
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     bool ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
 #endif
 
-#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+#if HAS_ORTHANC_PLUGINS_RESERVE_QUEUE_VALUE == 1
     void Acknowledge(uint64_t valueId);
 #endif
   };
--- a/Resources/Orthanc/Plugins/OrthancPluginException.h	Mon Aug 10 10:18:23 2026 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginException.h	Tue Aug 18 10:31:33 2026 +0200
@@ -41,13 +41,45 @@
 #endif
 
 
-#define ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code)                   \
+#if HAS_ORTHANC_EXCEPTION == 1 && defined(__ORTHANC_FILE__)   // the OrthancException class accepts a "details" argument -> add the file and line number
+
+#  include <boost/lexical_cast.hpp>
+
+#  define ORTHANC_PLUGINS_EXCEPTION_STRINGIFY_LINE_HELPER(line) #line
+#  define ORTHANC_PLUGINS_EXCEPTION_STRINGIFY_LINE(line) ORTHANC_PLUGINS_EXCEPTION_STRINGIFY_LINE_HELPER(line)
+#  define ORTHANC_PLUGINS_THROW_WITH_FILE_AND_LINE_INFO_HELPER(errorCode, errorCodeStr) \
+  throw ::Orthanc::OrthancException(                                    \
+    errorCode, "Plugin error code " + errorCodeStr + " triggered from " __ORTHANC_FILE__ ":" \
+    ORTHANC_PLUGINS_EXCEPTION_STRINGIFY_LINE(__LINE__))
+
+#  define ORTHANC_PLUGINS_THROW_WITH_FILE_AND_LINE_INFO(errorCode)      \
+  throw ::Orthanc::OrthancException(                                    \
+    errorCode, #errorCode " triggered from " __ORTHANC_FILE__ ":"       \
+    ORTHANC_PLUGINS_EXCEPTION_STRINGIFY_LINE(__LINE__))
+
+#  define ORTHANC_PLUGINS_THROW_ERROR_CODE(code)                        \
+  ORTHANC_PLUGINS_THROW_WITH_FILE_AND_LINE_INFO_HELPER(                 \
+    static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code),               \
+    boost::lexical_cast<std::string>(code))
+
+#  define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                         \
+  ORTHANC_PLUGINS_THROW_WITH_FILE_AND_LINE_INFO_HELPER(                 \
+    ORTHANC_PLUGINS_GET_ERROR_CODE(code),                               \
+    boost::lexical_cast<std::string>(ORTHANC_PLUGINS_GET_ERROR_CODE(code)))
+
+#else // the PluginException does not accept a "details" argument
+
+#  define ORTHANC_PLUGINS_THROW_ERROR_CODE(code)                        \
   throw ORTHANC_PLUGINS_EXCEPTION_CLASS(static_cast<ORTHANC_PLUGINS_ERROR_ENUMERATION>(code));
 
+#  define ORTHANC_PLUGINS_THROW_WITH_FILE_AND_LINE_INFO(errorCode)      \
+  ORTHANC_PLUGINS_THROW_ERROR_CODE(errorCode)
 
-#define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                           \
+#  define ORTHANC_PLUGINS_THROW_EXCEPTION(code)                         \
   throw ORTHANC_PLUGINS_EXCEPTION_CLASS(ORTHANC_PLUGINS_GET_ERROR_CODE(code));
-                                                  
+
+#endif                                                  
+
 
 #define ORTHANC_PLUGINS_CHECK_ERROR(code)                           \
   if (code != ORTHANC_PLUGINS_GET_ERROR_CODE(Success))              \