changeset 291:4d7469f72a0b

embedding of dicom dictionaries
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 14 Dec 2012 15:15:48 +0100
parents b3322636b06d
children 0439da59faef
files CMakeLists.txt Core/Cache/MemoryCache.cpp Core/DicomFormat/DicomTag.cpp Core/DicomFormat/DicomTag.h INSTALL NEWS OrthancServer/DicomProtocol/DicomServer.cpp OrthancServer/DicomProtocol/IStoreRequestHandler.h OrthancServer/FromDcmtkBridge.cpp OrthancServer/FromDcmtkBridge.h OrthancServer/Internals/StoreScp.cpp OrthancServer/OrthancRestApi.cpp OrthancServer/ServerContext.cpp OrthancServer/main.cpp Resources/CMake/AutoGeneratedCode.cmake Resources/CMake/DcmtkConfiguration.cmake
diffstat 16 files changed, 289 insertions(+), 153 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Dec 14 11:24:24 2012 +0100
+++ b/CMakeLists.txt	Fri Dec 14 15:15:48 2012 +0100
@@ -43,26 +43,6 @@
   SET(STANDALONE_BUILD ON)
 endif()
 
-if (${STANDALONE_BUILD})
-  # We embed all the resources in the binaries for standalone builds
-  add_definitions(-DORTHANC_STANDALONE=1)
-  EmbedResources(
-    PREPARE_DATABASE OrthancServer/PrepareDatabase.sql
-    ORTHANC_EXPLORER OrthancExplorer
-    CONFIGURATION_SAMPLE Resources/Configuration.json
-    )
-else()
-  add_definitions(
-    -DORTHANC_STANDALONE=0
-    -DORTHANC_PATH=\"${CMAKE_SOURCE_DIR}\"
-    )
-  EmbedResources(
-    PREPARE_DATABASE OrthancServer/PrepareDatabase.sql
-    CONFIGURATION_SAMPLE Resources/Configuration.json
-    )
-endif()
-
-
 # Prepare the third-party dependencies
 SET(THIRD_PARTY_SOURCES
   ${CMAKE_SOURCE_DIR}/Resources/md5/md5.c
@@ -93,6 +73,32 @@
 include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibPngConfiguration.cmake)
 
 
+# Prepare the embedded files
+set(EMBEDDED_FILES
+  PREPARE_DATABASE ${CMAKE_CURRENT_SOURCE_DIR}/OrthancServer/PrepareDatabase.sql
+  CONFIGURATION_SAMPLE ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Configuration.json
+  )
+
+if (${STANDALONE_BUILD})
+  # We embed all the resources in the binaries for standalone builds
+  add_definitions(-DORTHANC_STANDALONE=1)
+  EmbedResources(
+    ${EMBEDDED_FILES}
+    ORTHANC_EXPLORER ${CMAKE_CURRENT_SOURCE_DIR}/OrthancExplorer
+    ${DCMTK_DICTIONARIES}
+    )
+else()
+  add_definitions(
+    -DORTHANC_STANDALONE=0
+    -DORTHANC_PATH=\"${CMAKE_SOURCE_DIR}\"
+    )
+  EmbedResources(
+    ${EMBEDDED_FILES}
+    )
+endif()
+
+
+
 # The main instructions to build the Orthanc binaries
 add_library(CoreLibrary
   STATIC
--- a/Core/Cache/MemoryCache.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/Core/Cache/MemoryCache.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -32,6 +32,8 @@
 
 #include "MemoryCache.h"
 
+#include <stdlib.h>  // This fixes a problem in glog for recent
+                     // releases of MinGW
 #include <glog/logging.h>
 
 namespace Orthanc
--- a/Core/DicomFormat/DicomTag.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/Core/DicomFormat/DicomTag.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -70,4 +70,49 @@
     sprintf(b, "%04x,%04x", group_, element_);
     return std::string(b);
   }
