1 /*
2 *
3 * Copyright (C) 1994-2002, OFFIS
4 *
5 * This software and supporting documentation were developed by
6 *
7 * Kuratorium OFFIS e.V.
8 * Healthcare Information and Communication Systems
9 * Escherweg 2
10 * D-26121 Oldenburg, Germany
11 *
12 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
13 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
14 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
15 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
16 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
17 *
18 * Module: dcmdata
19 *
20 * Author: Andrew Hewett
21 *
22 * Purpose:
23 * Definitions of "well known" DICOM Unique Indentifiers,
24 * routines for finding and creating UIDs.
25 *
26 */
27
28 #include "osconfig.h" /* make sure OS specific configuration is included first */
29
30 #ifdef HAVE_WINDOWS_H
31 #include <windows.h> /* this includes either winsock.h or winsock2.h */
32 #else
33 #ifdef HAVE_WINSOCK_H
34 #include <winsock.h> /* include winsock.h directly i.e. on MacOS */
35 #endif
36 #endif
37
38 #ifdef _WIN32
39 #include <process.h> /* needed for declaration of getpid() */
40 #endif
41
42 #define INCLUDE_CSTDLIB
43 #define INCLUDE_CSTDIO
44 #define INCLUDE_CSTRING
45 #define INCLUDE_CTIME
46 #include "ofstdinc.h"
47
48 BEGIN_EXTERN_C
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52 #ifdef HAVE_LIBC_H
53 #include <libc.h>
54 #endif
55 #ifndef _WIN32
56 #ifdef HAVE_SYS_TIME_H
57 #include <sys/time.h>
58 #endif
59 #ifdef HAVE_SYS_TYPES_H
60 #include <sys/types.h>
61 #endif
62 #ifdef HAVE_SYS_SOCKET_H
63 #ifndef DCOMPAT_SYS_SOCKET_H_
64 #define DCOMPAT_SYS_SOCKET_H_
65 /* some systems don't protect sys/socket.h (e.g. DEC Ultrix) */
66 #include <sys/socket.h>
67 #endif
68 #endif
69 #endif
70 #ifdef HAVE_NETINET_IN_H
71 #include <netinet/in.h>
72 #endif
73 #ifdef HAVE_ARPA_INET_H
74 #include <arpa/inet.h>
75 #endif
76 #ifdef HAVE_NETDB_H
77 #include <netdb.h>
78 #endif
79 END_EXTERN_C
80
81 #include "ofstream.h"
82 #include "dcuid.h"
83 #include "ofthread.h"
84 #include "ofcrc32.h"
85
86 struct UIDNameMap {
87 const char* uid;
88 const char* name;
89 };
90
91 //
92 // It is very important that the names of the UIDs may not use the following
93 // characters: space ( ) [ ], = < >
94
95 static const UIDNameMap uidNameMap[] = {
96 { UID_StandardApplicationContext, "StandardApplicationContext" },
97 { UID_LittleEndianImplicitTransferSyntax, "LittleEndianImplicit" },
98 { UID_LittleEndianExplicitTransferSyntax, "LittleEndianExplicit" },
99 { UID_BigEndianExplicitTransferSyntax, "BigEndianExplicit" },
100 { UID_JPEGProcess1TransferSyntax, "JPEGBaseline" },
101 { UID_JPEGProcess2_4TransferSyntax, "JPEGExtended:Process2+4" },
102 { UID_JPEGProcess3_5TransferSyntax, "JPEGExtended:Process3+5" },
103 { UID_JPEGProcess6_8TransferSyntax, "JPEGSpectralSelection:Non-hierarchical:Process6+8" },
104 { UID_JPEGProcess7_9TransferSyntax, "JPEGSpectralSelection:Non-hierarchical:Process7+9" },
105 { UID_JPEGProcess10_12TransferSyntax, "JPEGFullProgression:Non-hierarchical:Process10+12" },
106 { UID_JPEGProcess11_13TransferSyntax, "JPEGFullProgression:Non-hierarchical:Process11+13" },
107 { UID_JPEGProcess14TransferSyntax, "JPEGLossless:Non-hierarchical:Process14" },
108 { UID_JPEGProcess15TransferSyntax, "JPEGLossless:Non-hierarchical:Process15" },
109 { UID_JPEGProcess16_18TransferSyntax, "JPEGExtended:Hierarchical:Process16+18" },
110 { UID_JPEGProcess17_19TransferSyntax, "JPEGExtended:Hierarchical:Process17+19" },
111 { UID_JPEGProcess20_22TransferSyntax, "JPEGSpectralSelection:Hierarchical:Process20+22" },
112 { UID_JPEGProcess21_23TransferSyntax, "JPEGSpectralSelection:Hierarchical:Process21+23" },
113 { UID_JPEGProcess24_26TransferSyntax, "JPEGFullProgression:Hierarchical:Process24+26" },
114 { UID_JPEGProcess25_27TransferSyntax, "JPEGFullProgression:Hierarchical:Process25+27" },
115 { UID_JPEGProcess28TransferSyntax, "JPEGLossless:Hierarchical:Process28" },
116 { UID_JPEGProcess29TransferSyntax, "JPEGLossless:Hierarchical:Process29" },
117 { UID_JPEGProcess14SV1TransferSyntax, "JPEGLossless:Non-hierarchical-1stOrderPrediction" },
118 { UID_JPEGLSLossless, "JPEGLSLossless" },
119 { UID_JPEGLSLossy, "JPEGLSLossy" },
120 { UID_RLELossless, "RLELossless" },
121 { UID_DeflatedExplicitVRLittleEndianTransferSyntax, "DeflatedLittleEndianExplicit" },
122 { UID_JPEG2000LosslessOnlyTransferSyntax, "JPEG2000LosslessOnly" },
123 { UID_JPEG2000TransferSyntax, "JPEG2000" },
124
125 // Storage
126 { UID_AmbulatoryECGWaveformStorage, "AmbulatoryECGWaveformStorage" },
127 { UID_BasicTextSR, "BasicTextSR" },
128 { UID_BasicVoiceAudioWaveformStorage, "BasicVoiceAudioWaveformStorage" },
129 { UID_CTImageStorage, "CTImageStorage" },
130 { UID_CardiacElectrophysiologyWaveformStorage, "CardiacElectrophysiologyWaveformStorage" },
131 { UID_ComprehensiveSR, "ComprehensiveSR" },
132 { UID_ComputedRadiographyImageStorage, "ComputedRadiographyImageStorage" },
133 { UID_DigitalIntraOralXRayImageStorageForPresentation, "DigitalIntraOralXRayImageStorageForPresentation" },
134 { UID_DigitalIntraOralXRayImageStorageForProcessing, "DigitalIntraOralXRayImageStorageForProcessing" },
135 { UID_DigitalMammographyXRayImageStorageForPresentation, "DigitalMammographyXRayImageStorageForPresentation" },
136 { UID_DigitalMammographyXRayImageStorageForProcessing, "DigitalMammographyXRayImageStorageForProcessing" },
137 { UID_DigitalXRayImageStorageForPresentation, "DigitalXRayImageStorageForPresentation" },
138 { UID_DigitalXRayImageStorageForProcessing, "DigitalXRayImageStorageForProcessing" },
139 { UID_EnhancedMRImageStorage, "EnhancedMRImageStorage" },
140 { UID_EnhancedSR, "EnhancedSR" },
141 { UID_GeneralECGWaveformStorage, "GeneralECGWaveformStorage" },
142 { UID_GrayscaleSoftcopyPresentationStateStorage, "GrayscaleSoftcopyPresentationStateStorage" },
143 { UID_HardcopyColorImageStorage, "HardcopyColorImageStorage" },
144 { UID_HardcopyGrayscaleImageStorage, "HardcopyGrayscaleImageStorage" },
145 { UID_HemodynamicWaveformStorage, "HemodynamicWaveformStorage" },
146 { UID_KeyObjectSelectionDocument, "KeyObjectSelectionDocument" },
147 { UID_MRImageStorage, "MRImageStorage" },
148 { UID_MRSpectroscopyStorage, "MRSpectroscopyStorage" },
149 { UID_MammographyCADSR, "MammographyCADSR" },
150 { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "MultiframeGrayscaleByteSecondaryCaptureImageStorage" },
151 { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "MultiframeGrayscaleWordSecondaryCaptureImageStorage" },
152 { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "MultiframeSingleBitSecondaryCaptureImageStorage" },
153 { UID_MultiframeTrueColorSecondaryCaptureImageStorage, "MultiframeTrueColorSecondaryCaptureImageStorage" },
154 { UID_NuclearMedicineImageStorage, "NuclearMedicineImageStorage" },
155 { UID_PETCurveStorage, "PETCurveStorage" },
156 { UID_PETImageStorage, "PETImageStorage" },
157 { UID_RETIRED_NuclearMedicineImageStorage, "RETIRED_NuclearMedicineImageStorage" },
158 { UID_RETIRED_UltrasoundImageStorage, "RETIRED_UltrasoundImageStorage" },
159 { UID_RETIRED_UltrasoundMultiframeImageStorage, "RETIRED_UltrasoundMultiframeImageStorage" },
160 { UID_RETIRED_VLImageStorage, "RETIRED_VLImageStorage" },
161 { UID_RETIRED_VLMultiFrameImageStorage, "RETIRED_VLMultiFrameImageStorage" },
162 { UID_RETIRED_XRayAngiographicBiPlaneImageStorage, "RETIRED_XRayAngiographicBiPlaneImageStorage" },
163 { UID_RTBeamsTreatmentRecordStorage, "RTBeamsTreatmentRecordStorage" },
164 { UID_RTBrachyTreatmentRecordStorage, "RTBrachyTreatmentRecordStorage" },
165 { UID_RTDoseStorage, "RTDoseStorage" },
166 { UID_RTImageStorage, "RTImageStorage" },
167 { UID_RTPlanStorage, "RTPlanStorage" },
168 { UID_RTStructureSetStorage, "RTStructureSetStorage" },
169 { UID_RTTreatmentSummaryRecordStorage, "RTTreatmentSummaryRecordStorage" },
170 { UID_RawDataStorage, "RawDataStorage" },
171 { UID_SecondaryCaptureImageStorage, "SecondaryCaptureImageStorage" },
172 { UID_StandaloneCurveStorage, "StandaloneCurveStorage" },
173 { UID_StandaloneModalityLUTStorage, "StandaloneModalityLUTStorage" },
174 { UID_StandaloneOverlayStorage, "StandaloneOverlayStorage" },
175 { UID_StandaloneVOILUTStorage, "StandaloneVOILUTStorage" },
176 { UID_StoredPrintStorage, "StoredPrintStorage" },
177 { UID_TwelveLeadECGWaveformStorage, "TwelveLeadECGWaveformStorage" },
178 { UID_UltrasoundImageStorage, "UltrasoundImageStorage" },
179 { UID_UltrasoundMultiframeImageStorage, "UltrasoundMultiframeImageStorage" },
180 { UID_VLEndoscopicImageStorage, "VLEndoscopicImageStorage" },
181 { UID_VLMicroscopicImageStorage, "VLMicroscopicImageStorage" },
182 { UID_VLPhotographicImageStorage, "VLPhotographicImageStorage" },
183 { UID_VLSlideCoordinatesMicroscopicImageStorage, "VLSlideCoordinatesMicroscopicImageStorage" },
184 { UID_XRayAngiographicImageStorage, "XRayAngiographicImageStorage" },
185 { UID_XRayFluoroscopyImageStorage, "XRayFluoroscopyImageStorage" },
186
187 // Query/Retrieve
188 { UID_FINDModalityWorklistInformationModel, "FINDModalityWorklistInformationModel" },
189 { UID_FINDPatientRootQueryRetrieveInformationModel, "FINDPatientRootQueryRetrieveInformationModel" },
190 { UID_FINDPatientStudyOnlyQueryRetrieveInformationModel, "FINDPatientStudyOnlyQueryRetrieveInformationModel" },
191 { UID_FINDStudyRootQueryRetrieveInformationModel, "FINDStudyRootQueryRetrieveInformationModel" },
192 { UID_GETPatientRootQueryRetrieveInformationModel, "GETPatientRootQueryRetrieveInformationModel" },
193 { UID_GETPatientStudyOnlyQueryRetrieveInformationModel, "GETPatientStudyOnlyQueryRetrieveInformationModel" },
194 { UID_GETStudyRootQueryRetrieveInformationModel, "GETStudyRootQueryRetrieveInformationModel" },
195 { UID_MOVEPatientRootQueryRetrieveInformationModel, "MOVEPatientRootQueryRetrieveInformationModel" },
196 { UID_MOVEPatientStudyOnlyQueryRetrieveInformationModel, "MOVEPatientStudyOnlyQueryRetrieveInformationModel" },
197 { UID_MOVEStudyRootQueryRetrieveInformationModel, "MOVEStudyRootQueryRetrieveInformationModel" },
198 { UID_FINDGeneralPurposeWorklistInformationModel, "FINDGeneralPurposeWorklistInformationModel" },
199
200 // Print
201 { UID_BasicAnnotationBoxSOPClass, "BasicAnnotationBoxSOPClass" },
202 { UID_BasicColorImageBoxSOPClass, "BasicColorImageBoxSOPClass" },
203 { UID_BasicColorPrintManagementMetaSOPClass, "BasicColorPrintManagementMetaSOPClass" },
204 { UID_BasicFilmBoxSOPClass, "BasicFilmBoxSOPClass" },
205 { UID_BasicFilmSessionSOPClass, "BasicFilmSessionSOPClass" },
206 { UID_BasicGrayscaleImageBoxSOPClass, "BasicGrayscaleImageBoxSOPClass" },
207 { UID_BasicGrayscalePrintManagementMetaSOPClass, "BasicGrayscalePrintManagementMetaSOPClass" },
208 { UID_BasicPrintImageOverlayBoxSOPClass, "BasicPrintImageOverlayBoxSOPClass" },
209 { UID_ImageOverlayBoxSOPClass, "ImageOverlayBoxSOPClass" },
210 { UID_PresentationLUTSOPClass, "PresentationLUTSOPClass" },
211 { UID_PrintJobSOPClass, "PrintJobSOPClass" },
212 { UID_PrintQueueManagementSOPClass, "PrintQueueManagementSOPClass" },
213 { UID_PrintQueueSOPInstance, "PrintQueueSOPInstance" },
214 { UID_PrinterConfigurationRetrievalSOPClass, "PrinterConfigurationRetrievalSOPClass" },
215 { UID_PrinterConfigurationRetrievalSOPInstance, "PrinterConfigurationRetrievalSOPInstance" },
216 { UID_PrinterSOPClass, "PrinterSOPClass" },
217 { UID_PrinterSOPInstance, "PrinterSOPInstance" },
218 { UID_PullPrintRequestSOPClass, "PullPrintRequestSOPClass" },
219 { UID_PullStoredPrintManagementMetaSOPClass, "PullStoredPrintManagementMetaSOPClass" },
220 { UID_RETIRED_ReferencedColorPrintManagementMetaSOPClass, "RETIRED_ReferencedColorPrintManagementMetaSOPClass" },
221 { UID_RETIRED_ReferencedGrayscalePrintManagementMetaSOPClass, "RETIRED_ReferencedGrayscalePrintManagementMetaSOPClass" },
222 { UID_RETIRED_ReferencedImageBoxSOPClass, "RETIRED_ReferencedImageBoxSOPClass" },
223 { UID_VOILUTBoxSOPClass, "VOILUTBoxSOPClass" },
224
225 // Storage Commitment
226 { UID_RETIRED_StorageCommitmentPullModelSOPClass, "RETIRED_StorageCommitmentPullModelSOPClass" },
227 { UID_RETIRED_StorageCommitmentPullModelSOPInstance, "RETIRED_StorageCommitmentPullModelSOPInstance" },
228 { UID_StorageCommitmentPushModelSOPClass, "StorageCommitmentPushModelSOPClass" },
229 { UID_StorageCommitmentPushModelSOPInstance, "StorageCommitmentPushModelSOPInstance" },
230
231 // MPPS
232 { UID_ModalityPerformedProcedureStepNotificationSOPClass, "ModalityPerformedProcedureStepNotificationSOPClass" },
233 { UID_ModalityPerformedProcedureStepRetrieveSOPClass, "ModalityPerformedProcedureStepRetrieveSOPClass" },
234 { UID_ModalityPerformedProcedureStepSOPClass, "ModalityPerformedProcedureStepSOPClass" },
235
236 // Detached Management
237 { UID_DetachedInterpretationManagementSOPClass, "DetachedInterpretationManagementSOPClass" },
238 { UID_DetachedPatientManagementMetaSOPClass, "DetachedPatientManagementMetaSOPClass" },
239 { UID_DetachedPatientManagementSOPClass, "DetachedPatientManagementSOPClass" },
240 { UID_DetachedResultsManagementMetaSOPClass, "DetachedResultsManagementMetaSOPClass" },
241 { UID_DetachedResultsManagementSOPClass, "DetachedResultsManagementSOPClass" },
242 { UID_DetachedStudyManagementMetaSOPClass, "DetachedStudyManagementMetaSOPClass" },
243 { UID_DetachedStudyManagementSOPClass, "DetachedStudyManagementSOPClass" },
244 { UID_DetachedVisitManagementSOPClass, "DetachedVisitManagementSOPClass" },
245
246 // General Purpose Worklist (Supplement 52 final text)
247 { UID_GeneralPurposeScheduledProcedureStepSOPClass, "GeneralPurposeScheduledProcedureStepSOPClass" },
248 { UID_GeneralPurposePerformedProcedureStepSOPClass, "GeneralPurposePerformedProcedureStepSOPClass" },
249 { UID_GeneralPurposeWorklistManagementMetaSOPClass, "GeneralPurposeWorklistManagementMetaSOPClass" },
250
251 // other
252 { UID_BasicDirectoryStorageSOPClass, "BasicDirectoryStorageSOPClass" },
253 { UID_BasicStudyContentNotificationSOPClass, "BasicStudyContentNotificationSOPClass" },
254 { UID_StudyComponentManagementSOPClass, "StudyComponentManagementSOPClass" },
255 { UID_VerificationSOPClass, "VerificationSOPClass" },
256
257 // DICOM Controlled Terminology
258 { UID_DICOMControlledTerminologyCodingScheme, "DICOMControlledTerminologyCodingScheme" },
259
260 // supplements
261 { UID_DRAFT_SRTextStorage, "DRAFT_SRTextStorage" },
262 { UID_DRAFT_SRAudioStorage, "DRAFT_SRAudioStorage" },
263 { UID_DRAFT_SRDetailStorage, "DRAFT_SRDetailStorage" },
264 { UID_DRAFT_SRComprehensiveStorage, "DRAFT_SRComprehensiveStorage" },
265 { UID_DRAFT_WaveformStorage, "DRAFT_WaveformStorage" },
266
267 { NULL, NULL }
268 };
269
270 static const int uidNameMap_size = ( sizeof(uidNameMap) / sizeof(UIDNameMap) );
271
272 /*
273 ** The global variable dcmStorageSOPClassUIDs is an array of
274 ** string pointers containing the UIDs of all known Storage SOP
275 ** Classes. The global variable numberOfDcmStorageSOPClassUIDs
276 ** defines the size of the array.
277 */
278
279 const char* dcmStorageSOPClassUIDs[] = {
280 // basic directory storage is a special case - we cannot
281 // transmit a DICOMDIR by c-store because of the absolute
282 // file position offsets within the DICOMDIR.
283 // UID_BasicDirectoryStorageSOPClass,
284
285 UID_AmbulatoryECGWaveformStorage,
286 UID_BasicTextSR,
287 UID_BasicVoiceAudioWaveformStorage,
288 UID_CTImageStorage,
289 UID_CardiacElectrophysiologyWaveformStorage,
290 UID_ComprehensiveSR,
291 UID_ComputedRadiographyImageStorage,
292 /* disabled draft storage SOP classes to keep the number of storage transfer
293 * syntaxes <= 64. If we have more than 64 storage transfer syntaxes, tools
294 * such as storescu will fail because they attempt to negotiate two
295 * presentation contexts for each SOP class, and there is a total limit of
296 * 128 contexts for one association.
297 *
298 UID_DRAFT_SRAudioStorage,
299 UID_DRAFT_SRComprehensiveStorage,
300 UID_DRAFT_SRDetailStorage,
301 UID_DRAFT_SRTextStorage,
302 UID_DRAFT_WaveformStorage,
303 */
304 UID_DigitalIntraOralXRayImageStorageForPresentation,
305 UID_DigitalIntraOralXRayImageStorageForProcessing,
306 UID_DigitalMammographyXRayImageStorageForPresentation,
307 UID_DigitalMammographyXRayImageStorageForProcessing,
308 UID_DigitalXRayImageStorageForPresentation,
309 UID_DigitalXRayImageStorageForProcessing,
310 UID_EnhancedMRImageStorage,
311 UID_EnhancedSR,
312 UID_GeneralECGWaveformStorage,
313 UID_GrayscaleSoftcopyPresentationStateStorage,
314 UID_HardcopyColorImageStorage,
315 UID_HardcopyGrayscaleImageStorage,
316 UID_HemodynamicWaveformStorage,
317 UID_KeyObjectSelectionDocument,
318 UID_MRImageStorage,
319 UID_MRSpectroscopyStorage,
320 UID_MammographyCADSR,
321 UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage,
322 UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage,
323 UID_MultiframeSingleBitSecondaryCaptureImageStorage,
324 UID_MultiframeTrueColorSecondaryCaptureImageStorage,
325 UID_NuclearMedicineImageStorage,
326 UID_PETCurveStorage,
327 UID_PETImageStorage,
328 UID_RETIRED_NuclearMedicineImageStorage,
329 UID_RETIRED_UltrasoundImageStorage,
330 UID_RETIRED_UltrasoundMultiframeImageStorage,
331 /* disabled draft storage SOP classes to keep the number of storage transfer
332 * syntaxes <= 64. If we have more than 64 storage transfer syntaxes, tools
333 * such as storescu will fail because they attempt to negotiate two
334 * presentation contexts for each SOP class, and there is a total limit of
335 * 128 contexts for one association.
336 *
337 UID_RETIRED_VLImageStorage,
338 UID_RETIRED_VLMultiFrameImageStorage,
339 */
340 UID_RETIRED_XRayAngiographicBiPlaneImageStorage,
341 UID_RTBeamsTreatmentRecordStorage,
342 UID_RTBrachyTreatmentRecordStorage,
343 UID_RTDoseStorage,
344 UID_RTImageStorage,
345 UID_RTPlanStorage,
346 UID_RTStructureSetStorage,
347 UID_RTTreatmentSummaryRecordStorage,
348 UID_RawDataStorage,
349 UID_SecondaryCaptureImageStorage,
350 UID_StandaloneCurveStorage,
351 UID_StandaloneModalityLUTStorage,
352 UID_StandaloneOverlayStorage,
353 UID_StandaloneVOILUTStorage,
354 UID_StoredPrintStorage,
355 UID_TwelveLeadECGWaveformStorage,
356 UID_UltrasoundImageStorage,
357 UID_UltrasoundMultiframeImageStorage,
358 UID_VLEndoscopicImageStorage,
359 UID_VLMicroscopicImageStorage,
360 UID_VLPhotographicImageStorage,
361 UID_VLSlideCoordinatesMicroscopicImageStorage,
362 UID_XRayAngiographicImageStorage,
363 UID_XRayFluoroscopyImageStorage,
364
365 NULL
366 };
367
368 const int numberOfDcmStorageSOPClassUIDs =
369 (sizeof(dcmStorageSOPClassUIDs) / sizeof(const char*)) - 1;
370
371
372 /*
373 ** The global variable dcmImageSOPClassUIDs is an array of
374 ** string pointers containing the UIDs of all known Image SOP
375 ** Classes. The instances of SOP Classes in this list can be
376 ** referenced from DICOMDIR IMAGE records.
377 **
378 ** The dcmgpdir program uses this list to determine what kind of
379 ** objects can be referenced from IMAGE records.
380 ** Be _very_ careful when adding SOP Classes to this list!!
381 **
382 ** The global variable numberOfDcmImageSOPClassUIDs
383 ** defines the size of the array.
384 ** NOTE: this list represents a subset of the dcmStorageSOPClassUIDs list
385 */
386
387 const char* dcmImageSOPClassUIDs[] = {
388 UID_CTImageStorage,
389 UID_ComputedRadiographyImageStorage,
390 UID_DigitalIntraOralXRayImageStorageForPresentation,
391 UID_DigitalIntraOralXRayImageStorageForProcessing,
392 UID_DigitalMammographyXRayImageStorageForPresentation,
393 UID_DigitalMammographyXRayImageStorageForProcessing,
394 UID_DigitalXRayImageStorageForPresentation,
395 UID_DigitalXRayImageStorageForProcessing,
396 UID_EnhancedMRImageStorage,
397 UID_HardcopyColorImageStorage,
398 UID_HardcopyGrayscaleImageStorage,
399 UID_MRImageStorage,
400 UID_NuclearMedicineImageStorage,
401 UID_PETCurveStorage,
402 UID_PETImageStorage,
403 UID_RETIRED_NuclearMedicineImageStorage,
404 UID_RETIRED_UltrasoundImageStorage,
405 UID_RETIRED_UltrasoundMultiframeImageStorage,
406 UID_RETIRED_VLImageStorage,
407 UID_RETIRED_VLMultiFrameImageStorage,
408 UID_RETIRED_XRayAngiographicBiPlaneImageStorage,
409 UID_RTImageStorage,
410 UID_SecondaryCaptureImageStorage,
411 UID_UltrasoundImageStorage,
412 UID_UltrasoundMultiframeImageStorage,
413 UID_VLEndoscopicImageStorage,
414 UID_VLMicroscopicImageStorage,
415 UID_VLPhotographicImageStorage,
416 UID_VLSlideCoordinatesMicroscopicImageStorage,
417 UID_XRayAngiographicImageStorage,
418 UID_XRayFluoroscopyImageStorage,
419 UID_MultiframeSingleBitSecondaryCaptureImageStorage,
420 UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage,
421 UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage,
422 UID_MultiframeTrueColorSecondaryCaptureImageStorage,
423
424 NULL
425 };
426
427 const int numberOfDcmImageSOPClassUIDs =
428 (sizeof(dcmImageSOPClassUIDs) / sizeof(const char*)) - 1;
429
430
431 typedef struct {
432 const char *sopClass;
433 const char *modality;
434 unsigned long averageSize; /* can be way, way out */
435 } DcmModalityTable;
436
437 /*
438 ** The modalities table defines a short character code for each
439 ** Storage SOP Class for use in filenames.
440 ** It also gives a typical size for each SOP Instance. This will
441 ** ususally be way out, but is useful in user interfaces to give an
442 ** idea of progress when receiving an image (C-STORE does not indicate
443 ** the size of an image being transmitted).
444 */
445 static const DcmModalityTable modalities[] = {
446 { UID_AmbulatoryECGWaveformStorage, "ECA", 4096 },
447 { UID_BasicTextSR, "SRt", 4096 },
448 { UID_BasicVoiceAudioWaveformStorage, "AUV", 4096 },
449 { UID_CTImageStorage, "CT", 2 * 512 * 512 },
450 { UID_CardiacElectrophysiologyWaveformStorage, "WVc", 4096 },
451 { UID_ComprehensiveSR, "SRc", 4096 },
452 { UID_ComputedRadiographyImageStorage, "CR", 2 * 2048 * 2048 },
453 { UID_DRAFT_SRAudioStorage, "SRw", 4096 },
454 { UID_DRAFT_SRComprehensiveStorage, "SRx", 4096 },
455 { UID_DRAFT_SRDetailStorage, "SRy", 4096 },
456 { UID_DRAFT_SRTextStorage, "SRz", 4096 },
457 { UID_DRAFT_WaveformStorage, "WVd", 4096 },
458 { UID_DigitalIntraOralXRayImageStorageForPresentation, "DXo", 2 * 1024 * 1024 },
459 { UID_DigitalIntraOralXRayImageStorageForProcessing, "DPo", 2 * 1024 * 1024 },
460 { UID_DigitalMammographyXRayImageStorageForPresentation, "DXm", 2 * 4096 * 4096 },
461 { UID_DigitalMammographyXRayImageStorageForProcessing, "DPm", 2 * 4096 * 4096 },
462 { UID_DigitalXRayImageStorageForPresentation, "DX", 2 * 2048 * 2048 },
463 { UID_DigitalXRayImageStorageForProcessing, "DP", 2 * 2048 * 2048 },
464 { UID_EnhancedMRImageStorage, "MRe", 512 * 512 * 256 },
465 { UID_EnhancedSR, "SRe", 4096 },
466 { UID_GeneralECGWaveformStorage, "ECG", 4096 },
467 { UID_GrayscaleSoftcopyPresentationStateStorage, "PSg", 4096 },
468 { UID_HardcopyColorImageStorage, "HC", 4096 },
469 { UID_HardcopyGrayscaleImageStorage, "HG", 4096 },
470 { UID_HemodynamicWaveformStorage, "WVh", 4096 },
471 { UID_KeyObjectSelectionDocument, "SRk", 4096 },
472 { UID_MRImageStorage, "MR", 2 * 256 * 256 },
473 { UID_MRSpectroscopyStorage, "MRs", 512 * 512 * 256 },
474 { UID_MammographyCADSR, "SRm", 4096 },
475 { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "SCb", 1 * 512 * 512 },
476 { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "SCw", 2 * 512 * 512 },
477 { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "SCs", 1024 * 1024 }, /* roughly an A4 300dpi scan */
478 { UID_MultiframeTrueColorSecondaryCaptureImageStorage, "SCc", 3 * 512 * 512 },
479 { UID_NuclearMedicineImageStorage, "NM", 2 * 64 * 64 },
480 { UID_PETCurveStorage, "PC", 4096 },
481 { UID_PETImageStorage, "PI", 512*512*2 },
482 { UID_RETIRED_NuclearMedicineImageStorage, "NMr", 2 * 64 * 64 },
483 { UID_RETIRED_UltrasoundImageStorage, "USr", 1 * 512 * 512 },
484 { UID_RETIRED_UltrasoundMultiframeImageStorage, "USr", 1 * 512 * 512 },
485 { UID_RETIRED_VLImageStorage, "VLr", 768 * 576 * 3 },
486 { UID_RETIRED_VLMultiFrameImageStorage, "VMr", 768 * 576 * 3 },
487 { UID_RETIRED_XRayAngiographicBiPlaneImageStorage, "XB", 2 * 512 * 512 },
488 { UID_RTBeamsTreatmentRecordStorage, "RTb", 4096 },
489 { UID_RTBrachyTreatmentRecordStorage, "RTr", 4096 },
490 { UID_RTDoseStorage, "RD", 4096 },
491 { UID_RTImageStorage, "RI", 4096 },
492 { UID_RTPlanStorage, "RP" , 4096 },
493 { UID_RTStructureSetStorage, "RS", 4096 },
494 { UID_RTTreatmentSummaryRecordStorage, "RTs", 4096 },
495 { UID_RawDataStorage, "RAW", 512 * 512 * 256 },
496 { UID_SecondaryCaptureImageStorage, "SC", 2 * 512 * 512 },
497 { UID_StandaloneCurveStorage, "CV", 4096 },
498 { UID_StandaloneModalityLUTStorage, "ML", 4096*2 },
499 { UID_StandaloneOverlayStorage, "OV", 512 * 512 },
500 { UID_StandaloneVOILUTStorage, "VO", 4096*2 },
501 { UID_StoredPrintStorage, "SP", 4096 },
502 { UID_TwelveLeadECGWaveformStorage, "TLE", 4096 },
503 { UID_UltrasoundImageStorage, "US", 1 * 512 * 512 },
504 { UID_UltrasoundMultiframeImageStorage, "US", 1 * 512 * 512 },
505 { UID_VLEndoscopicImageStorage, "VLe", 768 * 576 * 3 },
506 { UID_VLMicroscopicImageStorage, "VLm", 768 * 576 * 3 },
507 { UID_VLPhotographicImageStorage, "VLp", 768 * 576 * 3 },
508 { UID_VLSlideCoordinatesMicroscopicImageStorage, "VMs", 768 * 576 * 3 },
509 { UID_XRayAngiographicImageStorage, "XA", 2 * 512 * 512 },
510 { UID_XRayFluoroscopyImageStorage, "RF", 2 * 512 * 512 }
511 };
512
513 static const int numberOfDcmModalityTableEntries =
514 (sizeof(modalities) / sizeof(DcmModalityTable));
515
516
517 /*
518 * Public Function Prototypes
519 */
520
521
dcmSOPClassUIDToModality(const char * sopClassUID)522 const char *dcmSOPClassUIDToModality(const char *sopClassUID)
523 {
524 if (sopClassUID == NULL) return NULL;
525 for (int i = 0; i < numberOfDcmModalityTableEntries; i++)
526 {
527 if (strcmp(modalities[i].sopClass, sopClassUID) == 0) return modalities[i].modality;
528 }
529 return NULL;
530 }
531
dcmGuessModalityBytes(const char * sopClassUID)532 unsigned long dcmGuessModalityBytes(const char *sopClassUID)
533 {
534 unsigned long nbytes = 1048576; /* default: 1 MByte */
535
536 if (sopClassUID == NULL) return nbytes;
537
538 int found=0;
539 for (int i = 0; (!found && (i < numberOfDcmModalityTableEntries)); i++)
540 {
541 found = (strcmp(modalities[i].sopClass, sopClassUID) == 0);
542 if (found) nbytes = modalities[i].averageSize;
543 }
544
545 return nbytes;
546 }
547
548
549 /*
550 ** dcmFindNameOfUID(const char* uid)
551 ** Return the name of a UID.
552 ** Performs a table lookup and returns a pointer to a read-only string.
553 ** Returns NULL of the UID is not known.
554 */
555
556 const char*
dcmFindNameOfUID(const char * uid)557 dcmFindNameOfUID(const char* uid)
558 {
559 int i = 0;
560 if (uid == NULL) return NULL;
561 for (i=0; i<uidNameMap_size; i++) {
562 if (uidNameMap[i].uid != NULL && strcmp(uid, uidNameMap[i].uid) == 0) {
563 return uidNameMap[i].name;
564 }
565 }
566 return NULL;
567 }
568
569 //
570 // dcmFindUIDFromName(const char* name)
571 // Return the UID of a name.
572 // Performs a table lookup and returns a pointer to a read-only string.
573 // Returns NULL of the name is not known.
574 //
575
576 const char *
dcmFindUIDFromName(const char * name)577 dcmFindUIDFromName(const char * name)
578 {
579 if (name == NULL) return NULL;
580 for (int i = 0; i < uidNameMap_size; i++)
581 {
582 if (uidNameMap[i].name != NULL && strcmp(name, uidNameMap[i].name) == 0)
583 return uidNameMap[i].uid;
584 }
585 return NULL;
586 }
587
588
589 /*
590 ** dcmIsaStorageSOPClassUID(const char* uid)
591 ** Returns true if the uid is one of the Storage SOP Classes.
592 ** Performs a table lookup in the dcmStorageSOPClassUIDs table.
593 */
594 OFBool
dcmIsaStorageSOPClassUID(const char * uid)595 dcmIsaStorageSOPClassUID(const char* uid)
596 {
597 int i = 0;
598 if (uid == NULL) return OFFalse;
599 for (i=0; i<numberOfDcmStorageSOPClassUIDs; i++) {
600 if (dcmStorageSOPClassUIDs[i] != NULL
601 && strcmp(uid, dcmStorageSOPClassUIDs[i]) == 0) {
602 return OFTrue;
603 }
604 }
605 return OFFalse;
606 }
607
608 // ********************************
609
610 #ifndef HAVE_GETHOSTID
611 #ifdef HAVE_SYSINFO
612
613 #include <sys/systeminfo.h>
gethostid(void)614 static long gethostid(void)
615 {
616 char buf[128];
617 if (sysinfo(SI_HW_SERIAL, buf, 128) == -1) {
618 ofConsole.lockCerr() << "sysinfo: " << strerror(errno) << endl;
619 ofConsole.unlockCerr();
620 exit(1);
621 }
622 #ifdef HAVE_STRTOUL
623 return(strtoul(buf, NULL, 0));
624 #else
625 long result;
626 sscanf(buf, "%ld", &result);
627 return result;
628 #endif
629 }
630
631 #else // !HAVE_SYSINFO
632
633 /*
634 ** There is no implementation of gethostid() and we cannot implement it in
635 ** terms of sysinfo() so define a workaround.
636 */
637 #if (defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)) || defined(HAVE_WINDOWS_H)
638
639 // 16K should be large enough to handle everything pointed to by a struct hostent
640 #define GETHOSTBYNAME_R_BUFSIZE 16384
641
642 /* on Windows systems specify a routine to determine the MAC address of the Ethernet adapter */
643 #ifdef HAVE_WINDOWS_H
644
645 #include <snmp.h>
646
647 typedef int(WINAPI *pSnmpUtilOidCpy) (
648 OUT AsnObjectIdentifier *pOidDst,
649 IN AsnObjectIdentifier *pOidSrc);
650
651 typedef int(WINAPI *pSnmpUtilOidNCmp) (
652 IN AsnObjectIdentifier *pOid1,
653 IN AsnObjectIdentifier *pOid2,
654 IN UINT nSubIds);
655
656 typedef void(WINAPI *pSnmpUtilVarBindFree) (
657 IN OUT SnmpVarBind *pVb);
658
659 typedef bool(WINAPI *pSnmpExtensionInit) (
660 IN DWORD dwTimeZeroReference,
661 OUT HANDLE *hPollForTrapEvent,
662 OUT AsnObjectIdentifier *supportedView);
663
664 typedef bool(WINAPI *pSnmpExtensionTrap) (
665 OUT AsnObjectIdentifier *enterprise,
666 OUT AsnInteger32 *genericTrap,
667 OUT AsnInteger32 *specificTrap,
668 OUT AsnTimeticks *timeStamp,
669 OUT SnmpVarBindList *variableBindings);
670
671 typedef bool(WINAPI *pSnmpExtensionQuery) (
672 IN BYTE requestType,
673 IN OUT SnmpVarBindList *variableBindings,
674 OUT AsnInteger32 *errorStatus,
675 OUT AsnInteger32 *errorIndex);
676
677 typedef bool(WINAPI *pSnmpExtensionInitEx) (
678 OUT AsnObjectIdentifier *supportedView);
679
680 typedef struct _ASTAT_
681 {
682 ADAPTER_STATUS adapt;
683 NAME_BUFFER NameBuff[30];
684 } ASTAT, *PASTAT;
685
686 /* get the MAC address of the (first) Ethernet adapter (6 bytes) */
getMACAddress(unsigned char buffer[6])687 static unsigned char *getMACAddress(unsigned char buffer[6])
688 {
689 OFBool success = OFFalse;
690 /* init return variable */
691 memset(buffer, 0, sizeof(buffer));
692 NCB ncb;
693 memset(&ncb, 0, sizeof(ncb));
694 /* reset the LAN adapter */
695 ncb.ncb_command = NCBRESET;
696 /* it is considered bad practice to hardcode the LANA number (should enumerate
697 adapters first), but at least this approach also works on Windows 9x */
698 ncb.ncb_lana_num = 0;
699 if (Netbios(&ncb) == NRC_GOODRET)
700 {
701 ASTAT Adapter;
702 /* prepare to get the adapter status block */
703 memset(&ncb, 0, sizeof(ncb));
704 ncb.ncb_command = NCBASTAT;
705 /* it is considered bad practice to hardcode the LANA number (should enumerate
706 adapters first), but at least this approach also works on Windows 9x */
707 ncb.ncb_lana_num = 0;
708 strcpy((char *)ncb.ncb_callname, "*");
709 ncb.ncb_buffer = (unsigned char *)&Adapter;
710 ncb.ncb_length = sizeof(Adapter);
711 /* get the adapter's info */
712 if (Netbios(&ncb) == 0)
713 {
714 /* store the MAC address */
715 buffer[0] = Adapter.adapt.adapter_address[0];
716 buffer[1] = Adapter.adapt.adapter_address[1];
717 buffer[2] = Adapter.adapt.adapter_address[2];
718 buffer[3] = Adapter.adapt.adapter_address[3];
719 buffer[4] = Adapter.adapt.adapter_address[4];
720 buffer[5] = Adapter.adapt.adapter_address[5];
721 success = OFTrue;
722 }
723 }
724 /* check whether NetBIOS routines succeeded, if not try the SNMP approach */
725 if (!success)
726 {
727 HINSTANCE m_hInst1, m_hInst2;
728 /* load the "SNMP Utility Library" dll and get the addresses of the functions necessary */
729 m_hInst1 = LoadLibrary("snmpapi.dll");
730 if (m_hInst1 >= (HINSTANCE)HINSTANCE_ERROR)
731 {
732 pSnmpUtilOidCpy m_Copy = (pSnmpUtilOidCpy)GetProcAddress(m_hInst1, "SnmpUtilOidCpy");
733 pSnmpUtilOidNCmp m_Compare = (pSnmpUtilOidNCmp)GetProcAddress(m_hInst1, "SnmpUtilOidNCmp");
734 pSnmpUtilVarBindFree m_BindFree = (pSnmpUtilVarBindFree)GetProcAddress(m_hInst1, "SnmpUtilVarBindFree");
735 /* load the "SNMP Internet MIB" dll and get the addresses of the functions necessary */
736 m_hInst2 = LoadLibrary("inetmib1.dll");
737 if (m_hInst2 >= (HINSTANCE)HINSTANCE_ERROR)
738 {
739 HANDLE PollForTrapEvent;
740 AsnObjectIdentifier SupportedView;
741 UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3};
742 UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1};
743 UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6};
744 AsnObjectIdentifier MIB_ifMACEntAddr = {sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr};
745 AsnObjectIdentifier MIB_ifEntryType = {sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType};
746 AsnObjectIdentifier MIB_ifEntryNum = {sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum};
747 SnmpVarBindList varBindList;
748 SnmpVarBind varBind[2];
749 AsnInteger32 errorStatus;
750 AsnInteger32 errorIndex;
751 AsnObjectIdentifier MIB_NULL = {0, 0};
752 int ret;
753 int dtmp;
754 int i = 0, j = 0;
755 bool found = false;
756 pSnmpExtensionInit m_Init = (pSnmpExtensionInit)GetProcAddress(m_hInst2, "SnmpExtensionInit");
757 pSnmpExtensionInitEx m_InitEx = (pSnmpExtensionInitEx)GetProcAddress(m_hInst2, "SnmpExtensionInitEx");
758 pSnmpExtensionQuery m_Query = (pSnmpExtensionQuery)GetProcAddress(m_hInst2, "SnmpExtensionQuery");
759 pSnmpExtensionTrap m_Trap = (pSnmpExtensionTrap)GetProcAddress(m_hInst2, "SnmpExtensionTrap");
760 m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);
761 /* initialize the variable list to be retrieved by m_Query */
762 varBindList.list = varBind;
763 varBind[0].name = MIB_NULL;
764 varBind[1].name = MIB_NULL;
765 /* copy in the OID to find the number of entries in the interface table */
766 varBindList.len = 1; /* only retrieving one item */
767 m_Copy(&varBind[0].name, &MIB_ifEntryNum);
768 ret = m_Query(SNMP_PDU_GETNEXT, &varBindList, &errorStatus, &errorIndex);
769 varBindList.len = 2;
770 /* copy in the OID of ifType, the type of interface */
771 m_Copy(&varBind[0].name, &MIB_ifEntryType);
772 /* copy in the OID of ifPhysAddress, the address */
773 m_Copy(&varBind[1].name, &MIB_ifMACEntAddr);
774 do {
775 /* Submit the query. Responses will be loaded into varBindList.
776 We can expect this call to succeed a # of times corresponding
777 to the # of adapters reported to be in the system */
778 ret = m_Query(SNMP_PDU_GETNEXT, &varBindList, &errorStatus, &errorIndex);
779 if (!ret)
780 ret = 1;
781 else
782 {
783 /* confirm that the proper type has been returned */
784 ret = m_Compare(&varBind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength);
785 }
786 if (!ret)
787 {
788 j++;
789 dtmp = varBind[0].value.asnValue.number;
790 /* type 6 describes ethernet interfaces */
791 if (dtmp == 6)
792 {
793 /* confirm that we have an address here */
794 ret = m_Compare(&varBind[1].name, &MIB_ifMACEntAddr,MIB_ifMACEntAddr.idLength);
795 if ((!ret) && (varBind[1].value.asnValue.address.stream != NULL))
796 {
797 if ((varBind[1].value.asnValue.address.stream[0] == 0x44) &&
798 (varBind[1].value.asnValue.address.stream[1] == 0x45) &&
799 (varBind[1].value.asnValue.address.stream[2] == 0x53) &&
800 (varBind[1].value.asnValue.address.stream[3] == 0x54) &&
801 (varBind[1].value.asnValue.address.stream[4] == 0x00))
802 {
803 /* ignore all dial-up networking adapters */
804 continue;
805 }
806 if ((varBind[1].value.asnValue.address.stream[0] == 0x00) &&
807 (varBind[1].value.asnValue.address.stream[1] == 0x00) &&
808 (varBind[1].value.asnValue.address.stream[2] == 0x00) &&
809 (varBind[1].value.asnValue.address.stream[3] == 0x00) &&
810 (varBind[1].value.asnValue.address.stream[4] == 0x00) &&
811 (varBind[1].value.asnValue.address.stream[5] == 0x00))
812 {
813 /* ignore NULL addresses returned by other network interfaces */
814 continue;
815 }
816 /* store the MAC address */
817 buffer[0] = varBind[1].value.asnValue.address.stream[0];
818 buffer[1] = varBind[1].value.asnValue.address.stream[1];
819 buffer[2] = varBind[1].value.asnValue.address.stream[2];
820 buffer[3] = varBind[1].value.asnValue.address.stream[3];
821 buffer[4] = varBind[1].value.asnValue.address.stream[4];
822 buffer[5] = varBind[1].value.asnValue.address.stream[5];
823 ret = 1; // we found an address -> exit
824 }
825 }
826 }
827 } while (!ret); /* Stop only on an error. An error will occur when we
828 go exhaust the list of interfaces to be examined */
829 FreeLibrary(m_hInst2);
830 /* free the bindings */
831 m_BindFree(&varBind[0]);
832 m_BindFree(&varBind[1]);
833 }
834 FreeLibrary(m_hInst1);
835 }
836 }
837 return buffer;
838 }
839 #endif
840
841 #ifdef HAVE_PROTOTYPE_GETHOSTID
842 /* CW10 has a prototype but no implementation (gethostid() is already declared extern */
gethostid(void)843 long gethostid(void)
844 #else
845 static long gethostid(void)
846 #endif
847 {
848 long result = 0;
849 #if defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)
850 char name[1024];
851 struct hostent *hent = NULL;
852 char **p = NULL;
853 struct in_addr in;
854 #ifdef HAVE_WINSOCK_H
855 WSAData winSockData;
856 /* we need at least version 1.1 */
857 WORD winSockVersionNeeded = MAKEWORD(1, 1);
858 WSAStartup(winSockVersionNeeded, &winSockData);
859 #endif
860 /*
861 ** Define the hostid to be the system's main TCP/IP address.
862 ** This is not perfect but it is better than nothing (i.e. using zero)
863 */
864 if (gethostname(name, 1024) == 0)
865 {
866 #if defined(_REENTRANT) && !defined(_WIN32) && !defined(__CYGWIN__)
867 // use gethostbyname_r instead of gethostbyname
868 int h_errnop=0;
869 struct hostent theHostent;
870 char buffer[GETHOSTBYNAME_R_BUFSIZE];
871 if ((hent = gethostbyname_r(name, &theHostent, buffer, GETHOSTBYNAME_R_BUFSIZE, &h_errnop)) != NULL)
872 #else
873 if ((hent = gethostbyname(name)) != NULL)
874 #endif
875 {
876 p = hent->h_addr_list;
877 if (p && *p)
878 {
879 (void) memcpy(&in.s_addr, *p, sizeof(in.s_addr));
880 result = (long)in.s_addr;
881 }
882 }
883 }
884 #ifdef HAVE_WINSOCK_H
885 WSACleanup();
886 #endif
887 #endif /* defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME) */
888 /* on Windows systems determine some system specific information (e.g. MAC address) */
889 #ifdef HAVE_WINDOWS_H
890 OFCRC32 crc;
891 /* get some processor specific information in addition to the MAC address */
892 SYSTEM_INFO systemInfo;
893 GetSystemInfo(&systemInfo);
894 /* get volume information of the system drive */
895 char systemDrive[MAX_PATH];
896 DWORD serialNumber = 0;
897 if (GetSystemDirectory(systemDrive, sizeof(systemDrive)) >= 0)
898 {
899 /* check for proper pathname */
900 if ((strlen(systemDrive) >= 3) && (systemDrive[1] == ':') && (systemDrive[2] == '\\'))
901 {
902 /* truncate the pathname directly after the drive specification */
903 systemDrive[3] = 0;
904 if (!GetVolumeInformation(systemDrive, NULL, 0, &serialNumber, NULL, NULL, NULL, 0))
905 serialNumber = 0;
906 }
907 }
908 unsigned char buffer[6];
909 /* concatenate the host specific elements and compute a 32-bit checksum */
910 crc.addBlock(&result /*ip address*/, sizeof(result));
911 crc.addBlock(getMACAddress(buffer), sizeof(buffer));
912 crc.addBlock(&serialNumber, sizeof(serialNumber));
913 crc.addBlock(&systemInfo.wProcessorLevel, sizeof(systemInfo.wProcessorLevel));
914 crc.addBlock(&systemInfo.wProcessorRevision, sizeof(systemInfo.wProcessorRevision));
915 crc.addBlock(&systemInfo.dwProcessorType, sizeof(systemInfo.dwProcessorType));
916 result = (long)crc.getCRC32();
917 #endif
918 /* 'artificial' hostid: on Windows system a CRC32 checksum over some host specific
919 information (e.g. MAC address), the 4 bytes TCP/IP address otherwise.
920 */
921 return result;
922 }
923
924 #else // !(defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME))
925 /*
926 ** last chance workaround if there is no other way
927 */
928 #ifdef HAVE_PROTOTYPE_GETHOSTID
929 /* CW10 has a prototype but no implementation (gethostid() is already declared extern */
gethostid(void)930 long gethostid(void) { return 0; }
931 #else
gethostid(void)932 static long gethostid(void) { return 0; }
933 #endif
934 #endif // !(defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME))
935
936 #endif // !HAVE_SYSINFO
937 #else // HAVE_GETHOSTID
938 #ifndef HAVE_PROTOTYPE_GETHOSTID
939 extern "C" {
940 long gethostid(void);
941 }
942 #endif // !HAVE_PROTOTYPE_GETHOSTID
943 #endif // HAVE_GETHOSTID
944
945 #ifndef HAVE_GETPID
getpid(void)946 static int getpid(void) { return 0; } // workaround for MAC
947 #endif // !HAVE_GETPID
948
949 // ********************************
950
951 /*
952 * Global variable storing the return value of gethostid().
953 * Since the variable is not declared in the header file it can only be used
954 * within this source file. Any access to or modification of its value is
955 * protected by a mutex (see dcmGenerateUniqueIdentifier()).
956 */
957
958 static unsigned long hostIdentifier = 0;
959
960
961 /*
962 ** char* generateUniqueIdentifer(char* buf)
963 ** Creates a Unique Identifer in buf and returns buf.
964 ** buf must be at least 65 bytes.
965 */
966
967
968 #ifdef _REENTRANT
969 static OFMutex uidCounterMutex; // mutex protecting access to counterOfCurrentUID and hostIdentifier
970 #endif
971
972 static unsigned int counterOfCurrentUID = 1;
973
974 static const int maxUIDLen = 64; /* A UID may be 64 chars or less */
975
976 static char*
stripTrailing(char * s,char c)977 stripTrailing(char* s, char c)
978 {
979 int i, n;
980
981 if (s == NULL) return s;
982
983 n = strlen(s);
984 for (i = n - 1; (i >= 0) && (s[i] == c); i--)
985 s[i] = '\0';
986 return s;
987 }
988
989 static void
addUIDComponent(char * uid,const char * s)990 addUIDComponent(char* uid, const char* s)
991 {
992 int charsLeft = maxUIDLen - strlen(uid);
993
994 if (charsLeft > 0) {
995 /* copy into uid as much of the contents of s as possible */
996 int slen = strlen(s);
997 int use = charsLeft;
998 if (slen < charsLeft) use = slen;
999 strncat(uid, s, use);
1000 }
1001
1002 stripTrailing(uid, '.');
1003 }
1004
1005 inline static unsigned long
forcePositive(long i)1006 forcePositive(long i)
1007 {
1008 return (i < 0) ? (unsigned long)-i : (unsigned long)i;
1009 }
1010
dcmGenerateUniqueIdentifier(char * uid,const char * prefix)1011 char* dcmGenerateUniqueIdentifier(char* uid, const char* prefix)
1012 {
1013 char buf[128]; /* be very safe */
1014
1015 uid[0] = '\0'; /* initialise */
1016
1017 #ifdef _REENTRANT
1018 uidCounterMutex.lock();
1019 #endif
1020 if (hostIdentifier == 0)
1021 hostIdentifier = (unsigned long)gethostid();
1022 unsigned int counter = counterOfCurrentUID++;
1023 #ifdef _REENTRANT
1024 uidCounterMutex.unlock();
1025 #endif
1026
1027 if (prefix != NULL ) {
1028 addUIDComponent(uid, prefix);
1029 } else {
1030 addUIDComponent(uid, SITE_INSTANCE_UID_ROOT);
1031 }
1032
1033 sprintf(buf, ".%lu", hostIdentifier);
1034 addUIDComponent(uid, buf);
1035
1036 sprintf(buf, ".%lu", forcePositive(getpid()));
1037 addUIDComponent(uid, buf);
1038
1039 sprintf(buf, ".%lu", forcePositive(long(time(NULL))));
1040 addUIDComponent(uid, buf);
1041
1042 sprintf(buf, ".%u", counter);
1043
1044 addUIDComponent(uid, buf);
1045
1046 return uid;
1047 }
1048