Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/register.c
5968 views
1
/*
2
* Generation of dll registration scripts
3
*
4
* Copyright 2010 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 <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <ctype.h>
27
28
#include "widl.h"
29
#include "utils.h"
30
#include "parser.h"
31
#include "header.h"
32
#include "typegen.h"
33
#include "typelib.h"
34
35
static int indent;
36
37
static const char *format_uuid( const struct uuid *uuid )
38
{
39
static char buffer[40];
40
snprintf( buffer, sizeof(buffer),
41
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
42
uuid->Data1, uuid->Data2, uuid->Data3,
43
uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3],
44
uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] );
45
return buffer;
46
}
47
48
static const char *get_coclass_threading( const type_t *class )
49
{
50
static const char * const models[] =
51
{
52
NULL,
53
"Apartment", /* THREADING_APARTMENT */
54
"Neutral", /* THREADING_NEUTRAL */
55
"Single", /* THREADING_SINGLE */
56
"Free", /* THREADING_FREE */
57
"Both", /* THREADING_BOTH */
58
};
59
return models[get_attrv( class->attrs, ATTR_THREADING )];
60
}
61
62
static const type_t *find_ps_factory( const statement_list_t *stmts )
63
{
64
const statement_t *stmt;
65
66
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
67
{
68
if (stmt->type == STMT_TYPE)
69
{
70
const type_t *type = stmt->u.type;
71
if (type_get_type(type) == TYPE_COCLASS && !strcmp( type->name, "PSFactoryBuffer" ))
72
return type;
73
}
74
}
75
return NULL;
76
}
77
78
static void write_interface( const type_t *iface, const type_t *ps_factory )
79
{
80
const struct uuid *uuid = get_attrp( iface->attrs, ATTR_UUID );
81
const struct uuid *ps_uuid = get_attrp( ps_factory->attrs, ATTR_UUID );
82
83
if (!uuid) return;
84
if (!is_object( iface )) return;
85
if (!type_iface_get_inherit(iface)) /* special case for IUnknown */
86
{
87
put_str( indent, "'%s' = s '%s'\n", format_uuid( uuid ), iface->name );
88
return;
89
}
90
if (is_local( iface->attrs )) return;
91
put_str( indent, "'%s' = s '%s'\n", format_uuid( uuid ), iface->name );
92
put_str( indent, "{\n" );
93
indent++;
94
put_str( indent, "NumMethods = s %u\n", count_methods( iface ));
95
put_str( indent, "ProxyStubClsid32 = s '%s'\n", format_uuid( ps_uuid ));
96
indent--;
97
put_str( indent, "}\n" );
98
}
99
100
static void write_interfaces( const statement_list_t *stmts, const type_t *ps_factory )
101
{
102
const statement_t *stmt;
103
104
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
105
{
106
if (stmt->type == STMT_TYPE && type_get_type( stmt->u.type ) == TYPE_INTERFACE)
107
write_interface( stmt->u.type, ps_factory );
108
}
109
}
110
111
static void write_typelib_interface( const type_t *iface, const typelib_t *typelib )
112
{
113
const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
114
const struct uuid *uuid = get_attrp( iface->attrs, ATTR_UUID );
115
unsigned short major, minor;
116
117
get_version( typelib->attrs, &major, &minor );
118
119
if (!uuid) return;
120
if (!is_object( iface )) return;
121
put_str( indent, "'%s' = s '%s'\n", format_uuid( uuid ), iface->name );
122
put_str( indent, "{\n" );
123
indent++;
124
put_str( indent, "ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'\n" );
125
put_str( indent, "ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'\n" );
126
if (major || minor)
127
put_str( indent, "TypeLib = s '%s' { val Version = s '%u.%u' }\n",
128
format_uuid( typelib_uuid ), major, minor );
129
else
130
put_str( indent, "TypeLib = s '%s'", format_uuid( typelib_uuid ));
131
indent--;
132
put_str( indent, "}\n" );
133
}
134
135
static void write_typelib_interfaces( const typelib_t *typelib )
136
{
137
unsigned int i;
138
139
for (i = 0; i < typelib->reg_iface_count; ++i)
140
write_typelib_interface( typelib->reg_ifaces[i], typelib );
141
}
142
143
static int write_coclass( const type_t *class, const typelib_t *typelib )
144
{
145
const struct uuid *uuid = get_attrp( class->attrs, ATTR_UUID );
146
const char *descr = get_attrp( class->attrs, ATTR_HELPSTRING );
147
const char *progid = get_attrp( class->attrs, ATTR_PROGID );
148
const char *vi_progid = get_attrp( class->attrs, ATTR_VIPROGID );
149
const char *threading = get_coclass_threading( class );
150
unsigned short major, minor;
151
152
get_version( class->attrs, &major, &minor );
153
154
if (!uuid) return 0;
155
if (typelib && !threading && !progid) return 0;
156
if (!descr) descr = class->name;
157
158
put_str( indent, "'%s' = s '%s'\n", format_uuid( uuid ), descr );
159
put_str( indent++, "{\n" );
160
if (threading) put_str( indent, "InprocServer32 = s '%%MODULE%%' { val ThreadingModel = s '%s' }\n",
161
threading );
162
if (progid) put_str( indent, "ProgId = s '%s'\n", progid );
163
if (typelib)
164
{
165
const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
166
put_str( indent, "TypeLib = s '%s'\n", format_uuid( typelib_uuid ));
167
if (!(major && minor))
168
get_version( typelib->attrs, &major, &minor );
169
}
170
if (major || minor) put_str( indent, "Version = s '%u.%u'\n", major, minor );
171
if (vi_progid) put_str( indent, "VersionIndependentProgId = s '%s'\n", vi_progid );
172
put_str( --indent, "}\n" );
173
return 1;
174
}
175
176
static void write_coclasses( const statement_list_t *stmts, const typelib_t *typelib )
177
{
178
const statement_t *stmt;
179
180
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
181
{
182
if (stmt->type == STMT_TYPE)
183
{
184
const type_t *type = stmt->u.type;
185
if (type_get_type(type) == TYPE_COCLASS) write_coclass( type, typelib );
186
}
187
}
188
}
189
190
static void write_runtimeclasses_registry( const statement_list_t *stmts )
191
{
192
const statement_t *stmt;
193
const type_t *type;
194
195
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
196
{
197
if (stmt->type != STMT_TYPE && stmt->type != STMT_TYPEREF) continue;
198
if (stmt->type == STMT_TYPEREF && strcmp( stmt->where.input_name, input_name )) continue; /* ignore #included statements */
199
if (type_get_type((type = stmt->u.type)) != TYPE_RUNTIMECLASS) continue;
200
if (!get_attrp(type->attrs, ATTR_ACTIVATABLE) && !get_attrp(type->attrs, ATTR_STATIC)) continue;
201
put_str( indent, "ForceRemove %s\n", format_namespace( type->namespace, "", ".", type->name, NULL ) );
202
put_str( indent++, "{\n" );
203
put_str( indent, "val 'DllPath' = s '%%MODULE%%'\n" );
204
put_str( --indent, "}\n" );
205
}
206
}
207
208
static int write_progid( const type_t *class )
209
{
210
const struct uuid *uuid = get_attrp( class->attrs, ATTR_UUID );
211
const char *descr = get_attrp( class->attrs, ATTR_HELPSTRING );
212
const char *progid = get_attrp( class->attrs, ATTR_PROGID );
213
const char *vi_progid = get_attrp( class->attrs, ATTR_VIPROGID );
214
215
if (!uuid) return 0;
216
if (!descr) descr = class->name;
217
218
if (progid)
219
{
220
put_str( indent, "'%s' = s '%s'\n", progid, descr );
221
put_str( indent++, "{\n" );
222
put_str( indent, "CLSID = s '%s'\n", format_uuid( uuid ) );
223
put_str( --indent, "}\n" );
224
}
225
if (vi_progid)
226
{
227
put_str( indent, "'%s' = s '%s'\n", vi_progid, descr );
228
put_str( indent++, "{\n" );
229
put_str( indent, "CLSID = s '%s'\n", format_uuid( uuid ) );
230
if (progid && strcmp( progid, vi_progid )) put_str( indent, "CurVer = s '%s'\n", progid );
231
put_str( --indent, "}\n" );
232
}
233
return 1;
234
}
235
236
static void write_progids( const statement_list_t *stmts )
237
{
238
const statement_t *stmt;
239
240
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
241
{
242
if (stmt->type == STMT_TYPE)
243
{
244
const type_t *type = stmt->u.type;
245
if (type_get_type(type) == TYPE_COCLASS) write_progid( type );
246
}
247
}
248
}
249
250
void write_regscript( const statement_list_t *stmts )
251
{
252
const type_t *ps_factory;
253
254
if (!do_regscript) return;
255
if (do_everything && !need_proxy_file( stmts )) return;
256
257
init_output_buffer();
258
259
if (winrt_mode)
260
{
261
put_str( indent, "HKLM\n" );
262
put_str( indent++, "{\n" );
263
put_str( indent, "NoRemove Software\n" );
264
put_str( indent++, "{\n" );
265
put_str( indent, "NoRemove Microsoft\n" );
266
put_str( indent++, "{\n" );
267
put_str( indent, "NoRemove WindowsRuntime\n" );
268
put_str( indent++, "{\n" );
269
put_str( indent, "NoRemove ActivatableClassId\n" );
270
put_str( indent++, "{\n" );
271
write_runtimeclasses_registry( stmts );
272
put_str( --indent, "}\n" );
273
put_str( --indent, "}\n" );
274
put_str( --indent, "}\n" );
275
put_str( --indent, "}\n" );
276
put_str( --indent, "}\n" );
277
}
278
else
279
{
280
put_str( indent, "HKCR\n" );
281
put_str( indent++, "{\n" );
282
283
ps_factory = find_ps_factory( stmts );
284
if (ps_factory)
285
{
286
put_str( indent, "NoRemove Interface\n" );
287
put_str( indent++, "{\n" );
288
write_interfaces( stmts, ps_factory );
289
put_str( --indent, "}\n" );
290
}
291
292
put_str( indent, "NoRemove CLSID\n" );
293
put_str( indent++, "{\n" );
294
write_coclasses( stmts, NULL );
295
put_str( --indent, "}\n" );
296
297
write_progids( stmts );
298
put_str( --indent, "}\n" );
299
}
300
301
if (strendswith( regscript_name, ".res" )) /* create a binary resource file */
302
{
303
add_output_to_resources( "WINE_REGISTRY", regscript_token );
304
flush_output_resources( regscript_name );
305
}
306
else
307
{
308
FILE *f = fopen( regscript_name, "w" );
309
if (!f) error( "Could not open %s for output\n", regscript_name );
310
if (fwrite( output_buffer, 1, output_buffer_pos, f ) != output_buffer_pos)
311
error( "Failed to write to %s\n", regscript_name );
312
if (fclose( f ))
313
error( "Failed to write to %s\n", regscript_name );
314
}
315
}
316
317
void write_typelib_regscript( const statement_list_t *stmts )
318
{
319
const statement_t *stmt;
320
unsigned int count = 0;
321
322
if (!do_typelib) return;
323
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
324
{
325
if (stmt->type != STMT_LIBRARY) continue;
326
if (count && !strendswith( typelib_name, ".res" ))
327
error( "Cannot store multiple typelibs into %s\n", typelib_name );
328
else
329
{
330
if (old_typelib)
331
create_sltg_typelib( stmt->u.lib );
332
else
333
create_msft_typelib( stmt->u.lib );
334
}
335
count++;
336
}
337
if (count && strendswith( typelib_name, ".res" )) flush_output_resources( typelib_name );
338
}
339
340
void output_typelib_regscript( const typelib_t *typelib )
341
{
342
const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID );
343
const char *descr = get_attrp( typelib->attrs, ATTR_HELPSTRING );
344
const expr_t *lcid_expr = get_attrp( typelib->attrs, ATTR_LIBLCID );
345
unsigned short major, minor;
346
unsigned int flags = 0;
347
char id_part[12] = "";
348
char *resname = typelib_name;
349
expr_t *expr;
350
351
get_version( typelib->attrs, &major, &minor );
352
353
if (is_attr( typelib->attrs, ATTR_RESTRICTED )) flags |= 1; /* LIBFLAG_FRESTRICTED */
354
if (is_attr( typelib->attrs, ATTR_CONTROL )) flags |= 2; /* LIBFLAG_FCONTROL */
355
if (is_attr( typelib->attrs, ATTR_HIDDEN )) flags |= 4; /* LIBFLAG_FHIDDEN */
356
357
put_str( indent, "HKCR\n" );
358
put_str( indent++, "{\n" );
359
360
put_str( indent, "NoRemove Typelib\n" );
361
put_str( indent++, "{\n" );
362
put_str( indent, "NoRemove '%s'\n", format_uuid( typelib_uuid ));
363
put_str( indent++, "{\n" );
364
put_str( indent, "'%u.%u' = s '%s'\n", major, minor, descr ? descr : typelib->name );
365
put_str( indent++, "{\n" );
366
expr = get_attrp( typelib->attrs, ATTR_ID );
367
if (expr)
368
{
369
snprintf(id_part, sizeof(id_part), "\\%d", expr->cval);
370
resname = strmake("%s\\%d", typelib_name, expr->cval);
371
}
372
put_str( indent, "'%x' { %s = s '%%MODULE%%%s' }\n",
373
lcid_expr ? lcid_expr->cval : 0, pointer_size == 8 ? "win64" : "win32", id_part );
374
put_str( indent, "FLAGS = s '%u'\n", flags );
375
put_str( --indent, "}\n" );
376
put_str( --indent, "}\n" );
377
put_str( --indent, "}\n" );
378
379
put_str( indent, "NoRemove Interface\n" );
380
put_str( indent++, "{\n" );
381
write_typelib_interfaces( typelib );
382
put_str( --indent, "}\n" );
383
384
put_str( indent, "NoRemove CLSID\n" );
385
put_str( indent++, "{\n" );
386
write_coclasses( typelib->stmts, typelib );
387
put_str( --indent, "}\n" );
388
389
write_progids( typelib->stmts );
390
put_str( --indent, "}\n" );
391
392
add_output_to_resources( "WINE_REGISTRY", resname );
393
}
394
395