2 * MSCMS - Color Management System for Wine
4 * Copyright 2004, 2005 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "mscms_priv.h"
32 static inline void adjust_endianness32( ULONG
*ptr
)
34 #ifndef WORDS_BIGENDIAN
35 *ptr
= RtlUlongByteSwap(*ptr
);
39 static const struct tag_entry
*first_tag( const struct profile
*profile
)
41 return (const struct tag_entry
*)(profile
->data
+ sizeof(PROFILEHEADER
) + sizeof(DWORD
));
44 void get_profile_header( const struct profile
*profile
, PROFILEHEADER
*header
)
48 memcpy( header
, profile
->data
, sizeof(PROFILEHEADER
) );
50 /* ICC format is big-endian, swap bytes if necessary */
51 for (i
= 0; i
< sizeof(PROFILEHEADER
) / sizeof(ULONG
); i
++)
52 adjust_endianness32( (ULONG
*)header
+ i
);
55 void set_profile_header( const struct profile
*profile
, const PROFILEHEADER
*header
)
59 memcpy( profile
->data
, header
, sizeof(PROFILEHEADER
) );
61 /* ICC format is big-endian, swap bytes if necessary */
62 for (i
= 0; i
< sizeof(PROFILEHEADER
) / sizeof(ULONG
); i
++)
63 adjust_endianness32( (ULONG
*)profile
->data
+ i
);
66 DWORD
get_tag_count( const struct profile
*profile
)
68 DWORD num_tags
= *(DWORD
*)(profile
->data
+ sizeof(PROFILEHEADER
));
69 adjust_endianness32( &num_tags
);
70 if ((const BYTE
*)(first_tag( profile
) + num_tags
) > (const BYTE
*)profile
->data
+ profile
->size
)
75 BOOL
get_tag_entry( const struct profile
*profile
, DWORD index
, struct tag_entry
*tag
)
77 const struct tag_entry
*entry
= first_tag( profile
);
79 if (index
< 1 || index
> get_tag_count( profile
)) return FALSE
;
80 *tag
= entry
[index
- 1];
81 adjust_endianness32( &tag
->sig
);
82 adjust_endianness32( &tag
->offset
);
83 adjust_endianness32( &tag
->size
);
84 if (tag
->offset
> profile
->size
|| tag
->size
> profile
->size
- tag
->offset
) return FALSE
;
88 BOOL
get_adjusted_tag( const struct profile
*profile
, TAGTYPE type
, struct tag_entry
*tag
)
90 const struct tag_entry
*entry
= first_tag( profile
);
93 for (i
= get_tag_count(profile
); i
> 0; i
--, entry
++)
96 adjust_endianness32( &sig
);
100 adjust_endianness32( &tag
->sig
);
101 adjust_endianness32( &tag
->offset
);
102 adjust_endianness32( &tag
->size
);
103 if (tag
->offset
> profile
->size
|| tag
->size
> profile
->size
- tag
->offset
) return FALSE
;
110 static BOOL
get_linked_tag( const struct profile
*profile
, struct tag_entry
*ret
)
112 const struct tag_entry
*entry
= first_tag( profile
);
113 DWORD sig
, offset
, size
, i
;
115 for (i
= get_tag_count(profile
); i
> 0; i
--, entry
++)
118 adjust_endianness32( &sig
);
119 if (sig
== ret
->sig
) continue;
120 offset
= entry
->offset
;
122 adjust_endianness32( &offset
);
123 adjust_endianness32( &size
);
124 if (size
== ret
->size
&& offset
== ret
->offset
)
133 BOOL
get_tag_data( const struct profile
*profile
, TAGTYPE type
, DWORD offset
, void *buffer
,
134 DWORD
*len
, BOOL
*linked
)
136 struct tag_entry tag
;
138 if (!get_adjusted_tag( profile
, type
, &tag
)) return FALSE
;
140 if (!buffer
) offset
= 0;
141 if (offset
> tag
.size
) return FALSE
;
142 if (*len
< tag
.size
- offset
|| !buffer
)
144 *len
= tag
.size
- offset
;
147 memcpy( buffer
, profile
->data
+ tag
.offset
+ offset
, tag
.size
- offset
);
148 *len
= tag
.size
- offset
;
149 if (linked
) *linked
= get_linked_tag( profile
, &tag
);
153 BOOL
set_tag_data( const struct profile
*profile
, TAGTYPE type
, DWORD offset
, const void *buffer
, DWORD
*len
)
155 struct tag_entry tag
;
157 if (!get_adjusted_tag( profile
, type
, &tag
)) return FALSE
;
159 if (offset
> tag
.size
) return FALSE
;
160 *len
= min( tag
.size
- offset
, *len
);
161 memcpy( profile
->data
+ tag
.offset
+ offset
, buffer
, *len
);