changeset 2958:bb7a66efbeb1

OrthancPlugins::SetGlobalContext() in OrthancPluginCppWrapper
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Dec 2018 16:31:29 +0100
parents ccf61f6e22ef
children 7364415851ac
files Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Plugins/Samples/Common/OrthancPluginCppWrapper.h Plugins/Samples/ModalityWorklists/Plugin.cpp Plugins/Samples/ServeFolders/Plugin.cpp
diffstat 4 files changed, 335 insertions(+), 380 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Mon Dec 03 17:14:55 2018 +0100
+++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Tue Dec 04 16:31:29 2018 +0100
@@ -39,6 +39,45 @@
 
 namespace OrthancPlugins
 {
+  static OrthancPluginContext* globalContext_ = NULL;
+
+  
+  void SetGlobalContext(OrthancPluginContext* context)
+  {
+    if (context == NULL)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
+    }        
+    else if (globalContext_ == NULL)
+    {
+      globalContext_ = context;
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);      
+    }
+  }
+
+  
+  bool HasGlobalContext()
+  {
+    return globalContext_ != NULL;
+  }
+  
+
+  OrthancPluginContext* GetGlobalContext()
+  {
+    if (globalContext_ == NULL)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);      
+    }
+    else
+    {
+      return globalContext_;
+    }
+  }
+
+
   void MemoryBuffer::Check(OrthancPluginErrorCode code)
   {
     if (code != OrthancPluginErrorCode_Success)
@@ -76,8 +115,7 @@
   }
 
 
-  MemoryBuffer::MemoryBuffer(OrthancPluginContext* context) :
-    context_(context)
+  MemoryBuffer::MemoryBuffer()
   {
     buffer_.data = NULL;
     buffer_.size = 0;
@@ -88,7 +126,7 @@
   {
     if (buffer_.data != NULL)
     {
-      OrthancPluginFreeMemoryBuffer(context_, &buffer_);
+      OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &buffer_);
       buffer_.data = NULL;
       buffer_.size = 0;
     }
@@ -144,7 +182,7 @@
     Json::Reader reader;
     if (!reader.parse(tmp, tmp + buffer_.size, target))
     {
-      OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON");
+      LogError("Cannot convert some memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
@@ -157,11 +195,11 @@
 
     if (applyPlugins)
     {
-      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(context_, &buffer_, uri.c_str()));
+      return CheckHttp(OrthancPluginRestApiGetAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str()));
     }
     else
     {
-      return CheckHttp(OrthancPluginRestApiGet(context_, &buffer_, uri.c_str()));
+      return CheckHttp(OrthancPluginRestApiGet(GetGlobalContext(), &buffer_, uri.c_str()));
     }
   }
 
@@ -175,11 +213,11 @@
 
     if (applyPlugins)
     {
-      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
+      return CheckHttp(OrthancPluginRestApiPostAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
     }
     else
     {
-      return CheckHttp(OrthancPluginRestApiPost(context_, &buffer_, uri.c_str(), body, bodySize));
+      return CheckHttp(OrthancPluginRestApiPost(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
     }
   }
 
@@ -193,11 +231,11 @@
 
     if (applyPlugins)
     {
-      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(context_, &buffer_, uri.c_str(), body, bodySize));
+      return CheckHttp(OrthancPluginRestApiPutAfterPlugins(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
     }
     else
     {
-      return CheckHttp(OrthancPluginRestApiPut(context_, &buffer_, uri.c_str(), body, bodySize));
+      return CheckHttp(OrthancPluginRestApiPut(GetGlobalContext(), &buffer_, uri.c_str(), body, bodySize));
     }
   }
 
@@ -228,7 +266,7 @@
     Json::FastWriter writer;
     std::string s = writer.write(tags);
     
-    Check(OrthancPluginCreateDicom(context_, &buffer_, s.c_str(), NULL, flags));
+    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), NULL, flags));
   }
 
   void MemoryBuffer::CreateDicom(const Json::Value& tags,
@@ -240,21 +278,21 @@
     Json::FastWriter writer;
     std::string s = writer.write(tags);
 
-    Check(OrthancPluginCreateDicom(context_, &buffer_, s.c_str(), pixelData.GetObject(), flags));
+    Check(OrthancPluginCreateDicom(GetGlobalContext(), &buffer_, s.c_str(), pixelData.GetObject(), flags));
   }
 
 
   void MemoryBuffer::ReadFile(const std::string& path)
   {
     Clear();
-    Check(OrthancPluginReadFile(context_, &buffer_, path.c_str()));
+    Check(OrthancPluginReadFile(GetGlobalContext(), &buffer_, path.c_str()));
   }
 
 
   void MemoryBuffer::GetDicomQuery(const OrthancPluginWorklistQuery* query)
   {
     Clear();
-    Check(OrthancPluginWorklistGetDicomQuery(context_, &buffer_, query));
+    Check(OrthancPluginWorklistGetDicomQuery(GetGlobalContext(), &buffer_, query));
   }
 
 
@@ -276,7 +314,7 @@
   {
     if (str_ != NULL)
     {
-      OrthancPluginFreeString(context_, str_);
+      OrthancPluginFreeString(GetGlobalContext(), str_);
       str_ = NULL;
     }
   }
