Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/lcms2/src/cmserr.c
Line
Count
Source
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2026 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
26
#include "lcms2_internal.h"
27
28
29
// This function is here to help applications to prevent mixing lcms versions on header and shared objects.
30
int CMSEXPORT cmsGetEncodedCMMversion(void)
31
0
{
32
0
       return LCMS_VERSION;
33
0
}
34
35
// I am so tired about incompatibilities on those functions that here are some replacements
36
// that hopefully would be fully portable.
37
38
// compare two strings ignoring case
39
int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
40
0
{
41
0
    CMSREGISTER const unsigned char *us1 = (const unsigned char *)s1,
42
0
                                 *us2 = (const unsigned char *)s2;
43
44
0
    while (toupper(*us1) == toupper(*us2++))
45
0
        if (*us1++ == '\0')
46
0
            return 0;
47
48
0
    return (toupper(*us1) - toupper(*--us2));
49
0
}
50
51
#ifdef CMS_LARGE_FILE_SUPPORT
52
53
long long int CMSEXPORT cmsfilelength(FILE* f)
54
{
55
    long long int p, n;
56
57
#ifdef CMS_IS_WINDOWS_
58
    p = _ftelli64(f);
59
    if (p == -1LL)
60
        return -1LL;
61
62
    if (_fseeki64(f, 0, SEEK_END) != 0)
63
        return -1LL;
64
65
    n = _ftelli64(f);
66
67
    if (_fseeki64(f, p, SEEK_SET) != 0)
68
        return -1LL;
69
#else
70
    p = (long long int) ftello(f);
71
    if (p < 0)
72
        return -1LL;
73
74
    if (fseeko(f, 0, SEEK_END) != 0)
75
        return -1LL;
76
77
    n = (long long int) ftello(f);
78
79
    if (fseeko(f, (off_t) p, SEEK_SET) != 0)
80
        return -1LL;
81
#endif
82
83
    return n;
84
}
85
86
#else
87
88
// long int because C99 specifies ftell in such way (7.19.9.2)
89
long int CMSEXPORT cmsfilelength(FILE* f)
90
0
{
91
0
    long int p, n;
92
93
0
    p = ftell(f);
94
0
    if (p == -1L)
95
0
        return -1L;
96
97
0
    if (fseek(f, 0, SEEK_END) != 0)
98
0
        return -1L;
99
100
0
    n = ftell(f);
101
102
0
    if (fseek(f, p, SEEK_SET) != 0)
103
0
        return -1L;
104
105
0
    return n;
106
0
}
107
108
#endif
109
110
// Memory handling ------------------------------------------------------------------
111
//
112
// This is the interface to low-level memory management routines. By default a simple
113
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
114
// amount of memory that can be reclaimed. This is mostly as a safety feature to prevent 
115
// bogus or evil code to allocate huge blocks that otherwise lcms would never need.
116
117
#ifdef CMS_LARGE_FILE_SUPPORT
118
#   define MAX_MEMORY_FOR_ALLOC  ((cmsUInt32Number)(1024U*1024U*2048U))
119
#else
120
10
#   define MAX_MEMORY_FOR_ALLOC  ((cmsUInt32Number)(1024U*1024U*512U))
121
#endif
122
123
// User may override this behaviour by using a memory plug-in, which basically replaces
124
// the default memory management functions. In this case, no check is performed and it
125
// is up to the plug-in writer to keep in the safe side. There are only three functions
126
// required to be implemented: malloc, realloc and free, although the user may want to
127
// replace the optional mallocZero, calloc and dup as well.
128
129
cmsBool   _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
130
131
// *********************************************************************************
132
133
// This is the default memory allocation function. It does a very coarse
134
// check of amount of memory, just to prevent exploits
135
static
136
void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
137
10
{
138
    // Never allow 0 or over maximum
139
10
    if (size == 0 || size > MAX_MEMORY_FOR_ALLOC) return NULL;
140
141
10
    return (void*) malloc(size);
142
143
0
    cmsUNUSED_PARAMETER(ContextID);
144
0
}
145
146
// Generic allocate & zero
147
static
148
void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size)
149
6
{
150
6
    void *pt = _cmsMalloc(ContextID, size);
151
6
    if (pt == NULL) return NULL;
152
153
6
    memset(pt, 0, size);
154
6
    return pt;
155
6
}
156
157
158
// The default free function. The only check proformed is against NULL pointers
159
static
160
void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr)
161
10
{
162
    // free(NULL) is defined a no-op by C99, therefore it is safe to
163
    // avoid the check, but it is here just in case...
164
165
10
    if (Ptr) free(Ptr);
166
167
10
    cmsUNUSED_PARAMETER(ContextID);
168
10
}
169
170
// The default realloc function. Again it checks for exploits. If Ptr is NULL,
171
// realloc behaves the same way as malloc and allocates a new block of size bytes.
172
static
173
void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
174
0
{
175
176
0
    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never realloc over 512Mb
177
178
0
    return realloc(Ptr, size);
179
180
0
    cmsUNUSED_PARAMETER(ContextID);
181
0
}
182
183
184
// The default calloc function. Allocates an array of num elements, each one of size bytes
185
// all memory is initialized to zero.
186
static
187
void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
188
0
{
189
0
    cmsUInt32Number Total = num * size;
190
191
    // Preserve calloc behaviour
192
0
    if (Total == 0) return NULL;
193
194
    // Safe check for overflow.
195
0
    if (num >= UINT_MAX / size) return NULL;
196
197
    // Check for overflow
198
0
    if (Total < num || Total < size) {
199
0
        return NULL;
200
0
    }
201
202
0
    if (Total > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never alloc over 512Mb
203
204
0
    return _cmsMallocZero(ContextID, Total);
205
0
}
206
207
// Generic block duplication
208
static
209
void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size)
210
0
{
211
0
    void* mem;
212
213
0
    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never dup over 512Mb
214
215
0
    mem = _cmsMalloc(ContextID, size);
216
217
0
    if (mem != NULL && Org != NULL)
218
0
        memmove(mem, Org, size);
219
220
0
    return mem;
221
0
}
222
223
224
// Pointers to memory manager functions in Context0
225
_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, 
226
                                              _cmsReallocDefaultFn, _cmsCallocDefaultFn,    _cmsDupDefaultFn
