changeset 6444:31197da4a994 queues-timeout

integration mainline->queues-timeout
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 18 Nov 2025 17:50:39 +0100
parents 36aff9f84264 (current diff) f288ceb2a131 (diff)
children 68de7e892eaa
files NEWS OrthancServer/CMakeLists.txt OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h
diffstat 37 files changed, 575 insertions(+), 998 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Sat Nov 15 12:28:27 2025 +0100
+++ b/NEWS	Tue Nov 18 17:50:39 2025 +0100
@@ -53,29 +53,6 @@
   - civetweb 1.16, including patch for CVE-2025-55763
   - SQLite 3.50.4
 
-Plugins
--------
-
-* Worklists plugin:
-  - The Worklists plugin now provides a REST API to:
-    - create worklists through POST at /worklists/create
-    - list the worklists through GET at /worklists
-    - view a single worklist through GET at /worklists/{uuid}
-    - modify a worklist through PUT at /worklists/{uuid}
-    - delete a worklist through DELETE at /worklists/{uuid}
-    All details are available in the Orthanc book:
-    https://orthanc.uclouvain.be/book/plugins/worklists-plugin.html
-  - New configuration options:
-    - "SaveInOrthancDatabase" to store the worklists in the Orthanc DB (provided that you are using SQLite or PostgreSQL).
-    - "DeleteWorklistsOnStableStudy" to delete the worklist once its related study has been received and is stable.
-    - "SetStudyInstanceUidIfMissing" to add a StudyInstanceUID if the REST API request does not include one.
-    - "DeleteWorklistsDelay" to delete a worklist N hours after it has been created
-      (only available if using the "SaveInOrthancDatabase" mode).
-    - "HousekeepingInterval" to define the delay between 2 executions of the Worklist Housekeeping thread
-      that deletes the worklists when required.
-  - Note: the previous "Database" configuration has now been renamed in "Directory" to better differentiate
-    the "File" or "DB modes.
-
 Plugin SDK
 ----------
 
--- a/OrthancFramework/Resources/CMake/Compiler.cmake	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Resources/CMake/Compiler.cmake	Tue Nov 18 17:50:39 2025 +0100
@@ -246,6 +246,9 @@
   # fix this error that appears with recent compilers on MacOS: boost/mpl/aux_/integral_wrapper.hpp:73:31: error: integer value -1 is outside the valid range of values [0, 3] for this enumeration type [-Wenum-constexpr-conversion]
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-enum-constexpr-conversion")
 
+  # it seems that some recent MacOS compilers don't set these flags correctly which prevents zlib from building correctly
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64")
+
   add_definitions(
     -D_XOPEN_SOURCE=1
     )
--- a/OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake	Tue Nov 18 17:50:39 2025 +0100
@@ -215,6 +215,10 @@
         # Advanced storage 0.2.2 (framework pre-1.12.10)
         set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
         set(ORTHANC_FRAMEWORK_MD5 "bd5ba2cec329010b912209345acbdeaf")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "0ebe8cfd9bf7")
+        # Worklists plugin 0.9.0 (framework pre-1.12.10)
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "17a5ca9254e881ab89c93d052d4655cb")
       endif()
     endif()
   endif()
--- a/OrthancFramework/Resources/CMake/ZlibConfiguration.cmake	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Resources/CMake/ZlibConfiguration.cmake	Tue Nov 18 17:50:39 2025 +0100
@@ -25,8 +25,28 @@
   SET(ZLIB_URL "https://orthanc.uclouvain.be/downloads/third-party-downloads/zlib-1.3.1.tar.gz")
   SET(ZLIB_MD5 "9855b6d802d7fe5b7bd5b196a2271655")
 
+  if (IS_DIRECTORY "${ZLIB_SOURCES_DIR}")
+    set(FirstRun OFF)
+  else()
+    set(FirstRun ON)
+  endif()
+
   DownloadPackage(${ZLIB_MD5} ${ZLIB_URL} "${ZLIB_SOURCES_DIR}")
 
+  if (FirstRun)
+    # fix https://github.com/madler/zlib/issues/1044
+    execute_process(
+      COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
+      ${CMAKE_CURRENT_LIST_DIR}/../Patches/zlib-1.3.1-zconf.patch
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+      RESULT_VARIABLE Failure
+      )
+
+    if (Failure)
+      message(FATAL_ERROR "Error while patching a file")
+    endif()
+  endif()
+
   include_directories(
     ${ZLIB_SOURCES_DIR}
     )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancFramework/Resources/Patches/zlib-1.3.1-zconf.patch	Tue Nov 18 17:50:39 2025 +0100
@@ -0,0 +1,12 @@
+diff -ruN zlib-1.3.1-orig/zlib.h zlib-1.3.1/zlib.h
+--- zlib-1.3.1-orig/zlib.h	2025-11-18 10:09:54.402921485 +0100
++++ zlib-1.3.1/zlib.h	2025-11-18 10:10:33.743470112 +0100
+@@ -31,7 +31,7 @@
+ #ifndef ZLIB_H
+ #define ZLIB_H
+ 
+-#include "zconf.h"
++#include <zconf.h>
+ 
+ #ifdef __cplusplus
+ extern "C" {
--- a/OrthancFramework/Sources/Cache/MemoryCache.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/Cache/MemoryCache.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -88,9 +88,19 @@
       while (!index_.IsEmpty())
       {
         Page* element = NULL;
-        index_.RemoveOldest(element);
-        assert(element != NULL);
-        delete element;
+
+        try
+        {
+          index_.RemoveOldest(element);
+
+          assert(element != NULL);
+          delete element;
+        }
+        catch (OrthancException& e)
+        {
+          // Don't throw exceptions in destructors
+          LOG(ERROR) << "Exception in destructor: " << e.What();
+        }
       }
     }
 
--- a/OrthancFramework/Sources/Cache/MemoryObjectCache.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/Cache/MemoryObjectCache.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -26,6 +26,7 @@
 #include "MemoryObjectCache.h"
 
 #include "../Compatibility.h"
+#include "../Logging.h"
 
 namespace Orthanc
 {
@@ -96,7 +97,16 @@
 
   MemoryObjectCache::~MemoryObjectCache()
   {
-    Recycle(0);
+    try
+    {
+      Recycle(0);
+    }
+    catch (OrthancException& e)
+    {
+      // Don't throw exceptions in destructors
+      LOG(ERROR) << "Exception in destructor: " << e.What();
+    }
+
     assert(content_.IsEmpty());
   }
 
--- a/OrthancFramework/Sources/Cache/MemoryStringCache.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/Cache/MemoryStringCache.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -25,6 +25,8 @@
 #include "../PrecompiledHeaders.h"
 #include "MemoryStringCache.h"
 
+#include "../Logging.h"
+
 namespace Orthanc
 {
   class MemoryStringCache::StringValue : public ICacheable
@@ -118,7 +120,16 @@
 
   MemoryStringCache::~MemoryStringCache()
   {
-    Recycle(0);
+    try
+    {
+      Recycle(0);
+    }
+    catch (OrthancException& e)
+    {
+      // Don't throw exceptions in destructors
+      LOG(ERROR) << "Exception in destructor: " << e.What();
+    }
+
     assert(content_.IsEmpty());
   }
 
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -1696,15 +1696,20 @@
   {
     DcmDataset* dcmDataset = GetDcmtkObjectConst().getDataset();
 
-    if (!this->HasTag(DICOM_TAG_PIXEL_DATA) && !DicomImageDecoder::IsPsmctRle1(*dcmDataset))
+    if (dcmDataset == NULL)
     {
-      throw OrthancException(ErrorCode_BadRequest, "Cannot extract a frame from a DIOCM file that does not have pixel data.");
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    if (!this->HasTag(DICOM_TAG_PIXEL_DATA) &&
+        !DicomImageDecoder::IsPsmctRle1(*dcmDataset))
+    {
+      throw OrthancException(ErrorCode_BadRequest, "Cannot extract a frame from a DICOM file that does not have pixel data.");
     }
 
     if (pimpl_->frameIndex_.get() == NULL)
     {
-      assert(pimpl_->file_ != NULL && dcmDataset != NULL);
-
+      assert(pimpl_->file_ != NULL);
       pimpl_->frameIndex_.reset(new DicomFrameIndex(*dcmDataset));
     }
 
--- a/OrthancFramework/Sources/Enumerations.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/Enumerations.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -1199,6 +1199,9 @@
       case ErrorPayloadType_Dimse:
         return "Dimse";
 
+      case ErrorPayloadType_RetrieveJob:
+        return "RetrieveJob";
+
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
@@ -1932,6 +1935,10 @@
     {
       return ErrorPayloadType_Dimse;
     }
+    else if (type == "RetrieveJob")
+    {
+      return ErrorPayloadType_RetrieveJob;
+    }
     else
     {
       throw OrthancException(ErrorCode_ParameterOutOfRange);
--- a/OrthancFramework/Sources/Enumerations.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/Enumerations.h	Tue Nov 18 17:50:39 2025 +0100
@@ -805,7 +805,8 @@
   enum ErrorPayloadType
   {
     ErrorPayloadType_None = 1,
-    ErrorPayloadType_Dimse = 2
+    ErrorPayloadType_Dimse = 2,
+    ErrorPayloadType_RetrieveJob = 3,
   };
 
 
--- a/OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -369,7 +369,7 @@
           serialized.isMember(ERROR_PAYLOAD))
       {
         const std::string type = SerializationToolbox::ReadString(serialized, ERROR_PAYLOAD_TYPE);
-        lastStatus_.GetErrorPayload().SetContent(StringToErrorPayloadType(type.c_str()), serialized[ERROR_PAYLOAD]);
+        lastStatus_.GetErrorPayload().SetContent(StringToErrorPayloadType(type), serialized[ERROR_PAYLOAD]);
       }
 
       job_->Start();
@@ -1300,27 +1300,35 @@
     {
       boost::mutex::scoped_lock lock(registry_.mutex_);
 
-      switch (targetState_)
+      try
       {
-        case JobState_Failure:
-          registry_.MarkRunningAsCompleted
-            (*handler_, canceled_ ? CompletedReason_Canceled : CompletedReason_Failure);
-          break;
+        switch (targetState_)
+        {
+          case JobState_Failure:
+            registry_.MarkRunningAsCompleted
+              (*handler_, canceled_ ? CompletedReason_Canceled : CompletedReason_Failure);
+            break;
 
-        case JobState_Success:
-          registry_.MarkRunningAsCompleted(*handler_, CompletedReason_Success);
-          break;
+          case JobState_Success:
+            registry_.MarkRunningAsCompleted(*handler_, CompletedReason_Success);
+            break;
 
-        case JobState_Paused:
-          registry_.MarkRunningAsPaused(*handler_);
-          break;
+          case JobState_Paused:
+            registry_.MarkRunningAsPaused(*handler_);
+            break;
+
+          case JobState_Retry:
+            registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_);
+            break;
 
-        case JobState_Retry:
-          registry_.MarkRunningAsRetry(*handler_, targetRetryTimeout_);
-          break;
-
-        default:
-          assert(0);
+          default:
+            assert(0);
+        }
+      }
+      catch (OrthancException& e)
+      {
+        // Don't throw exceptions in destructors
+        LOG(ERROR) << "Exception in destructor: " << e.What();
       }
     }
   }
--- a/OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -191,12 +191,6 @@
   }
 
 
-  void SetOfInstancesJob::Start()
-  {
-    SetOfCommandsJob::Start();
-  }
-
-
   void SetOfInstancesJob::Reset()
   {
     SetOfCommandsJob::Reset();
--- a/OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.h	Tue Nov 18 17:50:39 2025 +0100
@@ -73,8 +73,6 @@
 
     bool IsFailedInstance(const std::string& instance) const;
 
-    virtual void Start() ORTHANC_OVERRIDE;
-
     virtual void Reset() ORTHANC_OVERRIDE;
 
     virtual void GetPublicContent(Json::Value& target) const ORTHANC_OVERRIDE;
--- a/OrthancFramework/Sources/MallocMemoryBuffer.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/MallocMemoryBuffer.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -25,6 +25,7 @@
 #include "PrecompiledHeaders.h"
 #include "MallocMemoryBuffer.h"
 
+#include "Logging.h"
 #include "OrthancException.h"
 
 #include <string.h>
@@ -40,6 +41,20 @@
   }
 
 
+  MallocMemoryBuffer::~MallocMemoryBuffer()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (OrthancException& e)
+    {
+      // Don't throw exceptions in destructors
+      LOG(ERROR) << "Exception in destructor: " << e.What();
+    }
+  }
+
+
   void MallocMemoryBuffer::Clear()
   {
     if (size_ != 0)
--- a/OrthancFramework/Sources/MallocMemoryBuffer.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/MallocMemoryBuffer.h	Tue Nov 18 17:50:39 2025 +0100
@@ -45,10 +45,7 @@
   public:
     MallocMemoryBuffer();
 
-    virtual ~MallocMemoryBuffer() ORTHANC_OVERRIDE
-    {
-      Clear();
-    }
+    virtual ~MallocMemoryBuffer() ORTHANC_OVERRIDE;
 
     void Clear();
 
--- a/OrthancFramework/Sources/MetricsRegistry.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/MetricsRegistry.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -27,6 +27,7 @@
 
 #include "ChunkedBuffer.h"
 #include "Compatibility.h"
+#include "Logging.h"
 #include "OrthancException.h"
 
 #include <boost/math/special_functions/round.hpp>
@@ -617,7 +618,15 @@
 
   MetricsRegistry::ActiveCounter::~ActiveCounter()
   {
-    metrics_.Add(-1);
+    try
+    {
+      metrics_.Add(-1);
+    }
+    catch (OrthancException& e)
+    {
+      // Don't throw exceptions in destructors
+      LOG(ERROR) << "Exception in destructor: " << e.What();
+    }
   }
 
 
@@ -629,7 +638,15 @@
 
   MetricsRegistry::AvailableResourcesDecounter::~AvailableResourcesDecounter()
   {
-    metrics_.Add(1);
+    try
+    {
+      metrics_.Add(1);
+    }
+    catch (OrthancException& e)
+    {
+      // Don't throw exceptions in destructors
+      LOG(ERROR) << "Exception in destructor: " << e.What();
+    }
   }
 
 
@@ -673,7 +690,16 @@
     if (active_)
     {
       boost::posix_time::time_duration diff = GetNow() - start_;
-      registry_.SetIntegerValue(name_, static_cast<int64_t>(diff.total_milliseconds()), policy_);
+
+      try
+      {
+        registry_.SetIntegerValue(name_, static_cast<int64_t>(diff.total_milliseconds()), policy_);
+      }
+      catch (OrthancException& e)
+      {
+        // Don't throw exceptions in destructors
+        LOG(ERROR) << "Exception in destructor: " << e.What();
+      }
     }
   }
 }