+
+
+  const char* DicomTag::GetMainTagsName() const
+  {
+    if (*this == DICOM_TAG_ACCESSION_NUMBER)
+      return "AccessionNumber";
+
+    if (*this == DICOM_TAG_SOP_INSTANCE_UID)
+      return "SOPInstanceUID";
+
+    if (*this == DICOM_TAG_PATIENT_ID)
+      return "PatientID";
+
+    if (*this == DICOM_TAG_SERIES_INSTANCE_UID)
+      return "SeriesInstanceUID";
+
+    if (*this == DICOM_TAG_STUDY_INSTANCE_UID)
+      return "StudyInstanceUID"; 
+
+    if (*this == DICOM_TAG_PIXEL_DATA)
+      return "PixelData";
+
+    if (*this == DICOM_TAG_IMAGE_INDEX)
+      return "ImageIndex";
+
+    if (*this == DICOM_TAG_INSTANCE_NUMBER)
+      return "InstanceNumber";
+
+    if (*this == DICOM_TAG_NUMBER_OF_SLICES)
+      return "NumberOfSlices";
+
+    if (*this == DICOM_TAG_NUMBER_OF_FRAMES)
+      return "NumberOfFrames";
+
+    if (*this == DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES)
+      return "CardiacNumberOfImages";
+
+    if (*this == DICOM_TAG_IMAGES_IN_ACQUISITION)
+      return "ImagesInAcquisition";
+
+    if (*this == DICOM_TAG_PATIENT_NAME)
+      return "PatientName";
+
+    return "";
+  }
 }
--- a/Core/DicomFormat/DicomTag.h	Fri Dec 14 11:24:24 2012 +0100
+++ b/Core/DicomFormat/DicomTag.h	Fri Dec 14 15:15:48 2012 +0100
@@ -64,6 +64,8 @@
       return element_;
     }
 
+    const char* GetMainTagsName() const;
+
     bool operator< (const DicomTag& other) const;
 
     bool operator== (const DicomTag& other) const
--- a/INSTALL	Fri Dec 14 11:24:24 2012 +0100
+++ b/INSTALL	Fri Dec 14 15:15:48 2012 +0100
@@ -76,7 +76,7 @@
 the following command:
 
 # cd ~/OrthancBuild
-# cmake -DCMAKE_TOOLCHAIN_FILE=~/Orthanc/Resources/MinGWToolchain.cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Orthanc
+# cmake -DCMAKE_TOOLCHAIN_FILE=~/Orthanc/Resources/MinGWToolchain.cmake -DSTANDALONE_BUILD=ON -DCMAKE_BUILD_TYPE=DEBUG ~/Orthanc
 # make
 
 
@@ -94,7 +94,7 @@
 ------------------------------------------------------
 
 # cd [...]\OrthancBuild
-# cmake -G "Visual Studio 8 2005" [...]\Orthanc
+# cmake -DSTANDALONE_BUILD=ON -G "Visual Studio 8 2005" [...]\Orthanc
 
 Then open the "[...]/OrthancBuild/Orthanc.sln" with Visual Studio.
 
--- a/NEWS	Fri Dec 14 11:24:24 2012 +0100
+++ b/NEWS	Fri Dec 14 15:15:48 2012 +0100
@@ -4,6 +4,7 @@
 * Recycling of disk space
 * Protection of patients against recycling (also in Orthanc Explorer)
 * Raw access to the value of the DICOM tags in the REST API
+* The DICOM dictionaries are embedded in Windows builds
 
 
 Version 0.3.1 (2012/12/05)
--- a/OrthancServer/DicomProtocol/DicomServer.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/DicomProtocol/DicomServer.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -34,7 +34,9 @@
 
 #include "../../Core/OrthancException.h"
 #include "../../Core/Toolbox.h"
+#include "../../Core/Uuid.h"
 #include "../Internals/CommandDispatcher.h"
+#include "EmbeddedResources.h"
 
 #include <boost/thread.hpp>
 #include <dcmtk/dcmdata/dcdict.h>
@@ -51,15 +53,44 @@
   };
 
 