227
                                            };
228
229
230
// Reset and duplicate memory manager
231
void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
232
0
{
233
0
    _cmsAssert(ctx != NULL);
234
235
0
    if (src != NULL) {    
236
237
        // Duplicate
238
0
        ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType));  
239
0
    }
240
0
    else {
241
242
        // To reset it, we use the default allocators, which cannot be overridden
243
0
        ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
244
0
    } 
245
0
}
246
247
// Auxiliary to fill memory management functions from plugin (or context 0 defaults)
248
void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr)
249
0
{
250
0
    if (Plugin == NULL) {
251
252
0
        memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk));
253
0
    }
254
0
    else {
255
256
0
        ptr ->MallocPtr  = Plugin -> MallocPtr;
257
0
        ptr ->FreePtr    = Plugin -> FreePtr;
258
0
        ptr ->ReallocPtr = Plugin -> ReallocPtr;
259
260
        // Make sure we revert to defaults
261
0
        ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn;
262
0
        ptr ->CallocPtr    = _cmsCallocDefaultFn;
263
0
        ptr ->DupPtr       = _cmsDupDefaultFn;
264
      
265
0
        if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr;
266
0
        if (Plugin ->CallocPtr != NULL)     ptr ->CallocPtr     = Plugin -> CallocPtr;
267
0
        if (Plugin ->DupPtr != NULL)        ptr ->DupPtr        = Plugin -> DupPtr;
268
        
269
0
    }