--- a/OrthancFramework/Sources/MultiThreading/IRunnableBySteps.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/Sources/MultiThreading/IRunnableBySteps.h	Tue Nov 18 17:50:39 2025 +0100
@@ -32,10 +32,6 @@
   class IRunnableBySteps : public IDynamicObject
   {
   public:
-    virtual ~IRunnableBySteps() ORTHANC_OVERRIDE
-    {
-    }
-
     // Must return "true" if the runnable wishes to continue. Must
     // return "false" if the runnable has not finished its job.
     virtual bool Step() = 0;
--- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -1562,7 +1562,7 @@
 
     if (components.size() != 2)
     {
-      throw;
+      throw OrthancException(ErrorCode_InternalError);
     }
 
     int a = boost::lexical_cast<int>(components[0]);
@@ -1571,7 +1571,7 @@
         b < 0 || b > 15 ||
         (a == 0 && b == 0))
     {
-      throw;
+      throw OrthancException(ErrorCode_InternalError);
     }
 
     result[i] = static_cast<uint8_t>(a * 16 + b);
--- a/OrthancFramework/UnitTestsSources/RestApiTests.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancFramework/UnitTestsSources/RestApiTests.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -1316,7 +1316,7 @@
       {
         if (b[i] != ('0' + i % 7))
         {
-          throw;
+          throw OrthancException(ErrorCode_InternalError);
         }
       }
       
--- a/OrthancServer/CMakeLists.txt	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/CMakeLists.txt	Tue Nov 18 17:50:39 2025 +0100
@@ -637,14 +637,6 @@
     list(APPEND MODALITY_WORKLISTS_RESOURCES ${AUTOGENERATED_DIR}/ModalityWorklists.rc)
   endif()
 