+  static void LoadEmbeddedDictionary(DcmDataDictionary& dictionary,
+                                     EmbeddedResources::FileResourceId resource)
+  {
+    Toolbox::TemporaryFile tmp;
+
+    FILE* fp = fopen(tmp.GetPath().c_str(), "wb");
+    fwrite(EmbeddedResources::GetFileResourceBuffer(resource), 
+           EmbeddedResources::GetFileResourceSize(resource), 1, fp);
+    fclose(fp);
+
+    if (!dictionary.loadDictionary(tmp.GetPath().c_str()))
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+  }
+                             
+
+
   void DicomServer::ServerThread(DicomServer* server)
   {
     /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */
     dcmDisableGethostbyaddr.set(OFTrue);
 
+#if ORTHANC_STANDALONE == 1
+    LOG(WARNING) << "Loading the embedded dictionaries";
+    dcmDataDict.clear();
+    DcmDataDictionary& d = dcmDataDict.wrlock();
+    LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_DICOM);
+    LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_PRIVATE);
+    LoadEmbeddedDictionary(d, EmbeddedResources::DICTIONARY_DICONDE);
+    dcmDataDict.unlock();
+#endif
+
     /* make sure data dictionary is loaded */
     if (!dcmDataDict.isDictionaryLoaded())
     {
       LOG(ERROR) << "no data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE;
+      throw OrthancException(ErrorCode_InternalError);
     }
 
     /* initialize network, i.e. create an instance of T_ASC_Network*. */
--- a/OrthancServer/DicomProtocol/IStoreRequestHandler.h	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/DicomProtocol/IStoreRequestHandler.h	Fri Dec 14 15:15:48 2012 +0100
@@ -47,7 +47,7 @@
     {
     }
 
-    virtual void Handle(const std::vector<uint8_t>& dicomFile,
+    virtual void Handle(const std::string& dicomFile,
                         const DicomMap& dicomSummary,
                         const Json::Value& dicomJson,
                         const std::string& distantAet) = 0;
--- a/OrthancServer/FromDcmtkBridge.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/FromDcmtkBridge.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -60,6 +60,8 @@
 #include <dcmtk/dcmdata/dcuid.h>
 
 #include <boost/math/special_functions/round.hpp>
+#include <glog/logging.h>
+#include <dcmtk/dcmdata/dcostrmb.h>
 
 namespace Orthanc
 {
@@ -73,10 +75,13 @@
     is.setEos();
 
     file_.reset(new DcmFileFormat);
+    file_->transferInit();
     if (!file_->read(is).good())
     {
       throw OrthancException(ErrorCode_BadFileFormat);
     }
+    file_->loadAllDataIntoMemory();
+    file_->transferEnd();
   }
 
 
@@ -144,6 +149,58 @@
     return true;
   }
 
+
+  static void SendSequence(RestApiOutput& output,
+                           DcmSequenceOfItems& sequence)
+  {
+    // This element is a sequence
+    Json::Value v = Json::arrayValue;
+
+    for (unsigned long i = 0; i < sequence.card(); i++)
+    {
+      v.append(boost::lexical_cast<std::string>(i));
+    }
+
+    output.AnswerJson(v);
+  }
+
+  static void SendField(RestApiOutput& output,
+                        DcmElement& element)
+  {
+    // This element is not a sequence
+    std::string buffer;
+    buffer.resize(65536);
+    Uint32 length = element.getLength();
+    Uint32 offset = 0;
+
+    output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL);
+
+    while (offset < length)
+    {
+      Uint32 nbytes;
+      if (length - offset < buffer.size())
+      {
+        nbytes = length - offset;
+      }
+      else
+      {
+        nbytes = buffer.size();
+      }
+
+      if (element.getPartialValue(&buffer[0], offset, nbytes).good())
+      {
+        output.GetLowLevelOutput().Send(&buffer[0], nbytes);
+        offset += nbytes;
+      }
+      else
+      {
+        return;
+      }
+    }
+
+    output.MarkLowLevelOutputDone();
+  }
+
   static void SendPathValueForLeaf(RestApiOutput& output,
                                    const std::string& tag,
                                    DcmItem& dicom)
@@ -154,57 +211,22 @@
       return;
     }
 