270
0
}
271
272
273
// Plug-in replacement entry
274
cmsBool  _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data)
275
0
{
276
0
    cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;     
277
0
    _cmsMemPluginChunkType* ptr;
278
279
    // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. 
280
    // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the
281
    // context internal data should be malloc'ed by using those functions. 
282
0
    if (Data == NULL) {
283
284
0
       struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID;
285
286
       // Return to the default allocators
287
0
        if (ContextID != NULL) {
288
0
            ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager;
289
0
        }
290
0
        return TRUE;
291
0
    }
292
293
    // Check for required callbacks
294
0
    if (Plugin -> MallocPtr == NULL ||
295
0
        Plugin -> FreePtr == NULL ||
296
0
        Plugin -> ReallocPtr == NULL) return FALSE;
297
298
    // Set replacement functions
299
0
    ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
300
0
    if (ptr == NULL) 
301
0
        return FALSE;
302
303
0
    _cmsInstallAllocFunctions(Plugin, ptr);
304
0
    return TRUE;
305
0
}
306
307
// Generic allocate
308
void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
309
10
{
310
10
    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
311
10
    return ptr ->MallocPtr(ContextID, size);
312
10
}
313
314
// Generic allocate & zero
315
void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
316
6
{
317
6
    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
318
6
    return ptr->MallocZeroPtr(ContextID, size);
319
6
}
320
321
// Generic calloc
322
void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
323
0
{
324
0
    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
325
0
    return ptr->CallocPtr(ContextID, num, size);
326
0
}
327
328
// Generic reallocate
329
void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
330
0
{
331
0
    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
332
0
    return ptr->ReallocPtr(ContextID, Ptr, size);
333
0
}
334
335
// Generic free memory
336
void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
337
10
{
338
10
    if (Ptr != NULL) {
339
10
        _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
340
10
        ptr ->FreePtr(ContextID, Ptr);
341
10
    }
342
10
}
343
344
// Generic block duplication
345
void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
346
0
{
347
0
    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
348
0
    return ptr ->DupPtr(ContextID, Org, size);
349
0
}
350
351
// ********************************************************************************************
352
353
// Sub allocation takes care of many pointers of small size. The memory allocated in
354
// this way have be freed at once. Next function allocates a single chunk for linked list
355
// I prefer this method over realloc due to the big impact on xput realloc may have if
356
// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms)
357
static
358
_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial)
359
0
{
360
0
    _cmsSubAllocator_chunk* chunk;
361
362
    // 20K by default
363
0
    if (Initial == 0)
364
0
        Initial = 20*1024;
365
366
    // Create the container
367
0
    chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk));
368
0
    if (chunk == NULL) return NULL;
369
370
    // Initialize values
371
0
    chunk ->Block     = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial);
372
0
    if (chunk ->Block == NULL) {
373
374
        // Something went wrong
375
0
        _cmsFree(ContextID, chunk);
376
0
        return NULL;
377
0
    }
378
379
0
    chunk ->BlockSize = Initial;
380
0
    chunk ->Used      = 0;
381
0
    chunk ->next      = NULL;
382
383
0
    return chunk;
384
0
}
385
386
// The suballocated is nothing but a pointer to the first element in the list. We also keep
387
// the thread ID in this structure.
388
_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial)
389
0
{
390
0
    _cmsSubAllocator* sub;
391
392
    // Create the container
393
0
    sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator));
394
0
    if (sub == NULL) return NULL;
395
396
0
    sub ->ContextID = ContextID;
397
398
0
    sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial);
399
0
    if (sub ->h == NULL) {
400
0
        _cmsFree(ContextID, sub);
401
0
        return NULL;
402
0
    }
403
404
0
    return sub;
405
0
}
406
407
408
// Get rid of whole linked list
409
void _cmsSubAllocDestroy(_cmsSubAllocator* sub)
410
0
{
411
0
    _cmsSubAllocator_chunk *chunk, *n;
412
413
0
    for (chunk = sub ->h; chunk != NULL; chunk = n) {
414
415
0
        n = chunk->next;
416
0
        if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block);
417
0
        _cmsFree(sub ->ContextID, chunk);
418
0
    }
419
420
    // Free the header
421
0
    _cmsFree(sub ->ContextID, sub);
422
0
}
423
424
425
// Get a pointer to small memory block.
426
void*  _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
427
0
{
428
0
    cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used;
429
0
    cmsUInt8Number* ptr;
430
431
0
    size = _cmsALIGNMEM(size);
432
433
    // Check for memory. If there is no room, allocate a new chunk of double memory size.
434
0
    if (size > Free) {
435
436
0
        _cmsSubAllocator_chunk* chunk;
437
0
        cmsUInt32Number newSize;
438
439
0
        newSize = sub -> h ->BlockSize * 2;
440
0
        if (newSize < size) newSize = size;
441
442
0
        chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize);
443
0
        if (chunk == NULL) return NULL;
444
445
        // Link list
446
0
        chunk ->next = sub ->h;
447
0
        sub ->h    = chunk;
448
449
0
    }
450
451
0
    ptr =  sub -> h ->Block + sub -> h ->Used;
452
0
    sub -> h -> Used += size;
453
454
0
    return (void*) ptr;