-  EmbedResources(
-    --target=ModalityWorklistsResources
-    --namespace=Orthanc.FrameworkResources
-    --framework-path=${CMAKE_SOURCE_DIR}/../OrthancFramework/Sources
-    ${LIBICU_RESOURCES}
-    ${DCMTK_DICTIONARIES}
-    )
-
   set_source_files_properties(
     ${CMAKE_SOURCE_DIR}/Plugins/Samples/ModalityWorklists/Plugin.cpp
     PROPERTIES COMPILE_DEFINITIONS "MODALITY_WORKLISTS_VERSION=\"${ORTHANC_VERSION}\""
@@ -652,14 +644,12 @@
 
   add_library(ModalityWorklists SHARED 
     ${CMAKE_SOURCE_DIR}/Plugins/Samples/ModalityWorklists/Plugin.cpp
-    ${CMAKE_SOURCE_DIR}/Plugins/Samples/ModalityWorklists/OrthancFrameworkDependencies.cpp
-    ${AUTOGENERATED_DIR}/ModalityWorklistsResources.cpp
     ${MODALITY_WORKLISTS_RESOURCES}
     )
 
   DefineSourceBasenameForTarget(ModalityWorklists)
 
-  target_link_libraries(ModalityWorklists PluginsDependencies ${DCMTK_LIBRARIES})
+  target_link_libraries(ModalityWorklists PluginsDependencies)
 
   set_target_properties(
     ModalityWorklists PROPERTIES 
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Nov 18 17:50:39 2025 +0100
@@ -2180,7 +2180,7 @@
    **/
   ORTHANC_PLUGIN_SINCE_SDK("1.4.0")
   ORTHANC_PLUGIN_INLINE int32_t  OrthancPluginCheckVersionAdvanced(
-    OrthancPluginContext* context,
+    const OrthancPluginContext* context,
     int32_t expectedMajor,
     int32_t expectedMinor,
     int32_t expectedRevision)
@@ -2295,7 +2295,7 @@
    * @ingroup Callbacks
    **/
   ORTHANC_PLUGIN_INLINE int32_t  OrthancPluginCheckVersion(
-    OrthancPluginContext* context)
+    const OrthancPluginContext* context)
   {
     return OrthancPluginCheckVersionAdvanced(
       context,
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -221,6 +221,19 @@
   }
 
 
+  MemoryBuffer::~MemoryBuffer()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void MemoryBuffer::Clear()
   {
     if (buffer_.data != NULL)
@@ -652,6 +665,19 @@
   }
 
 
+  OrthancString::~OrthancString()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void OrthancString::Assign(char* str)
   {
     Clear();
@@ -1301,6 +1327,20 @@
     }
   }
 
+
+  OrthancImage::~OrthancImage()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void OrthancImage::UncompressPngImage(const void* data,
                                         size_t size)
   {
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Nov 18 17:50:39 2025 +0100
@@ -219,10 +219,7 @@
   public:
     MemoryBuffer();
 
-    ~MemoryBuffer()
-    {
-      Clear();
-    }
+    ~MemoryBuffer();
 
     OrthancPluginMemoryBuffer* operator*()
     {
@@ -377,10 +374,7 @@
     {
     }
 
-    ~OrthancString()
-    {
-      Clear();
-    }
+    ~OrthancString();
 
     // This transfers ownership, warning: The string must have been
     // allocated by the Orthanc core
@@ -497,10 +491,7 @@
                  uint32_t                  pitch,
                  void*                     buffer);
 
-    ~OrthancImage()
-    {
-      Clear();
-    }
+    ~OrthancImage();
 
     void UncompressPngImage(const void* data,
                             size_t size);
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/CMakeLists.txt	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/ModalityWorklists/CMakeLists.txt	Tue Nov 18 17:50:39 2025 +0100
@@ -27,31 +27,22 @@
 SET(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)")
 SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
 
-include(${CMAKE_SOURCE_DIR}/../Common/OrthancPlugins.cmake)
-include(${CMAKE_SOURCE_DIR}/../../../../OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake)
+SET(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp")
+SET(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of boost")
 
-set(ENABLE_JPEG ON CACHE INTERNAL "")
-set(ENABLE_PNG ON CACHE INTERNAL "")
-set(ENABLE_ZLIB ON CACHE INTERNAL "")
-set(ENABLE_LOCALE ON CACHE INTERNAL "")
-set(ENABLE_DCMTK ON CACHE INTERNAL "")
-set(ENABLE_MODULE_DICOM ON CACHE INTERNAL "")
-set(ENABLE_MODULE_JOBS OFF CACHE INTERNAL "")
-
-include(${CMAKE_SOURCE_DIR}/../../../../OrthancFramework/Resources/CMake/OrthancFrameworkConfiguration.cmake)
+include(${CMAKE_SOURCE_DIR}/../Common/OrthancPlugins.cmake)
+include(${CMAKE_SOURCE_DIR}/../../../../OrthancFramework/Resources/CMake/JsonCppConfiguration.cmake)
+include(${CMAKE_SOURCE_DIR}/../../../../OrthancFramework/Resources/CMake/BoostConfiguration.cmake)
 
 add_library(ModalityWorklists SHARED 
   Plugin.cpp
   ${CMAKE_SOURCE_DIR}/../Common/OrthancPluginCppWrapper.cpp
-  ${ORTHANC_CORE_SOURCES}
-  ${ORTHANC_DICOM_SOURCES}
-  ${AUTOGENERATED_SOURCES}
+  ${JSONCPP_SOURCES}
+  ${BOOST_SOURCES}
   )
 
 DefineSourceBasenameForTarget(ModalityWorklists)
 
-target_link_libraries(ModalityWorklists ${DCMTK_LIBRARIES})
-
 message("Setting the version of the plugin to ${MODALITY_WORKLISTS_VERSION}")
 add_definitions(
   -DMODALITY_WORKLISTS_VERSION="${MODALITY_WORKLISTS_VERSION}"
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/OrthancFrameworkDependencies.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
- * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-/**
- * Remove the dependency upon ICU in plugins, as this greatly increase
- * the size of the resulting binaries, since they must embed the ICU
- * dictionary.
- **/
-
-#if BOOST_LOCALE_WITH_ICU == 1
-#  undef BOOST_LOCALE_WITH_ICU
-#  if ORTHANC_STATIC_ICU == 1
-#    include <unicode/udata.h>
-
-// Define an empty ICU dictionary for static builds
-extern "C"
-{
-  struct
-  {
-    double bogus;
-    uint8_t *bytes;
-  } U_ICUDATA_ENTRY_POINT = { 0.0, NULL };
-}
-
-#  endif
-#endif
-
-#include "../../../../OrthancFramework/Sources/ChunkedBuffer.cpp"
-#include "../../../../OrthancFramework/Sources/Compression/DeflateBaseCompressor.cpp"
-#include "../../../../OrthancFramework/Sources/Compression/GzipCompressor.cpp"
-#include "../../../../OrthancFramework/Sources/Compression/ZlibCompressor.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomArray.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomElement.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomImageInformation.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomInstanceHasher.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomIntegerPixelAccessor.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomMap.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomPath.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomTag.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomValue.cpp"
-#include "../../../../OrthancFramework/Sources/DicomFormat/Window.cpp"
-#include "../../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp"
-#include "../../../../OrthancFramework/Sources/DicomParsing/Internals/DicomFrameIndex.cpp"
-#include "../../../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp"
-#include "../../../../OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp"
-#include "../../../../OrthancFramework/Sources/DicomParsing/ToDcmtkBridge.cpp"
-#include "../../../../OrthancFramework/Sources/Enumerations.cpp"
-#include "../../../../OrthancFramework/Sources/HttpServer/HttpOutput.cpp"
-#include "../../../../OrthancFramework/Sources/Images/IImageWriter.cpp"
-#include "../../../../OrthancFramework/Sources/Images/Image.cpp"
-#include "../../../../OrthancFramework/Sources/Images/ImageAccessor.cpp"
-#include "../../../../OrthancFramework/Sources/Images/ImageBuffer.cpp"
-#include "../../../../OrthancFramework/Sources/Images/ImageProcessing.cpp"
-#include "../../../../OrthancFramework/Sources/Images/JpegErrorManager.cpp"
-#include "../../../../OrthancFramework/Sources/Images/JpegReader.cpp"
-#include "../../../../OrthancFramework/Sources/Images/JpegWriter.cpp"
-#include "../../../../OrthancFramework/Sources/Images/PamReader.cpp"
-#include "../../../../OrthancFramework/Sources/Images/PamWriter.cpp"
-#include "../../../../OrthancFramework/Sources/Images/PngReader.cpp"
-#include "../../../../OrthancFramework/Sources/Images/PngWriter.cpp"
-#include "../../../../OrthancFramework/Sources/Logging.cpp"
-#include "../../../../OrthancFramework/Sources/MetricsRegistry.cpp"
-#include "../../../../OrthancFramework/Sources/MultiThreading/RunnableWorkersPool.cpp"
-#include "../../../../OrthancFramework/Sources/MultiThreading/SharedMessageQueue.cpp"
-#include "../../../../OrthancFramework/Sources/OrthancException.cpp"
-#include "../../../../OrthancFramework/Sources/OrthancFramework.cpp"
-#include "../../../../OrthancFramework/Sources/RestApi/RestApiOutput.cpp"
-#include "../../../../OrthancFramework/Sources/SerializationToolbox.cpp"
-#include "../../../../OrthancFramework/Sources/SystemToolbox.cpp"
-#include "../../../../OrthancFramework/Sources/TemporaryFile.cpp"
-#include "../../../../OrthancFramework/Sources/Toolbox.cpp"
-
-namespace Orthanc
-{
-  void HttpClient::GlobalInitialize()
-  {
-  }
-
-  void HttpClient::GlobalFinalize()
-  {
-  }
-}
--- a/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -24,84 +24,17 @@
 #define MODALITY_WORKLISTS_NAME "worklists"
 
 #include "../../../../OrthancFramework/Sources/Compatibility.h"
-#include "../../../../OrthancFramework/Sources/OrthancException.h"
-#include "../../../../OrthancFramework/Sources/Logging.h"
-#include "../../../../OrthancFramework/Sources/Toolbox.h"
-#include "../../../../OrthancFramework/Sources/SystemToolbox.h"
-#include "../../../../OrthancFramework/Sources/DicomParsing/ParsedDicomFile.h"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomPath.h"
-#include "../../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
-#include "../../../../OrthancFramework/Sources/DicomFormat/DicomInstanceHasher.h"
 #include "../Common/OrthancPluginCppWrapper.h"
 
-#include <boost/thread.hpp>
 #include <boost/filesystem.hpp>
 #include <json/value.h>
 #include <string.h>
 #include <iostream>
 #include <algorithm>
 
-static boost::filesystem::path worklistDirectory_;
+static std::string folder_;
 static bool filterIssuerAet_ = false;
 static unsigned int limitAnswers_ = 0;
-static std::unique_ptr<boost::thread> worklistHousekeeperThread_;
-static bool worklistHousekeeperThreadShouldStop_ = false;
-static bool deleteWorklistsOnStableStudy_ = true;
-static unsigned int hkIntervalInSeconds_ = 60;
-static unsigned int deleteDelayInHours_ = 24;
-static std::unique_ptr<OrthancPlugins::KeyValueStore> worklistsStore_;
-static bool setStudyInstanceUidIfMissing_ = true;
-
-enum WorklistStorageType
-{
-  WorklistStorageType_Folder = 1,
-  WorklistStorageType_OrthancDb = 2
-};
-
-static WorklistStorageType worklistStorage_ = WorklistStorageType_Folder;
-
-struct Worklist
-{
-  std::string id_;
-  std::string createdAt_;
-  std::string dicomContent_;
-
-  Worklist(const std::string& id, 
-           const std::string& dicomContent) :
-    id_(id),
-    createdAt_(Orthanc::SystemToolbox::GetNowIsoString(true)),
-    dicomContent_(dicomContent)
-  {
-  }
-
-
-  Worklist(const std::string& id, const Json::Value& jsonWl) :
-    id_(id),
-    createdAt_(jsonWl["CreatedAt"].asString())
-  {
-    std::string b64DicomContent = jsonWl["Dicom"].asString();
-    Orthanc::Toolbox::DecodeBase64(dicomContent_, b64DicomContent);
-  }
-
-  void Serialize(std::string& target) const
-  {
-    Json::Value t;
-    t["CreatedAt"] = createdAt_;
-    std::string b64DicomContent;
-    Orthanc::Toolbox::EncodeBase64(b64DicomContent, dicomContent_);
-    t["Dicom"] = b64DicomContent;
-    
-    Orthanc::Toolbox::WriteFastJson(target, t);
-  }
-
-  bool IsOlderThan(unsigned int delayInHours) const
-  {
-    boost::posix_time::ptime now(boost::posix_time::from_iso_string(Orthanc::SystemToolbox::GetNowIsoString(true)));
-    boost::posix_time::ptime creationDate(boost::posix_time::from_iso_string(createdAt_));
-
-    return (now - creationDate).total_seconds() > (3600 * deleteDelayInHours_);
-  }
-};
 
 /**
  * This is the main function for matching a DICOM worklist against a query.
@@ -109,10 +42,10 @@
 static bool MatchWorklist(OrthancPluginWorklistAnswers*      answers,
                            const OrthancPluginWorklistQuery*  query,
                            const OrthancPlugins::FindMatcher& matcher,
-                           const std::string& dicomContent)
+                           const std::string& path)
 {
   OrthancPlugins::MemoryBuffer dicom;
-  dicom.Assign(dicomContent);
+  dicom.ReadFile(path);
 
   if (matcher.IsMatch(dicom))
   {
@@ -204,116 +137,70 @@
   }
 }
 
-static void ListWorklistsFromDb(std::vector<Worklist>& target)
-{
-  assert(worklistStorage_ == WorklistStorageType_OrthancDb);
-  assert(worklistsStore_);
-  
-  std::unique_ptr<OrthancPlugins::KeyValueStore::Iterator> it(worklistsStore_->CreateIterator());
-  
-  while (it->Next())
-  {
-    std::string serialized;
-    it->GetValue(serialized);
-    
-    Json::Value jsonWl;
-    if (Orthanc::Toolbox::ReadJson(jsonWl, serialized))
-    {
-      Worklist wl(it->GetKey(), jsonWl);
-      target.push_back(wl);
-    }
-  };
-  
-}
 
 
-static void ListWorklistsFromFolder(std::vector<Worklist>& target)
-{
-  assert(worklistStorage_ == WorklistStorageType_Folder);
-
-  // Loop over the regular files in the database folder
-  namespace fs = boost::filesystem;
-
-  fs::path source = worklistDirectory_;
-  fs::directory_iterator end;
-
-  try
-  {
-    for (fs::directory_iterator it(source); it != end; ++it)
-    {
-      fs::file_type type(it->status().type());
-
-      if (type == fs::regular_file ||
-          type == fs::reparse_file)   // cf. BitBucket issue #11
-      {
-        std::string extension = it->path().extension().string();
-        std::transform(extension.begin(), extension.end(), extension.begin(), tolower);  // Convert to lowercase
-
-        if (extension == ".wl")
-        {
-          std::string worklistId = Orthanc::SystemToolbox::PathToUtf8(it->path().filename().replace_extension(""));
-          std::string dicomContent;
-          Orthanc::SystemToolbox::ReadFile(dicomContent, it->path());
-
-          Worklist wl(worklistId, dicomContent);
-          target.push_back(wl);
-        }
-      }
-    }
-  }
-  catch (fs::filesystem_error&)
-  {
-    LOG(ERROR) << "Inexistent folder while scanning for worklists: " + source.string();
-  }
-}
-
-
-OrthancPluginErrorCode WorklistCallback(OrthancPluginWorklistAnswers*     answers,
-                                        const OrthancPluginWorklistQuery* query,
-                                        const char*                       issuerAet,
-                                        const char*                       calledAet)
+OrthancPluginErrorCode Callback(OrthancPluginWorklistAnswers*     answers,
+                                const OrthancPluginWorklistQuery* query,
+                                const char*                       issuerAet,
+                                const char*                       calledAet)
 {
   try
   {
-    unsigned int parsedFilesCount = 0;
-    unsigned int matchedWorklistCount = 0;
-
     // Construct an object to match the worklists in the database against the C-Find query
     std::unique_ptr<OrthancPlugins::FindMatcher> matcher(CreateMatcher(query, issuerAet));
 
-    std::vector<Worklist> worklists;
+    // Loop over the regular files in the database folder
+    namespace fs = boost::filesystem;
 
-    if (worklistStorage_ == WorklistStorageType_Folder)
+    fs::path source(folder_);
+    fs::directory_iterator end;
+
+    try
     {
-      ListWorklistsFromFolder(worklists);
-    }
-    else if (worklistStorage_ == WorklistStorageType_OrthancDb)
-    {
-      ListWorklistsFromDb(worklists);
-    }
-
-    for (std::vector<Worklist>::const_iterator it = worklists.begin(); it != worklists.end(); ++it)
-    {
-      if (MatchWorklist(answers, query, *matcher, it->dicomContent_))
+      unsigned int parsedFilesCount = 0;
+      unsigned int matchedWorklistCount = 0;
+      
+      for (fs::directory_iterator it(source); it != end; ++it)
       {
-        if (limitAnswers_ != 0 &&
-            matchedWorklistCount >= limitAnswers_)
+        fs::file_type type(it->status().type());
+
+        if (type == fs::regular_file ||
+            type == fs::reparse_file)   // cf. BitBucket issue #11
         {
-          // Too many answers are to be returned wrt. the
-          // "LimitAnswers" configuration parameter. Mark the
-          // C-FIND result as incomplete.
-          OrthancPluginWorklistMarkIncomplete(OrthancPlugins::GetGlobalContext(), answers);
-          return OrthancPluginErrorCode_Success;
+          std::string extension = it->path().extension().string();
+          std::transform(extension.begin(), extension.end(), extension.begin(), tolower);  // Convert to lowercase
+
+          if (extension == ".wl")
+          {
+            parsedFilesCount++;
+            // We found a worklist (i.e. a DICOM find with extension ".wl"), match it against the query
+            if (MatchWorklist(answers, query, *matcher, it->path().string()))
+            {
+              if (limitAnswers_ != 0 &&
+                  matchedWorklistCount >= limitAnswers_)
+              {
+                // Too many answers are to be returned wrt. the
+                // "LimitAnswers" configuration parameter. Mark the
+                // C-FIND result as incomplete.
+                OrthancPluginWorklistMarkIncomplete(OrthancPlugins::GetGlobalContext(), answers);
+                return OrthancPluginErrorCode_Success;
+              }
+              
+              ORTHANC_PLUGINS_LOG_INFO("Worklist matched: " + it->path().string());
+              matchedWorklistCount++;
+            }
+          }
         }
-        
-        LOG(INFO) << "Worklist matched: " << it->id_;
-        matchedWorklistCount++;
       }
+
+      ORTHANC_PLUGINS_LOG_INFO("Worklist C-Find: parsed " + boost::lexical_cast<std::string>(parsedFilesCount) +
+                               " files, found " + boost::lexical_cast<std::string>(matchedWorklistCount) + " match(es)");
     }
-
-    LOG(INFO) << "Worklist C-Find: parsed " << boost::lexical_cast<std::string>(parsedFilesCount) <<
-                 " worklists, found " << boost::lexical_cast<std::string>(matchedWorklistCount) << " match(es)";
-
+    catch (fs::filesystem_error&)
+    {
+      ORTHANC_PLUGINS_LOG_ERROR("Inexistent folder while scanning for worklists: " + source.string());
+      return OrthancPluginErrorCode_DirectoryExpected;
+    }
 
     return OrthancPluginErrorCode_Success;
   }
@@ -323,411 +210,13 @@
   }
 }
 
-static void DeleteWorklist(const std::string& worklistId)
-{
-  switch (worklistStorage_)
-  {
-    case WorklistStorageType_Folder:
-    {
-      boost::filesystem::path path = worklistDirectory_ / (worklistId + ".wl");
-      if (!Orthanc::SystemToolbox::IsRegularFile(path))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
-      }
-      Orthanc::SystemToolbox::RemoveFile(path);
-      break;
-    }
-
-    case WorklistStorageType_OrthancDb:
-      if (worklistsStore_.get() != NULL)
-      {
-        std::string notUsed;
-        if (!worklistsStore_->GetValue(notUsed, worklistId))
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
-        }
-        worklistsStore_->DeleteKey(worklistId);
-      }
-      break;
-
-    default:
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-  }
-
-}
-
-static void WorklistHkWorkerThread()
-{
-  OrthancPluginSetCurrentThreadName(OrthancPlugins::GetGlobalContext(), "WL HOUSEKEEPER");
-
-  OrthancPluginLogWarning(OrthancPlugins::GetGlobalContext(), "Starting Worklist Housekeeper worker thread");
-  Orthanc::Toolbox::ElapsedTimer timer;
-
-  while (!worklistHousekeeperThreadShouldStop_)
-  {
-    boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
-
-    if (timer.GetElapsedMilliseconds() > (hkIntervalInSeconds_ * 1000))
-    {
-      timer.Restart();
-      LOG(INFO) << "Performing Worklist Housekeeping";
-
-      std::vector<Worklist> worklists;
-
-      if (worklistStorage_ == WorklistStorageType_OrthancDb)
-      {
-        ListWorklistsFromDb(worklists);
-      }
-      else if (worklistStorage_ == WorklistStorageType_Folder)
-      {
-        ListWorklistsFromFolder(worklists);
-      }
-
-      for (std::vector<Worklist>::const_iterator it = worklists.begin(); it != worklists.end(); ++it)
-      {
-        if (deleteDelayInHours_ > 0 && it->IsOlderThan(deleteDelayInHours_))
-        {
-          LOG(INFO) << "Deleting worklist " << it->id_ << " " << deleteDelayInHours_ << " hours after its creation";
-          DeleteWorklist(it->id_);
-        }
-        else if (deleteWorklistsOnStableStudy_)
-        {
-          std::string studyInstanceUid;
-          std::string patientId;
-
-          Orthanc::ParsedDicomFile parsed(it->dicomContent_);
-          
-          if (parsed.GetTagValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID) &&
-              parsed.GetTagValue(patientId, Orthanc::DICOM_TAG_PATIENT_ID))
-          {
-            Orthanc::DicomInstanceHasher hasher(patientId, studyInstanceUid, "fake-id", "fake-id");
-            const std::string& studyOrthancId = hasher.HashStudy();
-
-            Json::Value studyInfo;
-            if (OrthancPlugins::RestApiGet(studyInfo, "/studies/" + studyOrthancId, false))
-            {
-              if (studyInfo["IsStable"].asBool())
-              {
-                LOG(INFO) << "Deleting worklist " << it->id_ << " because its study is now stable";
-                DeleteWorklist(it->id_);
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-
-static Orthanc::DicomToJsonFormat GetFormat(const OrthancPluginHttpRequest* request)
-{
-  std::map<std::string, std::string> getArguments;
-  OrthancPlugins::GetGetArguments(getArguments, request);
-
-  Orthanc::DicomToJsonFormat format = Orthanc::DicomToJsonFormat_Human;
-
-  if (getArguments.find("format") != getArguments.end())
-  {
-    format = Orthanc::StringToDicomToJsonFormat(getArguments["format"]);
-  }
-
-  return format;
-}
-
-static Orthanc::ParsedDicomFile* GetWorklist(const std::string& id)
-{
-  std::string fileContent;
-
-  switch (worklistStorage_)
-  {
-    case WorklistStorageType_Folder:
-    {
-      boost::filesystem::path path = worklistDirectory_ / Orthanc::SystemToolbox::PathFromUtf8(id + ".wl");  // the id might be a filename from a file that was pushed by an external program (therefore, it can contain fancy characters)
-      if (!Orthanc::SystemToolbox::IsRegularFile(path))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource, "Worklist not found");
-      }
-
-      Orthanc::SystemToolbox::ReadFile(fileContent, path);
-      break;
-    }
-
-    case WorklistStorageType_OrthancDb:
-    {
-      std::string serializedWl;
-      if (!worklistsStore_->GetValue(serializedWl, id))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource, "Worklist not found");
-      }
-
-      Json::Value jsonWl;
-      if (Orthanc::Toolbox::ReadJson(jsonWl, serializedWl))
-      {
-        Worklist wl(id, jsonWl);
-        fileContent = wl.dicomContent_;
-      }
-      break;
-    }
-
-    default:
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-  }
-
-  return new Orthanc::ParsedDicomFile(fileContent);  
-}
-
-static void SerializeWorklistForApi(Json::Value& target, const std::string& id, const Orthanc::ParsedDicomFile& parsed, Orthanc::DicomToJsonFormat format)
-{
-  target["ID"] = id;
-  target["Tags"] = Json::objectValue;
-  parsed.DatasetToJson(target["Tags"], format, Orthanc::DicomToJsonFlags_None, 0);
-}
 
 extern "C"
 {
-
-  OrthancPluginErrorCode ListWorklists(OrthancPluginRestOutput* output,
-                                       const char* url,
-                                       const OrthancPluginHttpRequest* request)
-  {
-    if (request->method != OrthancPluginHttpMethod_Get)
-    {
-      OrthancPlugins::AnswerMethodNotAllowed(output, "GET");
-    }
-    else
-    {
-      Json::Value response = Json::arrayValue;
-      Orthanc::DicomToJsonFormat format = GetFormat(request);
-
-      std::vector<Worklist> worklists;
-
-      if (worklistStorage_ == WorklistStorageType_Folder)
-      {
-        ListWorklistsFromFolder(worklists);
-      }
-      else if (worklistStorage_ == WorklistStorageType_OrthancDb)
-      {
-        ListWorklistsFromDb(worklists);
-      }
-
-      for (std::vector<Worklist>::const_iterator it = worklists.begin(); it != worklists.end(); ++it)
-      {
-        Orthanc::ParsedDicomFile parsed(it->dicomContent_);
-        Json::Value jsonWl;
-        SerializeWorklistForApi(jsonWl, it->id_, parsed, format);
-
-        if (worklistStorage_ == WorklistStorageType_OrthancDb)
-        {
-          jsonWl["CreationDate"] = it->createdAt_;
-        }
-
-        response.append(jsonWl);
-      }
-
-      OrthancPlugins::AnswerJson(response, output);
-    }
-
-    return OrthancPluginErrorCode_Success;
-  }
-
-
-  void CreateOrUpdateWorklist(std::string& worklistId, 
-                              bool defaultForceValue,
-                              OrthancPluginRestOutput* output,
-                              const char* url,
-                              const OrthancPluginHttpRequest* request)
-  {
-    Json::Value body;
-
-    if (!OrthancPlugins::ReadJson(body, request->body, request->bodySize))
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "A JSON payload was expected");
-    }
-
-    if (!body.isMember("Tags") || !body["Tags"].isObject())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "'Tags' field is missing or not a JSON object");
-    }
-
-    bool force = defaultForceValue;
-    if (body.isMember("Force")) {
-      force = body["Force"].asBool();
-    }
-
-    Json::Value& jsonWorklist = body["Tags"];
-
-    if (!jsonWorklist.isMember("SpecificCharacterSet"))
-    {
-      jsonWorklist["SpecificCharacterSet"] = Orthanc::GetDicomSpecificCharacterSet(Orthanc::Encoding_Utf8);
-    }
-
-    std::unique_ptr<Orthanc::ParsedDicomFile> dicom(Orthanc::ParsedDicomFile::CreateFromJson(jsonWorklist, Orthanc::DicomFromJsonFlags_None, ""));      
-
-    if (!force) 
-    {
-      if (!dicom->HasTag(Orthanc::DICOM_TAG_SCHEDULED_PROCEDURE_STEP_SEQUENCE))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "'Tags' is missing a 'ScheduledProcedureStepSequence'.  Use 'Force': true to bypass this check.");
-      }
-      Orthanc::DicomMap step;
-      if (!dicom->LookupSequenceItem(step, Orthanc::DicomPath::Parse("ScheduledProcedureStepSequence"), 0) || !step.HasTag(Orthanc::DICOM_TAG_MODALITY))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "'ScheduledProcedureStepSequence' is missing a 'Modality'  Use 'Force': true to bypass this check.");
-      }
-      if (!dicom->LookupSequenceItem(step, Orthanc::DicomPath::Parse("ScheduledProcedureStepSequence"), 0) || !step.HasTag(Orthanc::DICOM_TAG_SCHEDULED_PROCEDURE_STEP_START_DATE))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "'ScheduledProcedureStepSequence' is missing a 'ScheduledProcedureStepStartDate'  Use 'Force': true to bypass this check.");
-      }
-    }
-
-    dicom->SetIfAbsent(Orthanc::DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID, "1.2.276.0.7230010.3.1.0.1");
-      
-    if (setStudyInstanceUidIfMissing_)
-    {
-      dicom->SetIfAbsent(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, Orthanc::FromDcmtkBridge::GenerateUniqueIdentifier(Orthanc::ResourceType_Study));
-    }
-
-    if (worklistId.empty())
-    {
-      worklistId = Orthanc::Toolbox::GenerateUuid();
-    }
-
-    std::string dicomContent;
-    dicom->SaveToMemoryBuffer(dicomContent);
-      
-    switch (worklistStorage_)
-    {
-      case WorklistStorageType_Folder:
-        Orthanc::SystemToolbox::WriteFile(dicomContent.empty() ? NULL : dicomContent.c_str(), dicomContent.size(),
-                                          worklistDirectory_ / Orthanc::SystemToolbox::PathFromUtf8(worklistId + ".wl"), true);
-        break;
-
-      case WorklistStorageType_OrthancDb:
-      {
-        Worklist wl(worklistId, dicomContent);
-        std::string serializedWl;
-        wl.Serialize(serializedWl);
-
-        worklistsStore_->Store(worklistId, serializedWl);
-        break;
-      }
-
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-    }
-
-    Json::Value response;
-
-    response["ID"] = worklistId;
-    response["Path"] = "/worklists/" + worklistId;
-
-    OrthancPlugins::AnswerJson(response, output);
-  }
-
-
-  OrthancPluginErrorCode GetPutDeleteWorklist(OrthancPluginRestOutput* output,
-                                              const char* url,
-                                              const OrthancPluginHttpRequest* request)
-  {
-    std::string worklistId = std::string(request->groups[0]);
-
-    if (request->method == OrthancPluginHttpMethod_Delete)
-    {
-      DeleteWorklist(worklistId);
-
-      OrthancPlugins::AnswerString("{}", "application/json", output);
-    }
-    else if (request->method == OrthancPluginHttpMethod_Get)
-    {
-      Orthanc::DicomToJsonFormat format = GetFormat(request);
-      std::unique_ptr<Orthanc::ParsedDicomFile> parsed(GetWorklist(worklistId));
-
-      Json::Value jsonWl;
-      SerializeWorklistForApi(jsonWl, worklistId, *parsed, format);
-      
-      OrthancPlugins::AnswerJson(jsonWl, output);
-    }
-    else if (request->method == OrthancPluginHttpMethod_Put)
-    {
-      CreateOrUpdateWorklist(worklistId, true, output, url, request);
-    }
-    else
-    {
-      OrthancPlugins::AnswerMethodNotAllowed(output, "DELETE,GET");
-    }
-
-    return OrthancPluginErrorCode_Success;
-  }
-
-
-  OrthancPluginErrorCode PostCreateWorklist(OrthancPluginRestOutput* output,
-                                            const char* url,
-                                            const OrthancPluginHttpRequest* request)
-  {
-    if (request->method != OrthancPluginHttpMethod_Post)
-    {
-      OrthancPlugins::AnswerMethodNotAllowed(output, "POST");
-    }
-    else
-    {
-      std::string worklistId;
-      CreateOrUpdateWorklist(worklistId, false, output, url, request);
-    }
-    return OrthancPluginErrorCode_Success;
-  }
-
-  static OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeType, 
-                                                 OrthancPluginResourceType resourceType,
-                                                 const char *resourceId)
-  {
-    try
-    {
-      if (changeType == OrthancPluginChangeType_OrthancStarted)
-      {
-        Json::Value system;
-        bool hasKeyValueStores = (OrthancPlugins::RestApiGet(system, "/system", false) && system.isMember("Capabilities") &&
-                                  system["Capabilities"].isMember("HasKeyValueStores") && system["Capabilities"]["HasKeyValueStores"].asBool());
-
-        if (worklistStorage_ == WorklistStorageType_OrthancDb && !hasKeyValueStores)
-        {
-          LOG(ERROR) << "The Orthanc DB plugin does not support Key Value Stores.  It is therefore impossible to store the worklists in Orthanc Database";
-          return OrthancPluginErrorCode_IncompatibleConfigurations;
-        }
-
-        if (deleteDelayInHours_ > 0 && !hasKeyValueStores)
-        {
-          LOG(ERROR) << "The Orthanc DB plugin does not support Key Value Stores.  It is therefore impossible to use the \"DeleteWorklistsDelay\" option";
-          return OrthancPluginErrorCode_IncompatibleConfigurations;
-        }
-
-        if (worklistStorage_ == WorklistStorageType_OrthancDb)
-        {
-          worklistsStore_.reset(new OrthancPlugins::KeyValueStore("worklists"));
-        }
-
-        if (deleteDelayInHours_ > 0 || deleteWorklistsOnStableStudy_)
-        {
-          worklistHousekeeperThread_.reset(new boost::thread(WorklistHkWorkerThread));
-        }
-      }
-    }
-    catch (Orthanc::OrthancException& e)
-    {
-      LOG(ERROR) << "Exception: " << e.What();
-    }
-    catch (...)
-    {
-      LOG(ERROR) << "Uncatched native exception";
-    }      
-    return OrthancPluginErrorCode_Success;
-  }
-
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
   {
     OrthancPlugins::SetGlobalContext(c, MODALITY_WORKLISTS_NAME);
-    Orthanc::Logging::InitializePluginContext(c, MODALITY_WORKLISTS_NAME);
-  
+
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(c) == 0)
     {
@@ -737,29 +226,6 @@
       return -1;
     }
 
-    { // init the OrthancFramework
-      static const char* const LOCALE = "Locale";
-      static const char* const DEFAULT_ENCODING = "DefaultEncoding";
-
-      /**
-       * This function is a simplified version of function
-       * "Orthanc::OrthancInitialize()" that is executed when starting the
-       * Orthanc server.
-       **/
-      OrthancPlugins::OrthancConfiguration globalConfig;
-      Orthanc::InitializeFramework(globalConfig.GetStringValue(LOCALE, ""), false /* loadPrivateDictionary */);
-
-      std::string encoding;
-      if (globalConfig.LookupStringValue(encoding, DEFAULT_ENCODING))
-      {
-        Orthanc::SetDefaultDicomEncoding(Orthanc::StringToEncoding(encoding.c_str()));
-      }
-      else
-      {
-        Orthanc::SetDefaultDicomEncoding(Orthanc::ORTHANC_DEFAULT_DICOM_ENCODING);
-      }      
-    }
-
     ORTHANC_PLUGINS_LOG_WARNING("Sample worklist plugin is initializing");
     OrthancPluginSetDescription2(c, MODALITY_WORKLISTS_NAME, "Serve DICOM modality worklists from a folder with Orthanc.");
 
@@ -771,52 +237,19 @@
     bool enabled = worklists.GetBooleanValue("Enable", false);
     if (enabled)
     {
-      std::string folder;
-      if (worklists.LookupStringValue(folder, "Database") || worklists.LookupStringValue(folder, "Directory"))
+      if (worklists.LookupStringValue(folder_, "Database"))
       {
-        if (worklists.GetBooleanValue("SaveInOrthancDatabase", false))
-        {
-          LOG(ERROR) << "Worklists plugin: you can not set the \"SaveInOrthancDatabase\" configuration to \"true\" once you have configured the \"Directory\" (or former \"Database\") configuration.";
-          return -1;
-        }
-        
-        worklistStorage_ = WorklistStorageType_Folder;
-        worklistDirectory_ = folder; //Orthanc::SystemToolbox::PathFromUtf8(folder);
-        LOG(WARNING) << "The database of worklists will be read from folder: " << folder;
-      }
-      else if (worklists.GetBooleanValue("SaveInOrthancDatabase", false))
-      {
-
-        worklistStorage_ = WorklistStorageType_OrthancDb;
-        ORTHANC_PLUGINS_LOG_WARNING("The database of worklists will be read from Orthanc Database");
+        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.Directory\" must contain a path";
+        ORTHANC_PLUGINS_LOG_ERROR("The configuration option \"Worklists.Database\" must contain a path");
         return -1;
       }
 
-      OrthancPluginRegisterWorklistCallback(OrthancPlugins::GetGlobalContext(), WorklistCallback);
-
       filterIssuerAet_ = worklists.GetBooleanValue("FilterIssuerAet", false);
       limitAnswers_ = worklists.GetUnsignedIntegerValue("LimitAnswers", 0);
-
-      deleteWorklistsOnStableStudy_ = worklists.GetBooleanValue("DeleteWorklistsOnStableStudy", true);
-      hkIntervalInSeconds_ = worklists.GetUnsignedIntegerValue("HousekeepingInterval", 60);
-      deleteDelayInHours_ = worklists.GetUnsignedIntegerValue("DeleteWorklistsDelay", 0);
-      setStudyInstanceUidIfMissing_ = worklists.GetBooleanValue("SetStudyInstanceUidIfMissing", true);
-
-      if (deleteDelayInHours_ > 0 && worklistStorage_ == WorklistStorageType_Folder)
-      {
-        LOG(ERROR) << "Worklists plugin: you can not set the \"DeleteWorklistsDelay\" configuration once you have configured the \"Directory\" (or former \"Database\") configuration.  This feature only works once \"SaveInOrthancDatabase\" is set to true.";
-        return -1;
-      }
-
-      OrthancPluginRegisterOnChangeCallback(OrthancPlugins::GetGlobalContext(), OnChangeCallback);
-
-      OrthancPluginRegisterRestCallback(OrthancPlugins::GetGlobalContext(), "/worklists/create", PostCreateWorklist);
-      OrthancPluginRegisterRestCallback(OrthancPlugins::GetGlobalContext(), "/worklists/([^/]+)", GetPutDeleteWorklist);
-      OrthancPluginRegisterRestCallback(OrthancPlugins::GetGlobalContext(), "/worklists", ListWorklists);
     }
     else
     {
@@ -830,13 +263,6 @@
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
     ORTHANC_PLUGINS_LOG_WARNING("Sample worklist plugin is finalizing");
-
-    worklistHousekeeperThreadShouldStop_ = true;
-    if (worklistHousekeeperThread_.get() != NULL && worklistHousekeeperThread_->joinable())
-    {
-      worklistHousekeeperThread_->join();
-    }
-    worklistHousekeeperThread_.reset(NULL);
   }
 
 
--- a/OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -23,6 +23,8 @@
 
 #include "../Common/OrthancPluginCppWrapper.h"
 
+#include "../../../../OrthancFramework/Sources/Compatibility.h"
+
 #include <boost/thread/mutex.hpp>
 
 
@@ -69,12 +71,12 @@
     return content_;
   }
 
-  virtual bool IsFolder() const
+  virtual bool IsFolder() const ORTHANC_OVERRIDE
   {
     return false;
   }
     
-  virtual Resource* LookupPath(const std::vector<std::string>& path)
+  virtual Resource* LookupPath(const std::vector<std::string>& path) ORTHANC_OVERRIDE
   {
     if (path.empty())
     {
@@ -96,7 +98,7 @@
   Content content_;
 
 public:
-  virtual ~Folder()
+  virtual ~Folder() ORTHANC_OVERRIDE
   {
     for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
     {
@@ -105,12 +107,12 @@
     }
   }
 
-  virtual bool IsFolder() const
+  virtual bool IsFolder() const ORTHANC_OVERRIDE
   {
     return true;
   }
 
-  virtual Resource* LookupPath(const std::vector<std::string>& path)
+  virtual Resource* LookupPath(const std::vector<std::string>& path) ORTHANC_OVERRIDE
   {
     if (path.empty())
     {
@@ -242,7 +244,7 @@
   {
     boost::mutex::scoped_lock lock(mutex_);
     
-    Resource* resource = root_->LookupPath(path);
+    const Resource* resource = root_->LookupPath(path);
     return (resource != NULL &&
             resource->IsFolder());
   }
--- a/OrthancServer/Plugins/Samples/WebSkeleton/Framework/Plugin.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Plugins/Samples/WebSkeleton/Framework/Plugin.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -194,8 +194,8 @@
   }
   else
   {
-    std::string s = "Unknown static resource in plugin: " + std::string(request->groups[0]);
-    OrthancPluginLogError(context, s.c_str());
+    const std::string t = "Unknown static resource in plugin: " + std::string(request->groups[0]);
+    OrthancPluginLogError(context, t.c_str());
     OrthancPluginSendHttpStatusCode(context, output, 404);
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancServer/Resources/RunCppCheck-2.1.sh	Tue Nov 18 17:50:39 2025 +0100
@@ -0,0 +1,111 @@
+#!/bin/bash
+# Note: This script is tuned to run with cppcheck v2.1
+
+set -ex
+
+CPPCHECK=cppcheck
+
+if [ $# -ge 1 ]; then
+    CPPCHECK=$1
+fi
+
+cat <<EOF > /tmp/cppcheck-suppressions.txt
+constParameter:../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp
+knownArgument:../../OrthancFramework/UnitTestsSources/ImageTests.cpp
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp
+nullPointer:../../OrthancFramework/UnitTestsSources/RestApiTests.cpp:322
+stlFindInsert:../../OrthancFramework/Sources/DicomFormat/DicomMap.cpp:1535
+stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:166
+stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:74
+stlFindInsert:../../OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp:65
+stlFindInsert:../../OrthancServer/Sources/OrthancWebDav.cpp:328
+stlFindInsert:../../OrthancServer/Sources/ServerJobs/MergeStudyJob.cpp:41
+stlFindInsert:../../OrthancServer/Sources/ServerJobs/SplitStudyJob.cpp:191
+stlFindInsert:../../OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp:361
+syntaxError:../../OrthancFramework/Sources/SQLite/FunctionContext.h:53
+syntaxError:../../OrthancFramework/UnitTestsSources/DicomMapTests.cpp:74
+syntaxError:../../OrthancFramework/UnitTestsSources/ZipTests.cpp:133
+syntaxError:../../OrthancServer/UnitTestsSources/UnitTestsMain.cpp:325
+unreadVariable:../../OrthancFramework/Sources/FileStorage/StorageAccessor.cpp
+unreadVariable:../../OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp:1173
+useInitializationList:../../OrthancFramework/Sources/Images/PngReader.cpp:91
+useInitializationList:../../OrthancFramework/Sources/Images/PngWriter.cpp:99
+useInitializationList:../../OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp:275
+assertWithSideEffect:../../OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp:277
+assertWithSideEffect:../../OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp:1026
+assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:292
+assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:391
+assertWithSideEffect:../../OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp:3068
+assertWithSideEffect:../../OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp:286
+assertWithSideEffect:../../OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp:454
+EOF
+
+CPPCHECK_BUILD_DIR=/tmp/cppcheck-build-dir-2.1/
+mkdir -p ${CPPCHECK_BUILD_DIR}
+
+${CPPCHECK} -j8 --enable=all --quiet --std=c++11 \
+            --cppcheck-build-dir=${CPPCHECK_BUILD_DIR} \
+            --suppressions-list=/tmp/cppcheck-suppressions.txt \
+            --suppress=unusedFunction \
+            -DBOOST_HAS_DATE_TIME=1 \
+            -DBOOST_HAS_FILESYSTEM_V3=1 \
+            -DBOOST_HAS_REGEX=1 \
+            -DCIVETWEB_HAS_DISABLE_KEEP_ALIVE=1 \
+            -DCIVETWEB_HAS_WEBDAV_WRITING=1 \
+            -DDCMTK_VERSION_NUMBER=365 \
+            -DHAVE_MALLOPT=1 \
+            -DHAVE_MALLOC_TRIM=1 \
+            -DMONGOOSE_USE_CALLBACKS=1 \
+            -DJSONCPP_VERSION_MAJOR=1 \
+            -DJSONCPP_VERSION_MINOR=0 \
+            -DORTHANC_BUILDING_FRAMEWORK_LIBRARY=0 \
+            -DORTHANC_BUILD_UNIT_TESTS=1 \
+            -DORTHANC_ENABLE_BASE64=1 \
+            -DORTHANC_ENABLE_CIVETWEB=1 \
+            -DORTHANC_ENABLE_CURL=1 \
+            -DORTHANC_ENABLE_DCMTK=1 \
+            -DORTHANC_ENABLE_DCMTK_JPEG=1 \
+            -DORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS=1 \
+            -DORTHANC_ENABLE_DCMTK_NETWORKING=1 \
+            -DORTHANC_ENABLE_DCMTK_TRANSCODING=1 \
+            -DORTHANC_ENABLE_JPEG=1 \
+            -DORTHANC_ENABLE_LOCALE=1 \
+            -DORTHANC_ENABLE_LOGGING=1 \
+            -DORTHANC_ENABLE_LOGGING_STDIO=1 \
+            -DORTHANC_ENABLE_LUA=1 \
+            -DORTHANC_ENABLE_MD5=1 \
+            -DORTHANC_ENABLE_MONGOOSE=0 \
+            -DORTHANC_ENABLE_PKCS11=1 \
+            -DORTHANC_ENABLE_PLUGINS=1 \
+            -DORTHANC_ENABLE_PNG=1 \
+            -DORTHANC_ENABLE_PUGIXML=1 \
+            -DORTHANC_ENABLE_SQLITE=1 \
+            -DORTHANC_ENABLE_SSL=1 \
+            -DORTHANC_ENABLE_ZLIB=1 \
+            -DORTHANC_SANDBOXED=0 \
+            -DORTHANC_SQLITE_VERSION=3027001 \
+            -DORTHANC_UNIT_TESTS_LINK_FRAMEWORK=1 \
+            -DPUGIXML_VERSION=150 \
+            -DUNIT_TESTS_WITH_HTTP_CONNEXIONS=1 \
+            -D__BYTE_ORDER=__LITTLE_ENDIAN \
+            -D__GNUC__ \
+            -D__cplusplus=201103 \
+            -D__linux__ \
+            -UNDEBUG \
+            -DHAS_ORTHANC_EXCEPTION=1 \
+            \
+            ../../OrthancFramework/Sources \
+            ../../OrthancFramework/UnitTestsSources \
+            ../../OrthancServer/Plugins/Engine \
+            ../../OrthancServer/Plugins/Include \
+            ../../OrthancServer/Sources \
+            ../../OrthancServer/UnitTestsSources \
+            ../../OrthancServer/Plugins/Samples/Common \
+            ../../OrthancServer/Plugins/Samples/ConnectivityChecks \
+            ../../OrthancServer/Plugins/Samples/DelayedDeletion \
+            ../../OrthancServer/Plugins/Samples/Housekeeper \
+            ../../OrthancServer/Plugins/Samples/ModalityWorklists \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom \
+            ../../OrthancServer/Plugins/Samples/AdoptDicomInstance \
+            \
+            2>&1
--- a/OrthancServer/Resources/RunCppCheck-2.17.0.sh	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Resources/RunCppCheck-2.17.0.sh	Tue Nov 18 17:50:39 2025 +0100
@@ -1,4 +1,5 @@
 #!/bin/bash
+# Note: This script is tuned to run with cppcheck v2.17.0
 
 set -ex
 
@@ -36,7 +37,11 @@
 assertWithSideEffect:../../OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp:454
 EOF
 
-${CPPCHECK} --enable=all --std=gnu++11 --library=boost \
+CPPCHECK_BUILD_DIR=/tmp/cppcheck-build-dir-2.7.0/
+mkdir -p ${CPPCHECK_BUILD_DIR}
+
+${CPPCHECK} -j8 --enable=all --std=gnu++11 --library=boost \
+            --cppcheck-build-dir=${CPPCHECK_BUILD_DIR} \
             --suppressions-list=/tmp/cppcheck-suppressions.txt \
             -I/usr/include/ \
             -I/usr/include/jsoncpp/ \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancServer/Resources/RunCppCheck-2.17.1.sh	Tue Nov 18 17:50:39 2025 +0100
@@ -0,0 +1,147 @@
+#!/bin/bash
+# Note: This script is tuned to run with cppcheck v2.17.1
+
+set -ex
+
+CPPCHECK=cppcheck
+
+if [ $# -ge 1 ]; then
+    CPPCHECK=$1
+fi
+
+cat <<EOF > /tmp/cppcheck-suppressions.txt
+assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:292
+assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:391
+assertWithSideEffect:../../OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp:286
+constParameterCallback:../../OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp:50
+constParameterCallback:../../OrthancFramework/Sources/DicomNetworking/Internals/StoreScp.cpp:112
+constParameterCallback:../../OrthancFramework/Sources/DicomNetworking/Internals/StoreScp.cpp:113
+constParameterCallback:../../OrthancFramework/Sources/Pkcs11.cpp:125
+constParameterCallback:../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp:3489
+constParameterCallback:../../OrthancServer/Sources/OrthancGetRequestHandler.cpp:47
+constParameterPointer:../../OrthancFramework/Sources/Logging.cpp:447
+constParameterPointer:../../OrthancFramework/Sources/Logging.cpp:451
+constParameterPointer:../../OrthancFramework/Sources/Toolbox.cpp:3046
+cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:108
+cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:124
+cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:140
+cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:85
+knownConditionTrueFalse:../../OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp:114
+knownConditionTrueFalse:../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp:425
+knownConditionTrueFalse:../../OrthancFramework/Sources/JobsEngine/Operations/SequenceOfOperationsJob.cpp:345
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2291
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2292
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2293
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2294
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2295
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2296
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2297
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2298
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2299
+knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp:2300
+nullPointer:../../OrthancFramework/UnitTestsSources/RestApiTests.cpp:322
+stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:166
+stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:74
+syntaxError:../../OrthancFramework/Sources/SQLite/FunctionContext.h:53
+syntaxError:../../OrthancFramework/UnitTestsSources/DicomMapTests.cpp:74
+syntaxError:../../OrthancFramework/UnitTestsSources/ZipTests.cpp:133
+syntaxError:../../OrthancServer/UnitTestsSources/UnitTestsMain.cpp:325
+useInitializationList:../../OrthancFramework/Sources/Images/PngReader.cpp:91
+useInitializationList:../../OrthancFramework/Sources/Images/PngWriter.cpp:99
+useInitializationList:../../OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp:275
+variableScope:../../OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp:228
+variableScope:../../OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp:94
+EOF
+
+CPPCHECK_BUILD_DIR=/tmp/cppcheck-build-dir-2.7.1/
+mkdir -p ${CPPCHECK_BUILD_DIR}
+
+${CPPCHECK} -j8 --enable=all --quiet --std=c++11 \
+            --cppcheck-build-dir=${CPPCHECK_BUILD_DIR} \
+            --suppress=unusedFunction \
+            --suppress=missingIncludeSystem \
+            --suppress=missingInclude \
+            --suppress=useStlAlgorithm \
+            --check-level=exhaustive \
+            --suppressions-list=/tmp/cppcheck-suppressions.txt \
+            -DBOOST_HAS_DATE_TIME=1 \
+            -DBOOST_HAS_FILESYSTEM_V3=1 \
+            -DBOOST_HAS_REGEX=1 \
+            -DCIVETWEB_HAS_DISABLE_KEEP_ALIVE=1 \
+            -DCIVETWEB_HAS_WEBDAV_WRITING=1 \
+            -DDCMTK_VERSION_NUMBER=365 \
+            -DHAVE_MALLOPT=1 \
+            -DHAVE_MALLOC_TRIM=1 \
+            -DMONGOOSE_USE_CALLBACKS=1 \
+            -DJSONCPP_VERSION_MAJOR=1 \
+            -DJSONCPP_VERSION_MINOR=0 \
+            -DORTHANC_BUILDING_FRAMEWORK_LIBRARY=0 \
+            -DORTHANC_BUILD_UNIT_TESTS=1 \
+            -DORTHANC_ENABLE_BASE64=1 \
+            -DORTHANC_ENABLE_CIVETWEB=1 \
+            -DORTHANC_ENABLE_CURL=1 \
+            -DORTHANC_ENABLE_DCMTK=1 \
+            -DORTHANC_ENABLE_DCMTK_JPEG=1 \
+            -DORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS=1 \
+            -DORTHANC_ENABLE_DCMTK_NETWORKING=1 \
+            -DORTHANC_ENABLE_DCMTK_TRANSCODING=1 \
+            -DORTHANC_ENABLE_JPEG=1 \
+            -DORTHANC_ENABLE_LOCALE=1 \
+            -DORTHANC_ENABLE_LOGGING=1 \
+            -DORTHANC_ENABLE_LOGGING_STDIO=1 \
+            -DORTHANC_ENABLE_LUA=1 \
+            -DORTHANC_ENABLE_MD5=1 \
+            -DORTHANC_ENABLE_MONGOOSE=0 \
+            -DORTHANC_ENABLE_PKCS11=1 \
+            -DORTHANC_ENABLE_PLUGINS=1 \
+            -DORTHANC_ENABLE_PNG=1 \
+            -DORTHANC_ENABLE_PUGIXML=1 \
+            -DORTHANC_ENABLE_SQLITE=1 \
+            -DORTHANC_ENABLE_SSL=1 \
+            -DORTHANC_ENABLE_ZLIB=1 \
+            -DORTHANC_SANDBOXED=0 \
+            -DORTHANC_SQLITE_VERSION=3027001 \
+            -DORTHANC_UNIT_TESTS_LINK_FRAMEWORK=1 \
+            -DORTHANC_VERSION="\"mainline\"" \
+            -DPUGIXML_VERSION=150 \
+            -DUNIT_TESTS_WITH_HTTP_CONNEXIONS=1 \
+            -D__BYTE_ORDER=__LITTLE_ENDIAN \
+            -D__GNUC__ \
+            -D__cplusplus=201103 \
+            -D__linux__ \
+            -UNDEBUG \
+            -DHAS_ORTHANC_EXCEPTION=1 \
+            \
+            ../../OrthancFramework/Sources \
+            ../../OrthancFramework/UnitTestsSources \
+            ../../OrthancServer/Plugins/Engine \
+            ../../OrthancServer/Plugins/Include \
+            ../../OrthancServer/Sources \
+            ../../OrthancServer/UnitTestsSources \
+            ../../OrthancServer/Plugins/Samples/Common \
+            \
+            ../../OrthancServer/Plugins/Samples/AdoptDicomInstance/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/AutomatedJpeg2kCompression/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp \
+            ../../OrthancServer/Plugins/Samples/ConnectivityChecks/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/CppSkeleton/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/CustomImageDecoder/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/DelayedDeletion/LargeDeleteJob.cpp \
+            ../../OrthancServer/Plugins/Samples/DelayedDeletion/PendingDeletionsDatabase.cpp \
+            ../../OrthancServer/Plugins/Samples/DelayedDeletion/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/Housekeeper/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/ModalityWorklists/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/DicomFilter.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/FindRequestHandler.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/MoveRequestHandler.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/MultitenantDicomServer.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/PluginToolbox.cpp \
+            ../../OrthancServer/Plugins/Samples/MultitenantDicom/StoreRequestHandler.cpp \
+            ../../OrthancServer/Plugins/Samples/Sanitizer/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/StorageArea/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/StorageCommitmentScp/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/WebDavFilesystem/Plugin.cpp \
+            ../../OrthancServer/Plugins/Samples/WebSkeleton/Framework/Plugin.cpp \
+            \
+            2>&1
--- a/OrthancServer/Resources/RunCppCheck.sh	Sat Nov 15 12:28:27 2025 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-#!/bin/bash
-# note: this script was last tuned to run with cppcheck v2.17.1
-set -ex
-
-CPPCHECK=cppcheck
-
-if [ $# -ge 1 ]; then
-    CPPCHECK=$1
-fi
-
-cat <<EOF > /tmp/cppcheck-suppressions.txt
-knownConditionTrueFalse:../../OrthancServer/Plugins/Engine/OrthancPlugins.cpp
-nullPointer:../../OrthancFramework/UnitTestsSources/RestApiTests.cpp:322
-stlFindInsert:../../OrthancFramework/Sources/DicomFormat/DicomMap.cpp:1525
-stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:166
-stlFindInsert:../../OrthancFramework/Sources/RestApi/RestApiCallDocumentation.cpp:74
-syntaxError:../../OrthancFramework/Sources/SQLite/FunctionContext.h:53
-syntaxError:../../OrthancFramework/UnitTestsSources/DicomMapTests.cpp:74
-syntaxError:../../OrthancFramework/UnitTestsSources/ZipTests.cpp:133
-syntaxError:../../OrthancServer/UnitTestsSources/UnitTestsMain.cpp:325
-uninitMemberVar:../../OrthancServer/Sources/ServerJobs/StorageCommitmentScpJob.cpp:419
-useInitializationList:../../OrthancFramework/Sources/Images/PngReader.cpp:91
-useInitializationList:../../OrthancFramework/Sources/Images/PngWriter.cpp:99
-useInitializationList:../../OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp:275
-assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:292
-assertWithSideEffect:../../OrthancServer/Sources/Database/Compatibility/DatabaseLookup.cpp:391
-assertWithSideEffect:../../OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp:286
-variableScope:../../OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp:228
-variableScope:../../OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp:94
-uselessOverride:../../OrthancFramework/Sources/MultiThreading/IRunnableBySteps.h:35
-uselessOverride:../../OrthancFramework/Sources/JobsEngine/SetOfInstancesJob.h:76
-cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:85
-cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:108
-cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:124
-cstyleCast:../../OrthancServer/Plugins/Engine/PluginsManager.cpp:140
-constParameterPointer:../../OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h
-constParameterPointer:../../OrthancFramework/Sources/Logging.cpp:447
-constParameterPointer:../../OrthancFramework/Sources/Logging.cpp:451
-constParameterPointer:../../OrthancFramework/Sources/Toolbox.cpp:3053
-knownConditionTrueFalse:../../OrthancFramework/Sources/DicomNetworking/Internals/CommandDispatcher.cpp:114
-knownConditionTrueFalse:../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.cpp:425
-knownConditionTrueFalse:../../OrthancFramework/Sources/JobsEngine/Operations/SequenceOfOperationsJob.cpp:345
-throwInNoexceptFunction:../../OrthancFramework/Sources/Cache/MemoryStringCache.cpp:121
-throwInNoexceptFunction:../../OrthancFramework/Sources/Cache/MemoryCache.cpp:91
-throwInNoexceptFunction:../../OrthancFramework/Sources/Cache/MemoryObjectCache.cpp:99
-throwInNoexceptFunction:../../OrthancFramework/Sources/MallocMemoryBuffer.h:50
-throwInNoexceptFunction:../../OrthancFramework/Sources/MetricsRegistry.cpp:620
-throwInNoexceptFunction:../../OrthancFramework/Sources/MetricsRegistry.cpp:632
-throwInNoexceptFunction:../../OrthancFramework/Sources/MetricsRegistry.cpp:676
-throwInNoexceptFunction:../../OrthancFramework/Sources/JobsEngine/JobsRegistry.cpp:1296
-throwInNoexceptFunction:../../OrthancServer/Sources/LuaScripting.cpp:830
-throwInNoexceptFunction:../../OrthancServer/Sources/StorageCommitmentReports.cpp:187
-throwInNoexceptFunction:../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h:218
-throwInNoexceptFunction:../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h:376
-throwInNoexceptFunction:../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h:496
-rethrowNoCurrentException:../../OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp
-rethrowNoCurrentException:../../OrthancFramework/UnitTestsSources/RestApiTests.cpp
-constParameterPointer:../../OrthancFramework/Sources/Toolbox.cpp:3046
-constParameterCallback:../../OrthancServer/Sources/OrthancGetRequestHandler.cpp
-constParameterCallback:../../OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp
-constParameterCallback:../../OrthancFramework/Sources/DicomNetworking/Internals/StoreScp.cpp
-constParameterCallback:../../OrthancFramework/Sources/Pkcs11.cpp
-constParameterCallback:../../OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp:3449
-unknownMacro:../../OrthancFramework/Sources/DicomParsing/DicomModification.cpp:39
-EOF
-
-
-${CPPCHECK} -j 8 --enable=all --quiet --std=c++11 \
-            --suppress=missingIncludeSystem \
-            --suppress=missingInclude \
-            --suppress=useStlAlgorithm \
-            --check-level=exhaustive \
-            --suppressions-list=/tmp/cppcheck-suppressions.txt \
-            -DBOOST_HAS_DATE_TIME=1 \
-            -DBOOST_HAS_FILESYSTEM_V3=1 \
-            -DBOOST_HAS_REGEX=1 \
-            -DCIVETWEB_HAS_DISABLE_KEEP_ALIVE=1 \
-            -DCIVETWEB_HAS_WEBDAV_WRITING=1 \
-            -DDCMTK_VERSION_NUMBER=365 \
-            -DHAVE_MALLOPT=1 \
-            -DHAVE_MALLOC_TRIM=1 \
-            -DMONGOOSE_USE_CALLBACKS=1 \
-            -DJSONCPP_VERSION_MAJOR=1 \
-            -DJSONCPP_VERSION_MINOR=0 \
-            -DORTHANC_BUILDING_FRAMEWORK_LIBRARY=0 \
-            -DORTHANC_BUILD_UNIT_TESTS=1 \
-            -DORTHANC_ENABLE_BASE64=1 \
-            -DORTHANC_ENABLE_CIVETWEB=1 \
-            -DORTHANC_ENABLE_CURL=1 \
-            -DORTHANC_ENABLE_DCMTK=1 \
-            -DORTHANC_ENABLE_DCMTK_JPEG=1 \
-            -DORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS=1 \
-            -DORTHANC_ENABLE_DCMTK_NETWORKING=1 \
-            -DORTHANC_ENABLE_DCMTK_TRANSCODING=1 \
-            -DORTHANC_ENABLE_JPEG=1 \
-            -DORTHANC_ENABLE_LOCALE=1 \
-            -DORTHANC_ENABLE_LOGGING=1 \
-            -DORTHANC_ENABLE_LOGGING_STDIO=1 \
-            -DORTHANC_ENABLE_LUA=1 \
-            -DORTHANC_ENABLE_MD5=1 \
-            -DORTHANC_ENABLE_MONGOOSE=0 \
-            -DORTHANC_ENABLE_PKCS11=1 \
-            -DORTHANC_ENABLE_PLUGINS=1 \
-            -DORTHANC_ENABLE_PNG=1 \
-            -DORTHANC_ENABLE_PUGIXML=1 \
-            -DORTHANC_ENABLE_SQLITE=1 \
-            -DORTHANC_ENABLE_SSL=1 \
-            -DORTHANC_ENABLE_ZLIB=1 \
-            -DORTHANC_SANDBOXED=0 \
-            -DORTHANC_SQLITE_VERSION=3027001 \
-            -DORTHANC_UNIT_TESTS_LINK_FRAMEWORK=1 \
-            -DPUGIXML_VERSION=150 \
-            -DUNIT_TESTS_WITH_HTTP_CONNEXIONS=1 \
-            -D__BYTE_ORDER=__LITTLE_ENDIAN \
-            -D__GNUC__ \
-            -D__cplusplus=201103 \
-            -D__linux__ \
-            -UNDEBUG \
-            -DHAS_ORTHANC_EXCEPTION=1 \
-            \
-            ../../OrthancFramework/Sources \
-            ../../OrthancFramework/UnitTestsSources \
-            ../../OrthancServer/Plugins/Engine \
-            ../../OrthancServer/Plugins/Include \
-            ../../OrthancServer/Sources \
-            ../../OrthancServer/UnitTestsSources \
-            ../../OrthancServer/Plugins/Samples/Common \
-            ../../OrthancServer/Plugins/Samples/ConnectivityChecks \
-            ../../OrthancServer/Plugins/Samples/DelayedDeletion \
-            ../../OrthancServer/Plugins/Samples/Housekeeper \
-            ../../OrthancServer/Plugins/Samples/ModalityWorklists \
-            ../../OrthancServer/Plugins/Samples/MultitenantDicom \
-            ../../OrthancServer/Plugins/Samples/AdoptDicomInstance \
-            \
-            2>&1
--- a/OrthancServer/Sources/LuaScripting.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Sources/LuaScripting.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -827,7 +827,16 @@
     if (state_ == State_Running)
     {
       LOG(ERROR) << "INTERNAL ERROR: LuaScripting::Stop() should be invoked manually to avoid mess in the destruction order!";
-      Stop();
+
+      try
+      {
+        Stop();
+      }
+      catch (OrthancException& e)
+      {
+        // Don't throw exceptions in destructors
+        LOG(ERROR) << "Exception in destructor: " << e.What();
+      }
     }
   }
 
--- a/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -380,6 +380,6 @@
     Json::Value publicContent;
     GetPublicContent(publicContent);
 
-    payload.SetContent(ErrorPayloadType_Dimse, publicContent["Details"]);
+    payload.SetContent(ErrorPayloadType_RetrieveJob, publicContent["Details"]);
   }
 }
--- a/OrthancServer/Sources/ServerJobs/StorageCommitmentScpJob.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Sources/ServerJobs/StorageCommitmentScpJob.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -187,7 +187,6 @@
     explicit Unserializer(StorageCommitmentScpJob& that) :
       that_(that)
     {
-      that_.ready_ = false;
     }
 
     virtual ICommand* Unserialize(const Json::Value& source) const ORTHANC_OVERRIDE
@@ -420,9 +419,9 @@
                                                    const Json::Value& serialized) :
     SetOfCommandsJob(new Unserializer(*this), serialized),
     context_(context),
+    ready_(false),
     transactionUid_(SerializationToolbox::ReadString(serialized, TRANSACTION_UID)),
     calledAet_(SerializationToolbox::ReadString(serialized, CALLED_AET))
-    // "ready_" is initialized by the unserializer
   {
     if (serialized.type() != Json::objectValue ||
         !serialized.isMember(REMOTE_MODALITY))
--- a/OrthancServer/Sources/StorageCommitmentReports.cpp	Sat Nov 15 12:28:27 2025 +0100
+++ b/OrthancServer/Sources/StorageCommitmentReports.cpp	Tue Nov 18 17:50:39 2025 +0100
@@ -24,6 +24,7 @@
 #include "PrecompiledHeadersServer.h"
 #include "StorageCommitmentReports.h"
 
+#include "../../OrthancFramework/Sources/Logging.h"
 #include "../../OrthancFramework/Sources/OrthancException.h"
 
 namespace Orthanc
@@ -184,10 +185,18 @@
     while (!content_.IsEmpty())
     {
       Report* report = NULL;
-      content_.RemoveOldest(report);
 
-      assert(report != NULL);
-      delete report;
+      try
+      {
+        content_.RemoveOldest(report);
+        assert(report != NULL);
+        delete report;
+      }
+      catch (OrthancException& e)
+      {
+        // Don't throw exceptions in destructors
+        LOG(ERROR) << "Exception in destructor: " << e.What();
+      }
     }
   }