-    DcmElement* element = NULL;
-    if (dicom.findAndGetElement(k, element).good() && element != NULL)
+    DcmSequenceOfItems* sequence = NULL;
+    if (dicom.findAndGetSequence(k, sequence).good() && 
+        sequence != NULL &&
+        sequence->getVR() == EVR_SQ)
     {
-      if (element->getVR() == EVR_SQ)
-      {
-        // This element is a sequence
-        Json::Value v = Json::arrayValue;
-        DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(*element);
-
-        for (unsigned long i = 0; i < sequence.card(); i++)
-        {
-          v.append(boost::lexical_cast<std::string>(i));
-        }
-
-        output.AnswerJson(v);
-      }
-      else
-      {
-        // This element is not a sequence
-        std::string buffer;
-        buffer.resize(65536);
-        Uint32 length = element->getLength();
-        Uint32 offset = 0;
-
-        output.GetLowLevelOutput().SendOkHeader("application/octet-stream", true, length, NULL);
+      SendSequence(output, *sequence);
+      return;
+    }
 
-        while (offset < length)
-        {
-          Uint32 nbytes;
-          if (length - offset < buffer.size())
-          {
-            nbytes = length - offset;
-          }
-          else
-          {
-            nbytes = buffer.size();
-          }
-
-          if (element->getPartialValue(&buffer[0], offset, nbytes).good())
-          {
-            output.GetLowLevelOutput().Send(&buffer[0], nbytes);
-            offset += nbytes;
-          }
-          else
-          {
-            return;
-          }
-        }
-
-        output.MarkLowLevelOutputDone();
-      }
+    DcmElement* element = NULL;
+    if (dicom.findAndGetElement(k, element).good() && 
+        element != NULL &&
+        element->getVR() != EVR_UNKNOWN &&
+        element->getVR() != EVR_SQ)
+    {
+      SendField(output, *element);
     }
   }
 
@@ -728,15 +750,11 @@
   {
     // Some patches for important tags because of different DICOM
     // dictionaries between DCMTK versions
-    if (t == DICOM_TAG_PATIENT_NAME)
-      return "PatientName";
-
-    if (t == DicomTag(0x0010, 0x0030))
-      return "PatientBirthDate";
-
-    if (t == DicomTag(0x0010, 0x0040))
-      return "PatientSex";
-
+    std::string n = t.GetMainTagsName();
+    if (n.size() != 0)
+    {
+      return n;
+    }
     // End of patches
 
     DcmTagKey tag(t.GetGroup(), t.GetElement());
@@ -824,4 +842,53 @@
     }
   }
 
+  bool FromDcmtkBridge::SaveToMemoryBuffer(std::string& buffer,
+                                           DcmDataset* dataSet)
+  {
+    // Determine the transfer syntax which shall be used to write the
+    // information to the file. We always switch to the Little Endian
+    // syntax, with explicit length.
+
+    // http://support.dcmtk.org/docs/dcxfer_8h-source.html
+    E_TransferSyntax xfer = EXS_LittleEndianExplicit;
+    E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength;
+
+    uint32_t s = dataSet->getLength(xfer, encodingType);
+
+    buffer.resize(s);
+    DcmOutputBufferStream ob(&buffer[0], s);
+
+    dataSet->transferInit();
+
+#if DCMTK_VERSION_NUMBER >= 360
+    OFCondition c = dataSet->write(ob, xfer, encodingType, NULL,
+                                   /*opt_groupLength*/ EGL_recalcGL,
+                                   /*opt_paddingType*/ EPD_withoutPadding);
+#else
+    OFCondition c = dataSet->write(ob, xfer, encodingType, NULL);
+#endif
+
+    dataSet->transferEnd();
+    if (c.good())
+    {
+      return true;
+    }
+    else
+    {
+      buffer.clear();
+      return false;
+    }
+
+#if 0
+    OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, 
+                                               encodingType, 
+                                               /*opt_groupLength*/ EGL_recalcGL,
+                                               /*opt_paddingType*/ EPD_withoutPadding,
+                                               OFstatic_cast(Uint32, /*opt_filepad*/ 0), 
+                                               OFstatic_cast(Uint32, /*opt_itempad*/ 0),
+                                               (opt_useMetaheader) ? EWM_fileformat : EWM_dataset);
+#endif
+  }
+
+
 }
--- a/OrthancServer/FromDcmtkBridge.h	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/FromDcmtkBridge.h	Fri Dec 14 15:15:48 2012 +0100
@@ -136,5 +136,8 @@
                        const DicomMap& values);
 
     static std::string GenerateUniqueIdentifier(DicomRootLevel level);
+
+    static bool SaveToMemoryBuffer(std::string& buffer,
+                                   DcmDataset* dataSet);
   };
 }
--- a/OrthancServer/Internals/StoreScp.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/Internals/StoreScp.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -58,55 +58,6 @@
     };
 
 