455
0
}
456
457
// Duplicate in pool
458
void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size)
459
0
{
460
0
    void *NewPtr;
461
    
462
    // Dup of null pointer is also NULL
463
0
    if (ptr == NULL)
464
0
        return NULL;
465
466
0
    NewPtr = _cmsSubAlloc(s, size);
467
468
0
    if (ptr != NULL && NewPtr != NULL) {
469
0
        memcpy(NewPtr, ptr, size);
470
0
    }
471
472
0
    return NewPtr;
473
0
}
474
475
476
477
// Error logging ******************************************************************
478
479
// There is no error handling at all. When a function fails, it returns proper value.
480
// For example, all create functions does return NULL on failure. Other return FALSE
481
// It may be interesting, for the developer, to know why the function is failing.
482
// for that reason, lcms2 does offer a logging function. This function does receive
483
// a ENGLISH string with some clues on what is going wrong. You can show this
484
// info to the end user, or just create some sort of log.
485
// The logging function should NOT terminate the program, as this obviously can leave
486
// resources. It is the programmer's responsibility to check each function return code
487
// to make sure it didn't fail.
488
489
// Error messages are limited to MAX_ERROR_MESSAGE_LEN
490
491
2
#define MAX_ERROR_MESSAGE_LEN   1024
492
493
// ---------------------------------------------------------------------------------------------------------
494
495
// This is our default log error
496
static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
497
498
// Context0 storage, which is global
499
_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction };
500
501
// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value
502
// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients
503
void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, 
504
                            const struct _cmsContext_struct* src)
505
0
{    
506
0
    static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction };
507
0
    void* from;
508
     
509
0
     if (src != NULL) {
510
0
        from = src ->chunks[Logger];       
511
0
    }
512
0
    else {
513
0
       from = &LogErrorChunk;
514
0
    }
515
    
516
0
    ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType));   
517
0
}
518
519
// The default error logger does nothing.
520
static
521
void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
522
2
{
523
    // fprintf(stderr, "[lcms]: %s\n", Text);
524
    // fflush(stderr);
525
526
2
     cmsUNUSED_PARAMETER(ContextID);
527
2
     cmsUNUSED_PARAMETER(ErrorCode);
528
2
     cmsUNUSED_PARAMETER(Text);
529
2
}
530
531
// Change log error, context based
532
void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn)
533
0
{
534
0
    _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
535
536
0
    if (lhg != NULL) {
537
538
0
        if (Fn == NULL)
539
0
            lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction;
540
0
        else
541
0
            lhg -> LogErrorHandler = Fn;
542
0
    }
543
0
}
544
545
// Change log error, legacy
546
void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
547
0
{
548
0
    cmsSetLogErrorHandlerTHR(NULL, Fn);    
549
0
}
550
551
// Log an error
552
// ErrorText is a text holding an english description of error.
553
void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...)
554
2
{
555
2
    va_list args;
556
2
    char Buffer[MAX_ERROR_MESSAGE_LEN];
557
2
    _cmsLogErrorChunkType* lhg;
558
559
560
2
    va_start(args, ErrorText);
561
2
    vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
562
2
    va_end(args);
563
564
    // Check for the context, if specified go there. If not, go for the global
565
2
    lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
566
2
    if (lhg ->LogErrorHandler) {
567
2
        lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer);
568
2
    }   
569
2
}
570
571
// Utility function to print signatures
572
void _cmsTagSignature2String(char String[5], cmsTagSignature sig)
573
0
{
574
0
    cmsUInt32Number be;
575
576
    // Convert to big endian
577
0
    be = _cmsAdjustEndianess32((cmsUInt32Number) sig);
578
579
    // Move chars
580
0
    memmove(String, &be, 4);
581
582
    // Make sure of terminator
583
0
    String[4] = 0;
584
0
}
585
586
//--------------------------------------------------------------------------------------------------
587
588
589
static
590
void* defMtxCreate(cmsContext id)
591
2
{
592
2
    _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex));
593
2
    _cmsInitMutexPrimitive(ptr_mutex);
594
2
    return (void*) ptr_mutex;   
595
2
}
596
597
static
598
void defMtxDestroy(cmsContext id, void* mtx)
599
2
{
600
2
    _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); 
601
2
    _cmsFree(id, mtx);
