Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winebuild/res16.c
8729 views
1
/*
2
* Builtin dlls resource support
3
*
4
* Copyright 2000 Alexandre Julliard
5
*
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.
10
*
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.
15
*
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
19
*/
20
21
#include "config.h"
22
23
#include <assert.h>
24
#include <ctype.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <stdarg.h>
28
#include <stdio.h>
29
30
#include "build.h"
31
32
/* Unicode string or integer id */
33
struct string_id
34
{
35
char *str; /* ptr to string */
36
unsigned short id; /* integer id if str is NULL */
37
};
38
39
/* descriptor for a resource */
40
struct resource
41
{
42
struct string_id type;
43
struct string_id name;
44
const void *data;
45
unsigned int name_offset;
46
unsigned int data_size;
47
unsigned int memopt;
48
};
49
50
/* type level of the resource tree */
51
struct res_type
52
{
53
const struct string_id *type; /* type name */
54
struct resource *res; /* first resource of this type */
55
unsigned int name_offset; /* name offset if string */
56
unsigned int nb_names; /* total number of names */
57
};
58
59
static struct res_type *add_type( struct array *types, struct resource *res )
60
{
61
struct res_type *type = ARRAY_ADD( types, struct res_type );
62
type->type = &res->type;
63
type->res = res;
64
type->nb_names = 0;
65
return type;
66
}
67
68
/* get a string from the current resource file */
69
static void get_string( struct string_id *str )
70
{
71
unsigned char c = get_byte();
72
73
if (c == 0xff)
74
{
75
str->str = NULL;
76
str->id = get_word();
77
}
78
else
79
{
80
str->str = (char *)input_buffer + input_buffer_pos - 1;
81
str->id = 0;
82
while (get_byte()) /* nothing */;
83
}
84
}
85
86
/* load the next resource from the current file */
87
static void load_next_resource( DLLSPEC *spec )
88
{
89
struct resource *res = ARRAY_ADD( &spec->resources, struct resource );
90
91
get_string( &res->type );
92
get_string( &res->name );
93
res->memopt = get_word();
94
res->data_size = get_dword();
95
res->data = input_buffer + input_buffer_pos;
96
input_buffer_pos += res->data_size;
97
if (input_buffer_pos > input_buffer_size)
98
fatal_error( "%s is a truncated/corrupted file\n", input_buffer_filename );
99
}
100
101
/* load a Win16 .res file */
102
void load_res16_file( const char *name, DLLSPEC *spec )
103
{
104
init_input_buffer( name );
105
while (input_buffer_pos < input_buffer_size) load_next_resource( spec );
106
}
107
108
/* compare two strings/ids */
109
static int cmp_string( const struct string_id *str1, const struct string_id *str2 )
110
{
111
if (!str1->str)
112
{
113
if (!str2->str) return str1->id - str2->id;
114
return 1; /* an id compares larger than a string */
115
}
116
if (!str2->str) return -1;
117
return strcasecmp( str1->str, str2->str );
118
}
119
120
/* compare two resources for sorting the resource directory */
121
/* resources are stored first by type, then by name */
122
static int cmp_res( const void *ptr1, const void *ptr2 )
123
{
124
const struct resource *res1 = ptr1;
125
const struct resource *res2 = ptr2;
126
int ret;
127
128
if ((ret = cmp_string( &res1->type, &res2->type ))) return ret;
129
return cmp_string( &res1->name, &res2->name );
130
}
131
132
/* build the 2-level (type,name) resource tree */
133
static struct array build_resource_tree( DLLSPEC *spec )
134
{
135
unsigned int j, offset;
136
struct array types = empty_array;
137
struct res_type *type = NULL;
138
struct resource *res;
139
140
ARRAY_SORT( &spec->resources, struct resource, cmp_res );
141
142
offset = 2; /* alignment */
143
144
ARRAY_FOR_EACH( res, &spec->resources, struct resource )
145
{
146
if (!type || cmp_string( &res->type, &res[-1].type )) /* new type */
147
{
148
type = add_type( &types, res );
149
offset += 8;
150
}
151
type->nb_names++;
152
offset += 12;
153
}
154
offset += 2; /* terminator */
155
156
ARRAY_FOR_EACH( type, &types, struct res_type )
157
{
158
if (type->type->str)
159
{
160
type->name_offset = offset;
161
offset += strlen(type->type->str) + 1;
162
}
163
else type->name_offset = type->type->id | 0x8000;
164
165
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
166
{
167
if (res->name.str)
168
{
169
res->name_offset = offset;
170
offset += strlen(res->name.str) + 1;
171
}
172
else res->name_offset = res->name.id | 0x8000;
173
}
174
}
175
return types;
176
}
177
178
/* output a string preceded by its length */
179
static void output_string( const char *str )
180
{
181
unsigned int i, len = strlen(str);
182
output( "\t.byte 0x%02x", len );
183
for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)str[i] );
184
output( " /* %s */\n", str );
185
}
186
187
/* output a string preceded by its length in binary format*/
188
static void output_bin_string( const char *str )
189
{
190
put_byte( strlen(str) );
191
while (*str) put_byte( *str++ );
192
}
193
194
/* output the resource data */
195
void output_res16_data( DLLSPEC *spec )
196
{
197
unsigned int i = 0;
198
199
ARRAY_FOR_EACH( res, &spec->resources, const struct resource )
200
{
201
output( ".L__wine_spec_resource_%u:\n", i++ );
202
dump_bytes( res->data, res->data_size );
203
}
204
}
205
206
/* output the resource definitions */
207
void output_res16_directory( DLLSPEC *spec )
208
{
209
unsigned int j;
210
const struct resource *res;
211
struct array types = build_resource_tree( spec );
212
213
output( "\n.L__wine_spec_ne_rsrctab:\n" );
214
output( "\t.short 0\n" ); /* alignment */
215
216
/* type and name structures */
217
218
ARRAY_FOR_EACH( type, &types, const struct res_type )
219
{
220
output( "\t.short 0x%04x,%u,0,0\n", type->name_offset, type->nb_names );
221
222
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
223
{
224
output( "\t.short .L__wine_spec_resource_%lu-.L__wine_spec_dos_header,%u\n",
225
(unsigned long)(res - (struct resource *)spec->resources.data), res->data_size );
226
output( "\t.short 0x%04x,0x%04x,0,0\n", res->memopt, res->name_offset );
227
}
228
}
229
output( "\t.short 0\n" ); /* terminator */
230
231
/* name strings */
232
233
ARRAY_FOR_EACH( type, &types, const struct res_type )
234
{
235
if (type->type->str) output_string( type->type->str );
236
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
237
if (res->name.str) output_string( res->name.str );
238
}
239
output( "\t.byte 0\n" ); /* names terminator */
240
}
241
242
/* output the resource data in binary format */
243
void output_bin_res16_data( DLLSPEC *spec )
244
{
245
ARRAY_FOR_EACH( res, &spec->resources, const struct resource ) put_data( res->data, res->data_size );
246
}
247
248
/* output the resource definitions in binary format */
249
void output_bin_res16_directory( DLLSPEC *spec, unsigned int data_offset )
250
{
251
unsigned int j;
252
const struct resource *res;
253
struct array types = build_resource_tree( spec );
254
255
put_word( 0 ); /* alignment */
256
257
/* type and name structures */
258
259
ARRAY_FOR_EACH( type, &types, const struct res_type )
260
{
261
put_word( type->name_offset );
262
put_word( type->nb_names );
263
put_word( 0 );
264
put_word( 0 );
265
266
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
267
{
268
put_word( data_offset );
269
put_word( res->data_size );
270
put_word( res->memopt );
271
put_word( res->name_offset );
272
put_word( 0 );
273
put_word( 0 );
274
data_offset += res->data_size;
275
}
276
}
277
put_word( 0 ); /* terminator */
278
279
/* name strings */
280
281
ARRAY_FOR_EACH( type, &types, const struct res_type )
282
{
283
if (type->type->str) output_bin_string( type->type->str );
284
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
285
if (res->name.str) output_bin_string( res->name.str );
286
}
287
put_byte( 0 ); /* names terminator */
288
}
289
290