@@ -299,14 +337,14 @@
   {
     if (str_ == NULL)
     {
-      OrthancPluginLogError(context_, "Cannot convert an empty memory buffer to JSON");
+      LogError("Cannot convert an empty memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
     Json::Reader reader;
     if (!reader.parse(str_, target))
     {
-      OrthancPluginLogError(context_, "Cannot convert some memory buffer to JSON");
+      LogError("Cannot convert some memory buffer to JSON");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
   }
@@ -317,8 +355,9 @@
                                  OrthancPluginDicomToJsonFlags flags,
                                  uint32_t maxStringLength)
   {
-    OrthancString str(context_);
-    str.Assign(OrthancPluginDicomBufferToJson(context_, GetData(), GetSize(), format, flags, maxStringLength));
+    OrthancString str;
+    str.Assign(OrthancPluginDicomBufferToJson
+               (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
     str.ToJson(target);
   }
 
@@ -328,7 +367,7 @@
                              const std::string& password)
   {
     Clear();
-    return CheckHttp(OrthancPluginHttpGet(context_, &buffer_, url.c_str(),
+    return CheckHttp(OrthancPluginHttpGet(GetGlobalContext(), &buffer_, url.c_str(),
                                           username.empty() ? NULL : username.c_str(),
                                           password.empty() ? NULL : password.c_str()));
   }
@@ -340,7 +379,7 @@
                               const std::string& password)
   {
     Clear();
-    return CheckHttp(OrthancPluginHttpPost(context_, &buffer_, url.c_str(),
+    return CheckHttp(OrthancPluginHttpPost(GetGlobalContext(), &buffer_, url.c_str(),
                                            body.c_str(), body.size(),
                                            username.empty() ? NULL : username.c_str(),
                                            password.empty() ? NULL : password.c_str()));
@@ -353,7 +392,7 @@
                              const std::string& password)
   {
     Clear();
-    return CheckHttp(OrthancPluginHttpPut(context_, &buffer_, url.c_str(),
+    return CheckHttp(OrthancPluginHttpPut(GetGlobalContext(), &buffer_, url.c_str(),
                                           body.empty() ? NULL : body.c_str(),
                                           body.size(),
                                           username.empty() ? NULL : username.c_str(),
@@ -364,17 +403,16 @@
   void MemoryBuffer::GetDicomInstance(const std::string& instanceId)
   {
     Clear();
-    Check(OrthancPluginGetDicomForInstance(context_, &buffer_, instanceId.c_str()));
+    Check(OrthancPluginGetDicomForInstance(GetGlobalContext(), &buffer_, instanceId.c_str()));
   }
 
   
-  bool HttpDelete(OrthancPluginContext* context_,
-                  const std::string& url,
+  bool HttpDelete(const std::string& url,
                   const std::string& username,
                   const std::string& password)
   {
     OrthancPluginErrorCode error = OrthancPluginHttpDelete
-        (context_, url.c_str(),
+        (GetGlobalContext(), url.c_str(),
          username.empty() ? NULL : username.c_str(),
          password.empty() ? NULL : password.c_str());
 
@@ -394,15 +432,41 @@
   }
   
 
-  OrthancConfiguration::OrthancConfiguration(OrthancPluginContext* context) :
-    context_(context)
+  void LogError(const std::string& message)
+  {
+    if (HasGlobalContext())
+    {
+      OrthancPluginLogError(GetGlobalContext(), message.c_str());
+    }
+  }
+
+  
+  void LogWarning(const std::string& message)
   {
-    OrthancString str(context);
-    str.Assign(OrthancPluginGetConfiguration(context));
+    if (HasGlobalContext())
+    {
+      OrthancPluginLogWarning(GetGlobalContext(), message.c_str());
+    }
+  }
+
+  
+  void LogInfo(const std::string& message)
+  {
+    if (HasGlobalContext())
+    {
+      OrthancPluginLogInfo(GetGlobalContext(), message.c_str());
+    }
+  }
+
+
+  OrthancConfiguration::OrthancConfiguration()
+  {
+    OrthancString str;
+    str.Assign(OrthancPluginGetConfiguration(GetGlobalContext()));
 
     if (str.GetContent() == NULL)
     {
-      OrthancPluginLogError(context, "Cannot access the Orthanc configuration");
+      LogError("Cannot access the Orthanc configuration");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
 
@@ -410,25 +474,12 @@
 
     if (configuration_.type() != Json::objectValue)
     {
-      OrthancPluginLogError(context, "Unable to read the Orthanc configuration");
+      LogError("Unable to read the Orthanc configuration");
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
 
 
-  OrthancPluginContext* OrthancConfiguration::GetContext() const
-  {
-    if (context_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
-    }
-    else
-    {
-      return context_;
-    }
-  }
-
-
   std::string OrthancConfiguration::GetPath(const std::string& key) const
   {
     if (path_.empty())
@@ -456,7 +507,6 @@
   {
     assert(configuration_.type() == Json::objectValue);
 
-    target.context_ = context_;
     target.path_ = GetPath(key);
 
     if (!configuration_.isMember(key))
@@ -467,11 +517,8 @@
     {
       if (configuration_[key].type() != Json::objectValue)
       {
-        if (context_ != NULL)
-        {
-          std::string s = "The configuration section \"" + target.path_ + "\" is not an associative array as expected";
-          OrthancPluginLogError(context_, s.c_str());
-        }
+        LogError("The configuration section \"" + target.path_ +
+                 "\" is not an associative array as expected");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
       }
@@ -493,11 +540,8 @@
 
     if (configuration_[key].type() != Json::stringValue)
     {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a string as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not a string as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -528,11 +572,8 @@
       return true;
 
     default:
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not an integer as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -550,11 +591,8 @@
 
     if (tmp < 0)
     {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a positive integer as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not a positive integer as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -578,11 +616,8 @@
 
     if (configuration_[key].type() != Json::booleanValue)
     {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a Boolean as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not a Boolean as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -617,11 +652,8 @@
       return true;
 
     default:
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not an integer as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not an integer as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -680,12 +712,8 @@
       break;
     }
 
-    if (context_ != NULL)
-    {
-      std::string s = ("The configuration option \"" + GetPath(key) +
-                       "\" is not a list of strings as expected");
-      OrthancPluginLogError(context_, s.c_str());
-    }
+    LogError("The configuration option \"" + GetPath(key) +
+             "\" is not a list of strings as expected");
 
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
@@ -805,11 +833,8 @@
 
     if (configuration_[key].type() != Json::objectValue)
     {
-      if (context_ != NULL)
-      {
-        std::string s = "The configuration option \"" + GetPath(key) + "\" is not a string as expected";
-        OrthancPluginLogError(context_, s.c_str());
-      }
+      LogError("The configuration option \"" + GetPath(key) +
+               "\" is not a string as expected");
 
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -826,11 +851,8 @@
       }
       else
       {
-        if (context_ != NULL)
-        {
-          std::string s = "The configuration option \"" + GetPath(key) + "\" is not a dictionary mapping strings to strings";
-          OrthancPluginLogError(context_, s.c_str());
-        }
+        LogError("The configuration option \"" + GetPath(key) +
+                 "\" is not a dictionary mapping strings to strings");
 
         ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
       }
@@ -842,7 +864,7 @@
   {
     if (image_ != NULL)
     {
-      OrthancPluginFreeImage(context_, image_);
+      OrthancPluginFreeImage(GetGlobalContext(), image_);
       image_ = NULL;
     }
   }
@@ -852,66 +874,51 @@
   {
     if (image_ == NULL)
     {
-      OrthancPluginLogError(context_, "Trying to access a NULL image");
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-  }
-
-
-  OrthancImage::OrthancImage(OrthancPluginContext*  context) :
-    context_(context),
-    image_(NULL)
-  {
-    if (context == NULL)
-    {
+      LogError("Trying to access a NULL image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
 
 
-  OrthancImage::OrthancImage(OrthancPluginContext*  context,
-                             OrthancPluginImage*    image) :
-    context_(context),
+  OrthancImage::OrthancImage() :
+    image_(NULL)
+  {
+  }
+
+
+  OrthancImage::OrthancImage(OrthancPluginImage*  image) :
     image_(image)
   {
-    if (context == NULL)
+  }
+  
+
+  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
+                             uint32_t                  width,
+                             uint32_t                  height)
+  {
+    image_ = OrthancPluginCreateImage(GetGlobalContext(), format, width, height);
+
+    if (image_ == NULL)
     {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
+      LogError("Cannot create an image");
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
   
 
-  OrthancImage::OrthancImage(OrthancPluginContext*     context,
-                             OrthancPluginPixelFormat  format,
-                             uint32_t                  width,
-                             uint32_t                  height) :
-    context_(context)
-  {
-    if (context == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-    else
-    {
-      image_ = OrthancPluginCreateImage(context, format, width, height);
-    }
-  }
-
-  OrthancImage::OrthancImage(OrthancPluginContext*     context,
-                             OrthancPluginPixelFormat  format,
+  OrthancImage::OrthancImage(OrthancPluginPixelFormat  format,
                              uint32_t                  width,
                              uint32_t                  height,
                              uint32_t                  pitch,
-                             void*                     buffer) :
-    context_(context)
+                             void*                     buffer)
   {
-    if (context == NULL)
+    image_ = OrthancPluginCreateImageAccessor
+      (GetGlobalContext(), format, width, height, pitch, buffer);
+
+    if (image_ == NULL)
     {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
-    }
-    else
-    {
-      image_ = OrthancPluginCreateImageAccessor(context, format, width, height, pitch, buffer);
+      LogError("Cannot create an image accessor");
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
     }
   }
 
@@ -919,10 +926,12 @@
                                         size_t size)
   {
     Clear();
-    image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Png);
+    
+    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Png);
+
     if (image_ == NULL)
     {
-      OrthancPluginLogError(context_, "Cannot uncompress a PNG image");
+      LogError("Cannot uncompress a PNG image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -932,10 +941,10 @@
                                          size_t size)
   {
     Clear();
-    image_ = OrthancPluginUncompressImage(context_, data, size, OrthancPluginImageFormat_Jpeg);
+    image_ = OrthancPluginUncompressImage(GetGlobalContext(), data, size, OrthancPluginImageFormat_Jpeg);
     if (image_ == NULL)
     {
-      OrthancPluginLogError(context_, "Cannot uncompress a JPEG image");
+      LogError("Cannot uncompress a JPEG image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -946,10 +955,10 @@
                                       unsigned int frame)
   {
     Clear();
-    image_ = OrthancPluginDecodeDicomImage(context_, data, size, frame);
+    image_ = OrthancPluginDecodeDicomImage(GetGlobalContext(), data, size, frame);
     if (image_ == NULL)
     {
-      OrthancPluginLogError(context_, "Cannot uncompress a DICOM image");
+      LogError("Cannot uncompress a DICOM image");
       ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
     }
   }
@@ -958,35 +967,35 @@
   OrthancPluginPixelFormat OrthancImage::GetPixelFormat()
   {
     CheckImageAvailable();
-    return OrthancPluginGetImagePixelFormat(context_, image_);
+    return OrthancPluginGetImagePixelFormat(GetGlobalContext(), image_);
   }
 
 
   unsigned int OrthancImage::GetWidth()
   {
     CheckImageAvailable();
-    return OrthancPluginGetImageWidth(context_, image_);
+    return OrthancPluginGetImageWidth(GetGlobalContext(), image_);
   }
 
 
   unsigned int OrthancImage::GetHeight()
   {
     CheckImageAvailable();
-    return OrthancPluginGetImageHeight(context_, image_);
+    return OrthancPluginGetImageHeight(GetGlobalContext(), image_);
   }
 
 
   unsigned int OrthancImage::GetPitch()
   {
     CheckImageAvailable();
-    return OrthancPluginGetImagePitch(context_, image_);
+    return OrthancPluginGetImagePitch(GetGlobalContext(), image_);
   }
 
 
   const void* OrthancImage::GetBuffer()
   {
     CheckImageAvailable();
-    return OrthancPluginGetImageBuffer(context_, image_);
+    return OrthancPluginGetImageBuffer(GetGlobalContext(), image_);
   }
 
 
@@ -995,7 +1004,7 @@
     CheckImageAvailable();
     
     OrthancPluginMemoryBuffer tmp;
-    OrthancPluginCompressPngImage(context_, &tmp, GetPixelFormat(),
+    OrthancPluginCompressPngImage(GetGlobalContext(), &tmp, GetPixelFormat(),
                                   GetWidth(), GetHeight(), GetPitch(), GetBuffer());
 
     target.Assign(tmp);
@@ -1008,7 +1017,7 @@
     CheckImageAvailable();
     
     OrthancPluginMemoryBuffer tmp;
-    OrthancPluginCompressJpegImage(context_, &tmp, GetPixelFormat(),
+    OrthancPluginCompressJpegImage(GetGlobalContext(), &tmp, GetPixelFormat(),
                                    GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
     
     target.Assign(tmp);
@@ -1018,7 +1027,7 @@
   void OrthancImage::AnswerPngImage(OrthancPluginRestOutput* output)
   {
     CheckImageAvailable();
-    OrthancPluginCompressAndAnswerPngImage(context_, output, GetPixelFormat(),
+    OrthancPluginCompressAndAnswerPngImage(GetGlobalContext(), output, GetPixelFormat(),
                                            GetWidth(), GetHeight(), GetPitch(), GetBuffer());
   }
 
@@ -1027,16 +1036,14 @@
                                      uint8_t quality)
   {
     CheckImageAvailable();
-    OrthancPluginCompressAndAnswerJpegImage(context_, output, GetPixelFormat(),
+    OrthancPluginCompressAndAnswerJpegImage(GetGlobalContext(), output, GetPixelFormat(),
                                             GetWidth(), GetHeight(), GetPitch(), GetBuffer(), quality);
   }
 
 
 
 #if HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1
-  FindMatcher::FindMatcher(OrthancPluginContext*              context,
-                           const OrthancPluginWorklistQuery*  worklist) :
-    context_(context),
+  FindMatcher::FindMatcher(const OrthancPluginWorklistQuery* worklist) :
     matcher_(NULL),
     worklist_(worklist)
   {
@@ -1047,14 +1054,12 @@
   }
 
 
-  void FindMatcher::SetupDicom(OrthancPluginContext*  context,
-                               const void*            query,
-                               uint32_t               size)
+  void FindMatcher::SetupDicom(const void*  query,
+                               uint32_t     size)
   {
-    context_ = context;
     worklist_ = NULL;
 
-    matcher_ = OrthancPluginCreateFindMatcher(context_, query, size);
+    matcher_ = OrthancPluginCreateFindMatcher(GetGlobalContext(), query, size);
     if (matcher_ == NULL)
     {
       ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
@@ -1068,7 +1073,7 @@
 
     if (matcher_ != NULL)
     {
-      OrthancPluginFreeFindMatcher(context_, matcher_);
+      OrthancPluginFreeFindMatcher(GetGlobalContext(), matcher_);
     }
   }
 
@@ -1081,11 +1086,11 @@
 
     if (matcher_ != NULL)
     {
-      result = OrthancPluginFindMatcherIsMatch(context_, matcher_, dicom, size);
+      result = OrthancPluginFindMatcherIsMatch(GetGlobalContext(), matcher_, dicom, size);
     }
     else if (worklist_ != NULL)
     {
-      result = OrthancPluginWorklistIsMatch(context_, worklist_, dicom, size);
+      result = OrthancPluginWorklistIsMatch(GetGlobalContext(), worklist_, dicom, size);
     }
     else
     {
@@ -1110,11 +1115,11 @@
 
 
   bool RestApiGet(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   bool applyPlugins)
   {
-    MemoryBuffer answer(context);
+    MemoryBuffer answer;
+    
     if (!answer.RestApiGet(uri, applyPlugins))
     {
       return false;
@@ -1128,13 +1133,13 @@
 
 
   bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
                    const std::string& uri,
                    const char* body,
                    size_t bodySize,
                    bool applyPlugins)
   {
-    MemoryBuffer answer(context);
+    MemoryBuffer answer;
+    
     if (!answer.RestApiPost(uri, body, bodySize, applyPlugins))
     {
       return false;
@@ -1148,24 +1153,23 @@
 
 
   bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
                    const std::string& uri,
                    const Json::Value& body,
                    bool applyPlugins)
   {
     Json::FastWriter writer;
-    return RestApiPost(result, context, uri, writer.write(body), applyPlugins);
+    return RestApiPost(result, uri, writer.write(body), applyPlugins);
   }
 
 
   bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   const char* body,
                   size_t bodySize,
                   bool applyPlugins)
   {
-    MemoryBuffer answer(context);
+    MemoryBuffer answer;
+    
     if (!answer.RestApiPut(uri, body, bodySize, applyPlugins))
     {
       return false;
@@ -1179,29 +1183,27 @@
 
 
   bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   const Json::Value& body,
                   bool applyPlugins)
   {
     Json::FastWriter writer;
-    return RestApiPut(result, context, uri, writer.write(body), applyPlugins);
+    return RestApiPut(result, uri, writer.write(body), applyPlugins);
   }
 
 
-  bool RestApiDelete(OrthancPluginContext* context,
-                     const std::string& uri,
+  bool RestApiDelete(const std::string& uri,
                      bool applyPlugins)
   {
     OrthancPluginErrorCode error;
 
     if (applyPlugins)
     {
-      error = OrthancPluginRestApiDeleteAfterPlugins(context, uri.c_str());
+      error = OrthancPluginRestApiDeleteAfterPlugins(GetGlobalContext(), uri.c_str());
     }
     else
     {
-      error = OrthancPluginRestApiDelete(context, uri.c_str());
+      error = OrthancPluginRestApiDelete(GetGlobalContext(), uri.c_str());
     }
 
     if (error == OrthancPluginErrorCode_Success)
@@ -1220,35 +1222,31 @@
   }
 
 
-  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
-                                   unsigned int major,
+  void ReportMinimalOrthancVersion(unsigned int major,
                                    unsigned int minor,
                                    unsigned int revision)
   {
-    std::string s = ("Your version of the Orthanc core (" +
-                     std::string(context->orthancVersion) +
-                     ") is too old to run this plugin (version " +
-                     boost::lexical_cast<std::string>(major) + "." +
-                     boost::lexical_cast<std::string>(minor) + "." +
-                     boost::lexical_cast<std::string>(revision) +
-                     " is required)");
-    
-    OrthancPluginLogError(context, s.c_str());
+    LogError("Your version of the Orthanc core (" +
+             std::string(GetGlobalContext()->orthancVersion) +
+             ") is too old to run this plugin (version " +
+             boost::lexical_cast<std::string>(major) + "." +
+             boost::lexical_cast<std::string>(minor) + "." +
+             boost::lexical_cast<std::string>(revision) +
+             " is required)");
   }
 
 
-  bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
-                                  unsigned int major,
+  bool CheckMinimalOrthancVersion(unsigned int major,
                                   unsigned int minor,
                                   unsigned int revision)
   {
-    if (context == NULL)
+    if (!HasGlobalContext())
     {
-      OrthancPluginLogError(context, "Bad Orthanc context in the plugin");
+      LogError("Bad Orthanc context in the plugin");
       return false;
     }
 
-    if (!strcmp(context->orthancVersion, "mainline"))
+    if (!strcmp(GetGlobalContext()->orthancVersion, "mainline"))
     {
       // Assume compatibility with the mainline
       return true;
@@ -1262,7 +1260,7 @@
     #else
         sscanf
     #endif
-        (context->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
+        (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 ||
         aa < 0 ||
         bb < 0 ||
         cc < 0)
@@ -1326,38 +1324,31 @@
     }
     else
     {
-      std::string s = "Inexistent peer: " + name;
-      OrthancPluginLogError(context_, s.c_str());
+      LogError("Inexistent peer: " + name);
       ORTHANC_PLUGINS_THROW_EXCEPTION(UnknownResource);
     }
   }
 
 
-  OrthancPeers::OrthancPeers(OrthancPluginContext* context) :
-    context_(context),
+  OrthancPeers::OrthancPeers() :
     peers_(NULL),
     timeout_(0)
   {
-    if (context_ == NULL)
-    {
-      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer);
-    }
-
-    peers_ = OrthancPluginGetPeers(context_);
+    peers_ = OrthancPluginGetPeers(GetGlobalContext());
 
     if (peers_ == NULL)
     {
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
 
-    uint32_t count = OrthancPluginGetPeersCount(context_, peers_);
+    uint32_t count = OrthancPluginGetPeersCount(GetGlobalContext(), peers_);
 
     for (uint32_t i = 0; i < count; i++)
     {
-      const char* name = OrthancPluginGetPeerName(context_, peers_, i);
+      const char* name = OrthancPluginGetPeerName(GetGlobalContext(), peers_, i);
       if (name == NULL)
       {
-        OrthancPluginFreePeers(context_, peers_);
+        OrthancPluginFreePeers(GetGlobalContext(), peers_);
         ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
       }
 
@@ -1370,7 +1361,7 @@
   {
     if (peers_ != NULL)
     {
-      OrthancPluginFreePeers(context_, peers_);
+      OrthancPluginFreePeers(GetGlobalContext(), peers_);
     }
   }
 
@@ -1400,7 +1391,7 @@
     }
     else
     {
-      const char* s = OrthancPluginGetPeerName(context_, peers_, static_cast<uint32_t>(index));
+      const char* s = OrthancPluginGetPeerName(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
       if (s == NULL)
       {
         ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
@@ -1421,7 +1412,7 @@
     }
     else
     {
-      const char* s = OrthancPluginGetPeerUrl(context_, peers_, static_cast<uint32_t>(index));
+      const char* s = OrthancPluginGetPeerUrl(GetGlobalContext(), peers_, static_cast<uint32_t>(index));
       if (s == NULL)
       {
         ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
@@ -1450,7 +1441,7 @@
     }
     else
     {
-      const char* s = OrthancPluginGetPeerUserProperty(context_, peers_, static_cast<uint32_t>(index), key.c_str());
+      const char* s = OrthancPluginGetPeerUserProperty(GetGlobalContext(), peers_, static_cast<uint32_t>(index), key.c_str());
       if (s == NULL)
       {
         return false;
@@ -1484,7 +1475,7 @@
     OrthancPluginMemoryBuffer answer;
     uint16_t status;
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-        (context_, &answer, NULL, &status, peers_,
+        (GetGlobalContext(), &answer, NULL, &status, peers_,
          static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
          0, NULL, NULL, NULL, 0, timeout_);
 
@@ -1514,7 +1505,7 @@
                            size_t index,
                            const std::string& uri) const
   {
-    MemoryBuffer buffer(context_);
+    MemoryBuffer buffer;
 
     if (DoGet(buffer, index, uri))
     {
@@ -1532,7 +1523,7 @@
                            const std::string& name,
                            const std::string& uri) const
   {
-    MemoryBuffer buffer(context_);
+    MemoryBuffer buffer;
 
     if (DoGet(buffer, name, uri))
     {
@@ -1562,7 +1553,7 @@
                             const std::string& uri,
                             const std::string& body) const
   {
-    MemoryBuffer buffer(context_);
+    MemoryBuffer buffer;
 
     if (DoPost(buffer, index, uri, body))
     {
@@ -1581,7 +1572,7 @@
                             const std::string& uri,
                             const std::string& body) const
   {
-    MemoryBuffer buffer(context_);
+    MemoryBuffer buffer;
 
     if (DoPost(buffer, name, uri, body))
     {
@@ -1608,7 +1599,7 @@
     OrthancPluginMemoryBuffer answer;
     uint16_t status;
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-        (context_, &answer, NULL, &status, peers_,
+        (GetGlobalContext(), &answer, NULL, &status, peers_,
          static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
          0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
 
@@ -1636,13 +1627,13 @@
     OrthancPluginMemoryBuffer answer;
     uint16_t status;
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-        (context_, &answer, NULL, &status, peers_,
+        (GetGlobalContext(), &answer, NULL, &status, peers_,
          static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
          0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
-      OrthancPluginFreeMemoryBuffer(context_, &answer);
+      OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
       return (status == 200);
     }
     else
@@ -1673,13 +1664,13 @@
     OrthancPluginMemoryBuffer answer;
     uint16_t status;
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-        (context_, &answer, NULL, &status, peers_,
+        (GetGlobalContext(), &answer, NULL, &status, peers_,
          static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
          0, NULL, NULL, NULL, 0, timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
-      OrthancPluginFreeMemoryBuffer(context_, &answer);
+      OrthancPluginFreeMemoryBuffer(GetGlobalContext(), &answer);
       return (status == 200);
     }
     else
@@ -1888,8 +1879,7 @@
   }
 
 
-  OrthancPluginJob* OrthancJob::Create(OrthancPluginContext* context,
-                                       OrthancJob* job)
+  OrthancPluginJob* OrthancJob::Create(OrthancJob* job)
   {
     if (job == NULL)
     {
@@ -1897,9 +1887,9 @@
     }
 
     OrthancPluginJob* orthanc = OrthancPluginCreateJob(
-          context, job, CallbackFinalize, job->jobType_.c_str(),
-          CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
-          CallbackStep, CallbackStop, CallbackReset);
+      GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(),
+      CallbackGetProgress, CallbackGetContent, CallbackGetSerialized,
+      CallbackStep, CallbackStop, CallbackReset);
 
     if (orthanc == NULL)
     {
@@ -1912,25 +1902,24 @@
   }
 
   
-  std::string OrthancJob::Submit(OrthancPluginContext* context,
-                                 OrthancJob* job,
+  std::string OrthancJob::Submit(OrthancJob* job,
                                  int priority)
   {
-    OrthancPluginJob* orthanc = Create(context, job);
+    OrthancPluginJob* orthanc = Create(job);
     
-    char* id = OrthancPluginSubmitJob(context, orthanc, priority);
+    char* id = OrthancPluginSubmitJob(GetGlobalContext(), orthanc, priority);
 
     if (id == NULL)
     {
-      OrthancPluginLogError(context, "Plugin cannot submit job");
-      OrthancPluginFreeJob(context, orthanc);
+      LogError("Plugin cannot submit job");
+      OrthancPluginFreeJob(GetGlobalContext(), orthanc);
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin);
     }
     else
     {
       std::string tmp(id);
       tmp.assign(id);
-      OrthancPluginFreeString(context, id);
+      OrthancPluginFreeString(GetGlobalContext(), id);
 
       return tmp;
     }
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Mon Dec 03 17:14:55 2018 +0100
+++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Dec 04 16:31:29 2018 +0100
@@ -79,13 +79,20 @@
                                 const char* url,
                                 const OrthancPluginHttpRequest* request);
 
+
+  void SetGlobalContext(OrthancPluginContext* context);
+
+  bool HasGlobalContext();
+
+  OrthancPluginContext* GetGlobalContext();
+
+  
   class OrthancImage;
 
 
   class MemoryBuffer : public boost::noncopyable
   {
   private:
-    OrthancPluginContext*      context_;
     OrthancPluginMemoryBuffer  buffer_;
 
     void Check(OrthancPluginErrorCode code);
@@ -93,7 +100,7 @@
     bool CheckHttp(OrthancPluginErrorCode code);
 
   public:
-    MemoryBuffer(OrthancPluginContext* context);
+    MemoryBuffer();
 
     ~MemoryBuffer()
     {
@@ -205,14 +212,12 @@
   class OrthancString : public boost::noncopyable
   {
   private:
-    OrthancPluginContext*  context_;
-    char*                  str_;
+    char*   str_;
 
     void Clear();
 
   public:
-    OrthancString(OrthancPluginContext* context) :
-      context_(context),
+    OrthancString() :
       str_(NULL)
     {
     }
@@ -240,20 +245,13 @@
   class OrthancConfiguration : public boost::noncopyable
   {
   private:
-    OrthancPluginContext*  context_;
-    Json::Value            configuration_;  // Necessarily a Json::objectValue
-    std::string            path_;
+    Json::Value  configuration_;  // Necessarily a Json::objectValue
+    std::string  path_;
 
     std::string GetPath(const std::string& key) const;
 
   public:
-    OrthancConfiguration() : context_(NULL)
-    {
-    }
-
-    OrthancConfiguration(OrthancPluginContext* context);
-
-    OrthancPluginContext* GetContext() const;
+    OrthancConfiguration();
 
     const Json::Value& GetJson() const
     {
@@ -310,7 +308,6 @@
   class OrthancImage : public boost::noncopyable
   {
   private:
-    OrthancPluginContext*  context_;
     OrthancPluginImage*    image_;
 
     void Clear();
@@ -318,18 +315,15 @@
     void CheckImageAvailable();
 
   public:
-    OrthancImage(OrthancPluginContext*  context);
+    OrthancImage();
 
-    OrthancImage(OrthancPluginContext*  context,
-                 OrthancPluginImage*    image);
+    OrthancImage(OrthancPluginImage*    image);
 
-    OrthancImage(OrthancPluginContext*     context,
-                 OrthancPluginPixelFormat  format,
+    OrthancImage(OrthancPluginPixelFormat  format,
                  uint32_t                  width,
                  uint32_t                  height);
 
-    OrthancImage(OrthancPluginContext*     context,
-                 OrthancPluginPixelFormat  format,
+    OrthancImage(OrthancPluginPixelFormat  format,
                  uint32_t                  width,
                  uint32_t                  height,
                  uint32_t                  pitch,
@@ -382,29 +376,24 @@
   class FindMatcher : public boost::noncopyable
   {
   private:
-    OrthancPluginContext*              context_;
     OrthancPluginFindMatcher*          matcher_;
     const OrthancPluginWorklistQuery*  worklist_;
 
-    void SetupDicom(OrthancPluginContext*  context,
-                    const void*            query,
+    void SetupDicom(const void*            query,
                     uint32_t               size);
 
   public:
-    FindMatcher(OrthancPluginContext*              context,
-                const OrthancPluginWorklistQuery*  worklist);
+    FindMatcher(const OrthancPluginWorklistQuery*  worklist);
 
-    FindMatcher(OrthancPluginContext*  context,
-                const void*            query,
+    FindMatcher(const void*            query,
                 uint32_t               size)
     {
-      SetupDicom(context, query, size);
+      SetupDicom(query, size);
     }
 
-    FindMatcher(OrthancPluginContext*  context,
-                const MemoryBuffer&    dicom)
+    FindMatcher(const MemoryBuffer&    dicom)
     {
-      SetupDicom(context, dicom.GetData(), dicom.GetSize());
+      SetupDicom(dicom.GetData(), dicom.GetSize());
     }
 
     ~FindMatcher();
@@ -421,99 +410,67 @@
 
 
   bool RestApiGet(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   bool applyPlugins);
 
   bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
                    const std::string& uri,
                    const char* body,
                    size_t bodySize,
                    bool applyPlugins);
 
   bool RestApiPost(Json::Value& result,
-                   OrthancPluginContext* context,
                    const std::string& uri,
                    const Json::Value& body,
                    bool applyPlugins);
 
   inline bool RestApiPost(Json::Value& result,
-                          OrthancPluginContext* context,
                           const std::string& uri,
                           const std::string& body,
                           bool applyPlugins)
   {
-    return RestApiPost(result, context, uri, body.empty() ? NULL : body.c_str(), 
+    return RestApiPost(result, uri, body.empty() ? NULL : body.c_str(), 
                        body.size(), applyPlugins);
   }
 
   bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   const char* body,
                   size_t bodySize,
                   bool applyPlugins);
 
   bool RestApiPut(Json::Value& result,
-                  OrthancPluginContext* context,
                   const std::string& uri,
                   const Json::Value& body,
                   bool applyPlugins);
 
   inline bool RestApiPut(Json::Value& result,
-                         OrthancPluginContext* context,
                          const std::string& uri,
                          const std::string& body,
                          bool applyPlugins)
   {
-    return RestApiPut(result, context, uri, body.empty() ? NULL : body.c_str(), 
+    return RestApiPut(result, uri, body.empty() ? NULL : body.c_str(), 
                       body.size(), applyPlugins);
   }
 
-  bool RestApiDelete(OrthancPluginContext* context,
-                     const std::string& uri,
+  bool RestApiDelete(const std::string& uri,
                      bool applyPlugins);
 
-  bool HttpDelete(OrthancPluginContext* context,
-                  const std::string& url,
+  bool HttpDelete(const std::string& url,
                   const std::string& username,
                   const std::string& password);
 
-  inline void LogError(OrthancPluginContext* context,
-                       const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogError(context, message.c_str());
-    }
-  }
+  void LogError(const std::string& message);
+
+  void LogWarning(const std::string& message);
 
-  inline void LogWarning(OrthancPluginContext* context,
-                         const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogWarning(context, message.c_str());
-    }
-  }
+  void LogInfo(const std::string& message);
 
-  inline void LogInfo(OrthancPluginContext* context,
-                      const std::string& message)
-  {
-    if (context != NULL)
-    {
-      OrthancPluginLogInfo(context, message.c_str());
-    }
-  }
-
-  void ReportMinimalOrthancVersion(OrthancPluginContext* context,
-                                   unsigned int major,
+  void ReportMinimalOrthancVersion(unsigned int major,
                                    unsigned int minor,
                                    unsigned int revision);
   
-  bool CheckMinimalOrthancVersion(OrthancPluginContext* context,
-                                  unsigned int major,
+  bool CheckMinimalOrthancVersion(unsigned int major,
                                   unsigned int minor,
                                   unsigned int revision);
 
@@ -532,6 +489,14 @@
       }
       catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
       {
+#if HAS_ORTHANC_EXCEPTION == 1
+        if (HasGlobalContext() &&
+            e.HasDetails())
+        {
+          OrthancPluginSetHttpErrorDetails(GetGlobalContext(), output, e.GetDetails());
+        }
+#endif
+
         return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
       }
       catch (boost::bad_lexical_cast&)
@@ -547,17 +512,18 @@
 
   
   template <RestCallback Callback>
-  void RegisterRestCallback(OrthancPluginContext* context,
-                            const std::string& uri,
+  void RegisterRestCallback(const std::string& uri,
                             bool isThreadSafe)
   {
     if (isThreadSafe)
     {
-      OrthancPluginRegisterRestCallbackNoLock(context, uri.c_str(), Internals::Protect<Callback>);
+      OrthancPluginRegisterRestCallbackNoLock
+        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
     }
     else
     {
-      OrthancPluginRegisterRestCallback(context, uri.c_str(), Internals::Protect<Callback>);
+      OrthancPluginRegisterRestCallback
+        (GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>);
     }
   }
 
@@ -568,7 +534,6 @@
   private:
     typedef std::map<std::string, uint32_t>   Index;
 
-    OrthancPluginContext *context_;
     OrthancPluginPeers   *peers_;
     Index                 index_;
     uint32_t              timeout_;
@@ -576,7 +541,7 @@
     size_t GetPeerIndex(const std::string& name) const;
 
   public:
-    OrthancPeers(OrthancPluginContext* context);
+    OrthancPeers();
 
     ~OrthancPeers();
 
@@ -715,11 +680,9 @@
     
     virtual void Reset() = 0;
 
-    static OrthancPluginJob* Create(OrthancPluginContext* context,
-                                    OrthancJob* job /* takes ownership */);
+    static OrthancPluginJob* Create(OrthancJob* job /* takes ownership */);
 
-    static std::string Submit(OrthancPluginContext* context,
-                              OrthancJob* job /* takes ownership */,
+    static std::string Submit(OrthancJob* job /* takes ownership */,
                               int priority);
   };
 #endif
--- a/Plugins/Samples/ModalityWorklists/Plugin.cpp	Mon Dec 03 17:14:55 2018 +0100
+++ b/Plugins/Samples/ModalityWorklists/Plugin.cpp	Tue Dec 04 16:31:29 2018 +0100
@@ -28,7 +28,6 @@
 #include <iostream>
 #include <algorithm>
 
-static OrthancPluginContext* context_ = NULL;
 static std::string folder_;
 static bool filterIssuerAet_ = false;
 
@@ -40,18 +39,18 @@
                            const OrthancPlugins::FindMatcher& matcher,
                            const std::string& path)
 {
-  OrthancPlugins::MemoryBuffer dicom(context_);
+  OrthancPlugins::MemoryBuffer dicom;
   dicom.ReadFile(path);
 
   if (matcher.IsMatch(dicom))
   {
     // This DICOM file matches the worklist query, add it to the answers
     OrthancPluginErrorCode code = OrthancPluginWorklistAddAnswer
-      (context_, answers, query, dicom.GetData(), dicom.GetSize());
+      (OrthancPlugins::GetGlobalContext(), answers, query, dicom.GetData(), dicom.GetSize());
 
     if (code != OrthancPluginErrorCode_Success)
     {
-      OrthancPlugins::LogError(context_, "Error while adding an answer to a worklist request");
+      OrthancPlugins::LogError("Error while adding an answer to a worklist request");
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
     }
 
@@ -66,7 +65,7 @@
                                                   const char*                       issuerAet)
 {
   // Extract the DICOM instance underlying the C-Find query
-  OrthancPlugins::MemoryBuffer dicom(context_);
+  OrthancPlugins::MemoryBuffer dicom;
   dicom.GetDicomQuery(query);
 
   // Convert the DICOM as JSON, and dump it to the user in "--verbose" mode
@@ -74,12 +73,12 @@
   dicom.DicomToJson(json, OrthancPluginDicomToJsonFormat_Short,
                     static_cast<OrthancPluginDicomToJsonFlags>(0), 0);
 
-  OrthancPlugins::LogInfo(context_, "Received worklist query from remote modality " +
+  OrthancPlugins::LogInfo("Received worklist query from remote modality " +
                           std::string(issuerAet) + ":\n" + json.toStyledString());
 
   if (!filterIssuerAet_)
   {
-    return new OrthancPlugins::FindMatcher(context_, query);
+    return new OrthancPlugins::FindMatcher(query);
   }
   else
   {
@@ -126,9 +125,10 @@
     }
 
     // Encode the modified JSON as a DICOM instance, then convert it to a C-Find matcher
-    OrthancPlugins::MemoryBuffer modified(context_);
+    OrthancPlugins::MemoryBuffer modified;
     modified.CreateDicom(json, OrthancPluginCreateDicomFlags_None);
-    return new OrthancPlugins::FindMatcher(context_, modified);
+    
+    return new OrthancPlugins::FindMatcher(modified);
   }
 }
 
@@ -170,7 +170,7 @@
             // 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()))
             {
-              OrthancPlugins::LogInfo(context_, "Worklist matched: " + it->path().string());
+              OrthancPlugins::LogInfo("Worklist matched: " + it->path().string());
               matchedWorklistCount++;
             }
           }
@@ -179,17 +179,17 @@
 
       std::ostringstream message;
       message << "Worklist C-Find: parsed " << parsedFilesCount << " files, found " << matchedWorklistCount << " match(es)";
-      OrthancPlugins::LogInfo(context_, message.str());
+      OrthancPlugins::LogInfo(message.str());
 
     }
     catch (fs::filesystem_error&)
     {
-      OrthancPlugins::LogError(context_, "Inexistent folder while scanning for worklists: " + source.string());
+      OrthancPlugins::LogError("Inexistent folder while scanning for worklists: " + source.string());
       return OrthancPluginErrorCode_DirectoryExpected;
     }
 
     // Uncomment the following line if too many answers are to be returned
-    // OrthancPluginMarkWorklistAnswersIncomplete(context_, answers);
+    // OrthancPluginMarkWorklistAnswersIncomplete(OrthancPlugins::GetGlobalContext(), answers);
 
     return OrthancPluginErrorCode_Success;
   }
@@ -204,22 +204,21 @@
 {
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
   {
-    context_ = c;
+    OrthancPlugins::SetGlobalContext(c);
 
     /* Check the version of the Orthanc core */
     if (OrthancPluginCheckVersion(c) == 0)
     {
-      OrthancPlugins::ReportMinimalOrthancVersion(context_,
-                                                  ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
+      OrthancPlugins::ReportMinimalOrthancVersion(ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
                                                   ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
                                                   ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
       return -1;
     }
 
-    OrthancPlugins::LogWarning(context_, "Sample worklist plugin is initializing");
-    OrthancPluginSetDescription(context_, "Serve DICOM modality worklists from a folder with Orthanc.");
+    OrthancPlugins::LogWarning("Sample worklist plugin is initializing");
+    OrthancPluginSetDescription(c, "Serve DICOM modality worklists from a folder with Orthanc.");
 
-    OrthancPlugins::OrthancConfiguration configuration(context_);
+    OrthancPlugins::OrthancConfiguration configuration;
 
     OrthancPlugins::OrthancConfiguration worklists;
     configuration.GetSection(worklists, "Worklists");
@@ -229,12 +228,12 @@
     {
       if (worklists.LookupStringValue(folder_, "Database"))
       {
-        OrthancPlugins::LogWarning(context_, "The database of worklists will be read from folder: " + folder_);
-        OrthancPluginRegisterWorklistCallback(context_, Callback);
+        OrthancPlugins::LogWarning("The database of worklists will be read from folder: " + folder_);
+        OrthancPluginRegisterWorklistCallback(OrthancPlugins::GetGlobalContext(), Callback);
       }
       else
       {
-        OrthancPlugins::LogError(context_, "The configuration option \"Worklists.Database\" must contain a path");
+        OrthancPlugins::LogError("The configuration option \"Worklists.Database\" must contain a path");
         return -1;
       }
 
@@ -242,7 +241,7 @@
     }
     else
     {
-      OrthancPlugins::LogWarning(context_, "Worklist server is disabled by the configuration file");
+      OrthancPlugins::LogWarning("Worklist server is disabled by the configuration file");
     }
 
     return 0;
@@ -251,7 +250,7 @@
 
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
-    OrthancPluginLogWarning(context_, "Sample worklist plugin is finalizing");
+    OrthancPlugins::LogWarning("Sample worklist plugin is finalizing");
   }
 
 
--- a/Plugins/Samples/ServeFolders/Plugin.cpp	Mon Dec 03 17:14:55 2018 +0100
+++ b/Plugins/Samples/ServeFolders/Plugin.cpp	Tue Dec 04 16:31:29 2018 +0100
@@ -33,7 +33,6 @@
 
 
 
-static OrthancPluginContext* context_ = NULL;
 static std::map<std::string, std::string> extensions_;
 static std::map<std::string, std::string> folders_;
 static const char* INDEX_URI = "/app/plugin-serve-folders.html";
@@ -46,9 +45,10 @@
   if (!allowCache_)
   {
     // http://stackoverflow.com/a/2068407/881731
-    OrthancPluginSetHttpHeader(context_, output, "Cache-Control", "no-cache, no-store, must-revalidate");
-    OrthancPluginSetHttpHeader(context_, output, "Pragma", "no-cache");
-    OrthancPluginSetHttpHeader(context_, output, "Expires", "0");
+    OrthancPluginContext* context = OrthancPlugins::GetGlobalContext();
+    OrthancPluginSetHttpHeader(context, output, "Cache-Control", "no-cache, no-store, must-revalidate");
+    OrthancPluginSetHttpHeader(context, output, "Pragma", "no-cache");
+    OrthancPluginSetHttpHeader(context, output, "Expires", "0");
   }
 }
 
@@ -89,7 +89,7 @@
   }
   else
   {
-    OrthancPlugins::LogWarning(context_, "ServeFolders: Unknown MIME type for extension \"" + extension + "\"");
+    OrthancPlugins::LogWarning("ServeFolders: Unknown MIME type for extension \"" + extension + "\"");
     return "application/octet-stream";
   }
 }
@@ -104,8 +104,8 @@
   std::map<std::string, std::string>::const_iterator found = folders_.find(uri);
   if (found == folders_.end())
   {
-    OrthancPlugins::LogError(context_, "Unknown URI in plugin server-folders: " + uri);
-    OrthancPluginSendHttpStatusCode(context_, output, 404);
+    OrthancPlugins::LogError("Unknown URI in plugin server-folders: " + uri);
+    OrthancPluginSendHttpStatusCode(OrthancPlugins::GetGlobalContext(), output, 404);
     return false;
   }
   else
@@ -123,15 +123,15 @@
 {
   if (generateETag_)
   {
-    OrthancPlugins::OrthancString md5(context_);
-    md5.Assign(OrthancPluginComputeMd5(context_, content, size));
+    OrthancPlugins::OrthancString md5;
+    md5.Assign(OrthancPluginComputeMd5(OrthancPlugins::GetGlobalContext(), content, size));
 
     std::string etag = "\"" + std::string(md5.GetContent()) + "\"";
-    OrthancPluginSetHttpHeader(context_, output, "ETag", etag.c_str());
+    OrthancPluginSetHttpHeader(OrthancPlugins::GetGlobalContext(), output, "ETag", etag.c_str());
   }
 
   SetHttpHeaders(output);
-  OrthancPluginAnswerBuffer(context_, output, content, size, mime.c_str());
+  OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, content, size, mime.c_str());
 }
 
 
@@ -143,7 +143,7 @@
 
   if (request->method != OrthancPluginHttpMethod_Get)
   {
-    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
+    OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), output, "GET");
     return;
   }
 
@@ -198,7 +198,7 @@
       std::string path = folder + "/" + item.string();
       std::string mime = GetMimeType(path);
 
-      OrthancPlugins::MemoryBuffer content(context_);
+      OrthancPlugins::MemoryBuffer content;
 
       try
       {
@@ -209,9 +209,11 @@
         ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentFile);
       }
 
-      boost::posix_time::ptime lastModification = boost::posix_time::from_time_t(fs::last_write_time(path));
+      boost::posix_time::ptime lastModification =
+        boost::posix_time::from_time_t(fs::last_write_time(path));
       std::string t = boost::posix_time::to_iso_string(lastModification);
-      OrthancPluginSetHttpHeader(context_, output, "Last-Modified", t.c_str());
+      OrthancPluginSetHttpHeader(OrthancPlugins::GetGlobalContext(),
+                                 output, "Last-Modified", t.c_str());
 
       Answer(output, content.GetData(), content.GetSize(), mime);
     }
@@ -225,7 +227,7 @@
 {
   if (request->method != OrthancPluginHttpMethod_Get)
   {
-    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
+    OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), output, "GET");
     return;
   }
 
@@ -258,7 +260,7 @@
 {
   if (folders.type() != Json::objectValue)
   {
-    OrthancPlugins::LogError(context_, "The list of folders to be served is badly formatted (must be a JSON object)");
+    OrthancPlugins::LogError("The list of folders to be served is badly formatted (must be a JSON object)");
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
 
@@ -270,7 +272,7 @@
   {
     if (folders[*it].type() != Json::stringValue)
     {
-      OrthancPlugins::LogError(context_, "The folder to be served \"" + *it + 
+      OrthancPlugins::LogError("The folder to be served \"" + *it + 
                                "\" must be associated with a string value (its mapped URI)");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -292,7 +294,7 @@
 
     if (baseUri.empty())
     {
-      OrthancPlugins::LogError(context_, "The URI of a folder to be served cannot be empty");
+      OrthancPlugins::LogError("The URI of a folder to be served cannot be empty");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
 
@@ -300,7 +302,7 @@
     const std::string folder = folders[*it].asString();
     if (!boost::filesystem::is_directory(folder))
     {
-      OrthancPlugins::LogError(context_, "Trying and serve an inexistent folder: " + folder);
+      OrthancPlugins::LogError("Trying and serve an inexistent folder: " + folder);
       ORTHANC_PLUGINS_THROW_EXCEPTION(InexistentFile);
     }
 
@@ -309,7 +311,7 @@
     // Register the callback to serve the folder
     {
       const std::string regex = "/(" + baseUri + ")/(.*)";
-      OrthancPlugins::RegisterRestCallback<ServeFolder>(context_, regex.c_str(), true);
+      OrthancPlugins::RegisterRestCallback<ServeFolder>(regex.c_str(), true);
     }
   }
 }
@@ -319,7 +321,7 @@
 {
   if (extensions.type() != Json::objectValue)
   {
-    OrthancPlugins::LogError(context_, "The list of extensions is badly formatted (must be a JSON object)");
+    OrthancPlugins::LogError("The list of extensions is badly formatted (must be a JSON object)");
     ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
   }
 
@@ -330,7 +332,7 @@
   {
     if (extensions[*it].type() != Json::stringValue)
     {
-      OrthancPlugins::LogError(context_, "The file extension \"" + *it + 
+      OrthancPlugins::LogError("The file extension \"" + *it + 
                                "\" must be associated with a string value (its MIME type)");
       ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat);
     }
@@ -349,11 +351,12 @@
 
     if (mime.empty())
     {
-      OrthancPlugins::LogWarning(context_, "ServeFolders: Removing MIME type for file extension \"." + name + "\"");
+      OrthancPlugins::LogWarning("ServeFolders: Removing MIME type for file extension \"." +
+                                 name + "\"");
     }
     else
     {
-      OrthancPlugins::LogWarning(context_, "ServeFolders: Associating file extension \"." + name + 
+      OrthancPlugins::LogWarning("ServeFolders: Associating file extension \"." + name + 
                                  "\" with MIME type \"" + mime + "\"");
     }
   }  
@@ -365,7 +368,7 @@
   OrthancPlugins::OrthancConfiguration configuration;
 
   {
-    OrthancPlugins::OrthancConfiguration globalConfiguration(context_);
+    OrthancPlugins::OrthancConfiguration globalConfiguration;
     globalConfiguration.GetSection(configuration, "ServeFolders");
   }
 
@@ -384,7 +387,7 @@
     if (configuration.LookupBooleanValue(tmp, "AllowCache"))
     {
       allowCache_ = tmp;
-      OrthancPlugins::LogWarning(context_, "ServeFolders: Requesting the HTTP client to " +
+      OrthancPlugins::LogWarning("ServeFolders: Requesting the HTTP client to " +
                                  std::string(tmp ? "enable" : "disable") + 
                                  " its caching mechanism");
     }
@@ -392,7 +395,8 @@
     if (configuration.LookupBooleanValue(tmp, "GenerateETag"))
     {
       generateETag_ = tmp;
-      OrthancPlugins::LogWarning(context_, "ServeFolders: The computation of an ETag for the served resources is " +
+      OrthancPlugins::LogWarning("ServeFolders: The computation of an ETag for the "
+                                 "served resources is " +
                                  std::string(tmp ? "enabled" : "disabled"));
     }
 
@@ -403,7 +407,8 @@
 
   if (folders_.empty())
   {
-    OrthancPlugins::LogWarning(context_, "ServeFolders: Empty configuration file: No additional folder will be served!");
+    OrthancPlugins::LogWarning("ServeFolders: Empty configuration file: "
+                               "No additional folder will be served!");
   }
 }
 
@@ -412,22 +417,21 @@
 {
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
   {
-    context_ = context;
+    OrthancPlugins::SetGlobalContext(context);
 
     /* Check the version of the Orthanc core */
-    if (OrthancPluginCheckVersion(context_) == 0)
+    if (OrthancPluginCheckVersion(context) == 0)
     {
-      OrthancPlugins::ReportMinimalOrthancVersion(context_, 
-                                                  ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
+      OrthancPlugins::ReportMinimalOrthancVersion(ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER,
                                                   ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER,
                                                   ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER);
       return -1;
     }
 
     RegisterDefaultExtensions();
-    OrthancPluginSetDescription(context_, "Serve additional folders with the HTTP server of Orthanc.");
+    OrthancPluginSetDescription(context, "Serve additional folders with the HTTP server of Orthanc.");
     OrthancPluginSetRootUri(context, INDEX_URI);
-    OrthancPlugins::RegisterRestCallback<ListServedFolders>(context_, INDEX_URI, true);
+    OrthancPlugins::RegisterRestCallback<ListServedFolders>(INDEX_URI, true);
 
     try
     {
@@ -435,8 +439,8 @@
     }
     catch (OrthancPlugins::PluginException& e)
     {
-      OrthancPlugins::LogError(context_, "Error while initializing the ServeFolders plugin: " + 
-                               std::string(e.What(context_)));
+      OrthancPlugins::LogError("Error while initializing the ServeFolders plugin: " + 
+                               std::string(e.What(context)));
     }
 
     return 0;