602
2
}
603
604
static
605
cmsBool defMtxLock(cmsContext id, void* mtx)
606
0
{
607
0
    cmsUNUSED_PARAMETER(id);
608
0
    return _cmsLockPrimitive((_cmsMutex *) mtx) == 0;     
609
0
}
610
611
static
612
void defMtxUnlock(cmsContext id, void* mtx)
613
0
{
614
0
    cmsUNUSED_PARAMETER(id);
615
0
    _cmsUnlockPrimitive((_cmsMutex *) mtx); 
616
0
}
617
618
619
620
// Pointers to memory manager functions in Context0
621
_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
622
623
// Allocate and init mutex container.
624
void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, 
625
                                        const struct _cmsContext_struct* src)
626
0
{
627
0
    static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
628
0
    void* from;
629
     
630
0
     if (src != NULL) {
631
0
        from = src ->chunks[MutexPlugin];       
632
0
    }
633
0
    else {
634
0
       from = &MutexChunk;
635
0
    }
636
    
637
0
    ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType));   
638
0
}
639
640
// Register new ways to transform
641
cmsBool  _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data)
642
0
{
643
0
    cmsPluginMutex* Plugin = (cmsPluginMutex*) Data;
644
0
    _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
645
646
0
    if (Data == NULL) {
647
648
        // No lock routines
649
0
        ctx->CreateMutexPtr = NULL; 
650
0
        ctx->DestroyMutexPtr = NULL; 
651
0
        ctx->LockMutexPtr = NULL;
652
0
        ctx ->UnlockMutexPtr = NULL;
653
0
        return TRUE;
654
0
    }
655
656
    // Factory callback is required
657
0
    if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || 
658
0
        Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE;
659
660
0
    ctx->CreateMutexPtr  = Plugin->CreateMutexPtr;
661
0
    ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr;
662
0
    ctx ->LockMutexPtr   = Plugin ->LockMutexPtr;
663
0
    ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr;
664
665
    // All is ok
666
0
    return TRUE;
667
0
}
668
669
// Generic Mutex fns
670
void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID)
671
2
{
672
2
    _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
673
674
2
    if (ptr ->CreateMutexPtr == NULL) return NULL;
675
676
2
    return ptr ->CreateMutexPtr(ContextID);
677
2
}
678
679
void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx)
680
2
{
681
2
    _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
682
683
2
    if (ptr ->DestroyMutexPtr != NULL) {
684
685
2
        ptr ->DestroyMutexPtr(ContextID, mtx);
686
2
    }
687
2
}
688
689
cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx)
690
0
{
691
0
    _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
692
693
0
    if (ptr ->LockMutexPtr == NULL) return TRUE;
694
695
0
    return ptr ->LockMutexPtr(ContextID, mtx);
696
0
}
697
698
void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx)
699
0
{
700
0
    _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
701
702
0
    if (ptr ->UnlockMutexPtr != NULL) {
703
704
0
        ptr ->UnlockMutexPtr(ContextID, mtx);
705
0
    }
706
0
}
707
708
// The global Context0 storage for parallelization plug-in
709
 _cmsParallelizationPluginChunkType _cmsParallelizationPluginChunk = { 0 };
710
711
// Allocate parallelization container.
712
void _cmsAllocParallelizationPluginChunk(struct _cmsContext_struct* ctx,
713
                                         const struct _cmsContext_struct* src)
714
0
{    
715
0
    if (src != NULL) {
716
0
        void* from = src->chunks[ParallelizationPlugin];
717
0
        ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, from, sizeof(_cmsParallelizationPluginChunkType));
718
0
    }
719
0
    else {        
720
0
        _cmsParallelizationPluginChunkType ParallelizationPluginChunk = { 0 };
721
0
        ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &ParallelizationPluginChunk, sizeof(_cmsParallelizationPluginChunkType));
722
0
    }         
723
0
}
724
725
// Register parallel processing
726
cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Data)
727
0
{
728
0
    cmsPluginParalellization* Plugin = (cmsPluginParalellization*)Data;
729
0
    _cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin);
730
731
0
    if (Data == NULL) {
732
733
        // No parallelization routines
734
0
        ctx->MaxWorkers = 0;
735
0
        ctx->WorkerFlags = 0;
736
0
        ctx->SchedulerFn = NULL;        
737
0
        return TRUE;
738
0
    }
739
740
    // callback is required
741
0
    if (Plugin->SchedulerFn == NULL) return FALSE;
742
743
0
    ctx->MaxWorkers = Plugin->MaxWorkers;
744
0
    ctx->WorkerFlags = Plugin->WorkerFlags;
745
0
    ctx->SchedulerFn = Plugin->SchedulerFn;
746
    
747
    // All is ok
748
0
    return TRUE;
749
0
}
750