-    static int SaveToMemoryBuffer(DcmDataset* dataSet,
-                                  std::vector<uint8_t>& buffer)
-    {
-      // Determine the transfer syntax which shall be used to write the
-      // information to the file. We always switch to the Little Endian
-      // syntax, with explicit length.
-
-      // http://support.dcmtk.org/docs/dcxfer_8h-source.html
-      E_TransferSyntax xfer = EXS_LittleEndianExplicit;
-      E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength;
-
-      uint32_t s = dataSet->getLength(xfer, encodingType);
-
-      buffer.resize(s);
-      DcmOutputBufferStream ob(&buffer[0], s);
-
-      dataSet->transferInit();
-
-#if DCMTK_VERSION_NUMBER >= 360
-      OFCondition c = dataSet->write(ob, xfer, encodingType, NULL,
-                                     /*opt_groupLength*/ EGL_recalcGL,
-                                     /*opt_paddingType*/ EPD_withoutPadding);
-#else
-      OFCondition c = dataSet->write(ob, xfer, encodingType, NULL);
-#endif
-
-      dataSet->transferEnd();
-      if (c.good())
-      {
-        return 0;
-      }
-      else
-      {
-        buffer.clear();
-        return -1;
-      }
-
-#if 0
-      OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, 
-                                                 encodingType, 
-                                                 /*opt_groupLength*/ EGL_recalcGL,
-                                                 /*opt_paddingType*/ EPD_withoutPadding,
-                                                 OFstatic_cast(Uint32, /*opt_filepad*/ 0), 
-                                                 OFstatic_cast(Uint32, /*opt_itempad*/ 0),
-                                                 (opt_useMetaheader) ? EWM_fileformat : EWM_dataset);
-#endif
-    }
-
-
     static void
     storeScpCallback(
       void *callbackData,
@@ -159,14 +110,14 @@
         {
           DicomMap summary;
           Json::Value dicomJson;
-          std::vector<uint8_t> buffer;
+          std::string buffer;
 
           try
           {
             FromDcmtkBridge::Convert(summary, **imageDataSet);
             FromDcmtkBridge::ToJson(dicomJson, **imageDataSet);       
 
-            if (SaveToMemoryBuffer(*imageDataSet, buffer) < 0)
+            if (FromDcmtkBridge::SaveToMemoryBuffer(buffer, *imageDataSet) < 0)
             {
               LOG(ERROR) << "cannot write DICOM file to memory";
               rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources;
--- a/OrthancServer/OrthancRestApi.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/OrthancRestApi.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -758,22 +758,29 @@
     RETRIEVE_CONTEXT(call);
 
     const std::string& postData = call.GetPostBody();
+    if (postData.size() == 0)
+    {
+      return;
+    }
 
     LOG(INFO) << "Receiving a DICOM file of " << postData.size() << " bytes through HTTP";
 
-    // Prepare an input stream for the memory buffer
-    DcmInputBufferStream is;
-    if (postData.size() > 0)
+    DcmFileFormat dicomFile;
+
     {
+      // Prepare an input stream for the memory buffer
+      DcmInputBufferStream is;
       is.setBuffer(&postData[0], postData.size());
-    }
-    is.setEos();
+      is.setEos();
 
-    DcmFileFormat dicomFile;
-    if (!dicomFile.read(is).good())
-    {
-      call.GetOutput().SignalError(Orthanc_HttpStatus_415_UnsupportedMediaType);
-      return;
+      dicomFile.transferInit();
+      if (!dicomFile.read(is).good())
+      {
+        call.GetOutput().SignalError(Orthanc_HttpStatus_415_UnsupportedMediaType);
+        return;
+      }
+      dicomFile.loadAllDataIntoMemory();
+      dicomFile.transferEnd();
     }
 
     DicomMap dicomSummary;
@@ -788,9 +795,9 @@
     if (postData.size() > 0)
     {
       status = context.Store
-        (reinterpret_cast<const char*>(&postData[0]),
-         postData.size(), dicomSummary, dicomJson, "");
-    }
+        (reinterpret_cast<const char*>(&postData[0]), postData.size(), 
+         dicomSummary, dicomJson, "");
+    }   
 
     Json::Value result = Json::objectValue;
 
--- a/OrthancServer/ServerContext.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/ServerContext.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -36,6 +36,8 @@
 
 #include <glog/logging.h>
 
+#define ENABLE_DICOM_CACHE  1
+
 
 static const size_t DICOM_CACHE_SIZE = 2;
 
@@ -178,6 +180,12 @@
 
   ParsedDicomFile& ServerContext::GetDicomFile(const std::string& instancePublicId)
   {
+#if ENABLE_DICOM_CACHE == 0
+    static std::auto_ptr<IDynamicObject> p;
+    p.reset(provider_.Provide(instancePublicId));
+    return dynamic_cast<ParsedDicomFile&>(*p);
+#else
     return dynamic_cast<ParsedDicomFile&>(dicomCache_.Access(instancePublicId));
+#endif
   }
 }
--- a/OrthancServer/main.cpp	Fri Dec 14 11:24:24 2012 +0100
+++ b/OrthancServer/main.cpp	Fri Dec 14 15:15:48 2012 +0100
@@ -58,15 +58,14 @@
   {
   }
 
-  virtual void Handle(const std::vector<uint8_t>& dicomFile,
+  virtual void Handle(const std::string& dicomFile,
                       const DicomMap& dicomSummary,
                       const Json::Value& dicomJson,
                       const std::string& remoteAet)
   {
     if (dicomFile.size() > 0)
     {
-      context_.Store(reinterpret_cast<const char*>(&dicomFile[0]), dicomFile.size(),
-                     dicomSummary, dicomJson, remoteAet);
+      context_.Store(&dicomFile[0], dicomFile.size(), dicomSummary, dicomJson, remoteAet);
     }
   }
 };
@@ -187,7 +186,7 @@
 
   google::InitGoogleLogging("Orthanc");
 
-
+  int status = 0;
   try
   {
     bool isInitialized = false;
@@ -289,10 +288,15 @@
   catch (OrthancException& e)
   {
     LOG(ERROR) << "EXCEPTION [" << e.What() << "]";
-return -1;
+    status = -1;
+  }
+  catch (...)
+  {
+    LOG(ERROR) << "NATIVE EXCEPTION";
+    status = -1;
   }
 
   OrthancFinalize();
 
-  return 0;
+  return status;
 }
--- a/Resources/CMake/AutoGeneratedCode.cmake	Fri Dec 14 11:24:24 2012 +0100
+++ b/Resources/CMake/AutoGeneratedCode.cmake	Fri Dec 14 15:15:48 2012 +0100
@@ -11,8 +11,8 @@
   set(IS_PATH_NAME false)
   foreach(arg ${ARGN})
     if (${IS_PATH_NAME})
-      list(APPEND SCRIPT_ARGUMENTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}")
-      list(APPEND DEPENDENCIES "${CMAKE_CURRENT_SOURCE_DIR}/${arg}")
+      list(APPEND SCRIPT_ARGUMENTS "${arg}")
+      list(APPEND DEPENDENCIES "${arg}")
       set(IS_PATH_NAME false)
     else()
       list(APPEND SCRIPT_ARGUMENTS "${arg}")
--- a/Resources/CMake/DcmtkConfiguration.cmake	Fri Dec 14 11:24:24 2012 +0100
+++ b/Resources/CMake/DcmtkConfiguration.cmake	Fri Dec 14 15:15:48 2012 +0100
@@ -70,6 +70,14 @@
 
   set(DCMTK_BUNDLES_LOG4CPLUS 1)
 
+  if (${STANDALONE_BUILD})
+    set(DCMTK_DICTIONARIES
+      DICTIONARY_DICOM ${DCMTK_SOURCES_DIR}/dcmdata/data/dicom.dic
+      DICTIONARY_PRIVATE ${DCMTK_SOURCES_DIR}/dcmdata/data/private.dic
+      DICTIONARY_DICONDE ${DCMTK_SOURCES_DIR}/dcmdata/data/diconde.dic
+      )
+  endif()
+
 else()
   # The following line allows to manually add libraries at the
   # command-line, which is necessary for Ubuntu/Debian packages
@@ -103,6 +111,7 @@
     "\\1\\2\\3" 
     DCMTK_VERSION_NUMBER 
     ${DCMTK_VERSION_NUMBER1})
+
 endif()
 
 add_definitions(-DDCMTK_VERSION_NUMBER=${DCMTK_VERSION_NUMBER})