2 * Generation of dll registration scripts
4 * Copyright 2010 Alexandre Julliard
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
37 static const char *format_uuid( const struct uuid
*uuid
)
39 static char buffer
[40];
40 sprintf( buffer
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
41 uuid
->Data1
, uuid
->Data2
, uuid
->Data3
,
42 uuid
->Data4
[0], uuid
->Data4
[1], uuid
->Data4
[2], uuid
->Data4
[3],
43 uuid
->Data4
[4], uuid
->Data4
[5], uuid
->Data4
[6], uuid
->Data4
[7] );
47 static const char *get_coclass_threading( const type_t
*class )
49 static const char * const models
[] =
52 "Apartment", /* THREADING_APARTMENT */
53 "Neutral", /* THREADING_NEUTRAL */
54 "Single", /* THREADING_SINGLE */
55 "Free", /* THREADING_FREE */
56 "Both", /* THREADING_BOTH */
58 return models
[get_attrv( class->attrs
, ATTR_THREADING
)];
61 static const type_t
*find_ps_factory( const statement_list_t
*stmts
)
63 const statement_t
*stmt
;
65 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
67 if (stmt
->type
== STMT_TYPE
)
69 const type_t
*type
= stmt
->u
.type
;
70 if (type_get_type(type
) == TYPE_COCLASS
&& !strcmp( type
->name
, "PSFactoryBuffer" ))
77 static void write_interface( const type_t
*iface
, const type_t
*ps_factory
)
79 const struct uuid
*uuid
= get_attrp( iface
->attrs
, ATTR_UUID
);
80 const struct uuid
*ps_uuid
= get_attrp( ps_factory
->attrs
, ATTR_UUID
);
83 if (!is_object( iface
)) return;
84 if (!type_iface_get_inherit(iface
)) /* special case for IUnknown */
86 put_str( indent
, "'%s' = s '%s'\n", format_uuid( uuid
), iface
->name
);
89 if (is_local( iface
->attrs
)) return;
90 put_str( indent
, "'%s' = s '%s'\n", format_uuid( uuid
), iface
->name
);
91 put_str( indent
, "{\n" );
93 put_str( indent
, "NumMethods = s %u\n", count_methods( iface
));
94 put_str( indent
, "ProxyStubClsid32 = s '%s'\n", format_uuid( ps_uuid
));
96 put_str( indent
, "}\n" );
99 static void write_interfaces( const statement_list_t
*stmts
, const type_t
*ps_factory
)
101 const statement_t
*stmt
;
103 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
105 if (stmt
->type
== STMT_TYPE
&& type_get_type( stmt
->u
.type
) == TYPE_INTERFACE
)
106 write_interface( stmt
->u
.type
, ps_factory
);
110 static void write_typelib_interface( const type_t
*iface
, const typelib_t
*typelib
)
112 const struct uuid
*typelib_uuid
= get_attrp( typelib
->attrs
, ATTR_UUID
);
113 const struct uuid
*uuid
= get_attrp( iface
->attrs
, ATTR_UUID
);
114 unsigned int version
= get_attrv( typelib
->attrs
, ATTR_VERSION
);
117 if (!is_object( iface
)) return;
118 put_str( indent
, "'%s' = s '%s'\n", format_uuid( uuid
), iface
->name
);
119 put_str( indent
, "{\n" );
121 put_str( indent
, "ProxyStubClsid = s '{00020424-0000-0000-C000-000000000046}'\n" );
122 put_str( indent
, "ProxyStubClsid32 = s '{00020424-0000-0000-C000-000000000046}'\n" );
124 put_str( indent
, "TypeLib = s '%s' { val Version = s '%u.%u' }\n",
125 format_uuid( typelib_uuid
), MAJORVERSION(version
), MINORVERSION(version
) );
127 put_str( indent
, "TypeLib = s '%s'", format_uuid( typelib_uuid
));
129 put_str( indent
, "}\n" );
132 static void write_typelib_interfaces( const typelib_t
*typelib
)
136 for (i
= 0; i
< typelib
->reg_iface_count
; ++i
)
137 write_typelib_interface( typelib
->reg_ifaces
[i
], typelib
);
140 static int write_coclass( const type_t
*class, const typelib_t
*typelib
)
142 const struct uuid
*uuid
= get_attrp( class->attrs
, ATTR_UUID
);
143 const char *descr
= get_attrp( class->attrs
, ATTR_HELPSTRING
);
144 const char *progid
= get_attrp( class->attrs
, ATTR_PROGID
);
145 const char *vi_progid
= get_attrp( class->attrs
, ATTR_VIPROGID
);
146 const char *threading
= get_coclass_threading( class );
147 unsigned int version
= get_attrv( class->attrs
, ATTR_VERSION
);
150 if (typelib
&& !threading
&& !progid
) return 0;
151 if (!descr
) descr
= class->name
;
153 put_str( indent
, "'%s' = s '%s'\n", format_uuid( uuid
), descr
);
154 put_str( indent
++, "{\n" );
155 if (threading
) put_str( indent
, "InprocServer32 = s '%%MODULE%%' { val ThreadingModel = s '%s' }\n",
157 if (progid
) put_str( indent
, "ProgId = s '%s'\n", progid
);
160 const struct uuid
*typelib_uuid
= get_attrp( typelib
->attrs
, ATTR_UUID
);
161 put_str( indent
, "TypeLib = s '%s'\n", format_uuid( typelib_uuid
));
162 if (!version
) version
= get_attrv( typelib
->attrs
, ATTR_VERSION
);
164 if (version
) put_str( indent
, "Version = s '%u.%u'\n", MAJORVERSION(version
), MINORVERSION(version
) );
165 if (vi_progid
) put_str( indent
, "VersionIndependentProgId = s '%s'\n", vi_progid
);
166 put_str( --indent
, "}\n" );
170 static void write_coclasses( const statement_list_t
*stmts
, const typelib_t
*typelib
)
172 const statement_t
*stmt
;
174 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
176 if (stmt
->type
== STMT_TYPE
)
178 const type_t
*type
= stmt
->u
.type
;
179 if (type_get_type(type
) == TYPE_COCLASS
) write_coclass( type
, typelib
);
184 static void write_runtimeclasses_registry( const statement_list_t
*stmts
)
186 const statement_t
*stmt
;
189 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
191 if (stmt
->type
!= STMT_TYPE
) continue;
192 if (type_get_type((type
= stmt
->u
.type
)) != TYPE_RUNTIMECLASS
) continue;
193 if (!get_attrp(type
->attrs
, ATTR_ACTIVATABLE
) && !get_attrp(type
->attrs
, ATTR_STATIC
)) continue;
194 put_str( indent
, "ForceRemove %s\n", format_namespace( type
->namespace, "", ".", type
->name
, NULL
) );
195 put_str( indent
++, "{\n" );
196 put_str( indent
, "val 'DllPath' = s '%%MODULE%%'\n" );
197 put_str( --indent
, "}\n" );
201 static int write_progid( const type_t
*class )
203 const struct uuid
*uuid
= get_attrp( class->attrs
, ATTR_UUID
);
204 const char *descr
= get_attrp( class->attrs
, ATTR_HELPSTRING
);
205 const char *progid
= get_attrp( class->attrs
, ATTR_PROGID
);
206 const char *vi_progid
= get_attrp( class->attrs
, ATTR_VIPROGID
);
209 if (!descr
) descr
= class->name
;
213 put_str( indent
, "'%s' = s '%s'\n", progid
, descr
);
214 put_str( indent
++, "{\n" );
215 put_str( indent
, "CLSID = s '%s'\n", format_uuid( uuid
) );
216 put_str( --indent
, "}\n" );
220 put_str( indent
, "'%s' = s '%s'\n", vi_progid
, descr
);
221 put_str( indent
++, "{\n" );
222 put_str( indent
, "CLSID = s '%s'\n", format_uuid( uuid
) );
223 if (progid
&& strcmp( progid
, vi_progid
)) put_str( indent
, "CurVer = s '%s'\n", progid
);
224 put_str( --indent
, "}\n" );
229 static void write_progids( const statement_list_t
*stmts
)
231 const statement_t
*stmt
;
233 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
235 if (stmt
->type
== STMT_TYPE
)
237 const type_t
*type
= stmt
->u
.type
;
238 if (type_get_type(type
) == TYPE_COCLASS
) write_progid( type
);
243 void write_regscript( const statement_list_t
*stmts
)
245 const type_t
*ps_factory
;
247 if (!do_regscript
) return;
248 if (do_everything
&& !need_proxy_file( stmts
)) return;
250 init_output_buffer();
254 put_str( indent
, "HKLM\n" );
255 put_str( indent
++, "{\n" );
256 put_str( indent
, "NoRemove Software\n" );
257 put_str( indent
++, "{\n" );
258 put_str( indent
, "NoRemove Microsoft\n" );
259 put_str( indent
++, "{\n" );
260 put_str( indent
, "NoRemove WindowsRuntime\n" );
261 put_str( indent
++, "{\n" );
262 put_str( indent
, "NoRemove ActivatableClassId\n" );
263 put_str( indent
++, "{\n" );
264 write_runtimeclasses_registry( stmts
);
265 put_str( --indent
, "}\n" );
266 put_str( --indent
, "}\n" );
267 put_str( --indent
, "}\n" );
268 put_str( --indent
, "}\n" );
269 put_str( --indent
, "}\n" );
273 put_str( indent
, "HKCR\n" );
274 put_str( indent
++, "{\n" );
276 put_str( indent
, "NoRemove Interface\n" );
277 put_str( indent
++, "{\n" );
278 ps_factory
= find_ps_factory( stmts
);
279 if (ps_factory
) write_interfaces( stmts
, ps_factory
);
280 put_str( --indent
, "}\n" );
282 put_str( indent
, "NoRemove CLSID\n" );
283 put_str( indent
++, "{\n" );
284 write_coclasses( stmts
, NULL
);
285 put_str( --indent
, "}\n" );
287 write_progids( stmts
);
288 put_str( --indent
, "}\n" );
291 if (strendswith( regscript_name
, ".res" )) /* create a binary resource file */
293 add_output_to_resources( "WINE_REGISTRY", regscript_token
);
294 flush_output_resources( regscript_name
);
298 FILE *f
= fopen( regscript_name
, "w" );
299 if (!f
) error( "Could not open %s for output\n", regscript_name
);
300 if (fwrite( output_buffer
, 1, output_buffer_pos
, f
) != output_buffer_pos
)
301 error( "Failed to write to %s\n", regscript_name
);
303 error( "Failed to write to %s\n", regscript_name
);
307 void write_typelib_regscript( const statement_list_t
*stmts
)
309 const statement_t
*stmt
;
310 unsigned int count
= 0;
312 if (!do_typelib
) return;
313 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
315 if (stmt
->type
!= STMT_LIBRARY
) continue;
316 if (count
&& !strendswith( typelib_name
, ".res" ))
317 error( "Cannot store multiple typelibs into %s\n", typelib_name
);
319 create_msft_typelib( stmt
->u
.lib
);
322 if (count
&& strendswith( typelib_name
, ".res" )) flush_output_resources( typelib_name
);
325 void output_typelib_regscript( const typelib_t
*typelib
)
327 const struct uuid
*typelib_uuid
= get_attrp( typelib
->attrs
, ATTR_UUID
);
328 const char *descr
= get_attrp( typelib
->attrs
, ATTR_HELPSTRING
);
329 const expr_t
*lcid_expr
= get_attrp( typelib
->attrs
, ATTR_LIBLCID
);
330 unsigned int version
= get_attrv( typelib
->attrs
, ATTR_VERSION
);
331 unsigned int flags
= 0;
332 char id_part
[12] = "";
333 char *resname
= typelib_name
;
336 if (is_attr( typelib
->attrs
, ATTR_RESTRICTED
)) flags
|= 1; /* LIBFLAG_FRESTRICTED */
337 if (is_attr( typelib
->attrs
, ATTR_CONTROL
)) flags
|= 2; /* LIBFLAG_FCONTROL */
338 if (is_attr( typelib
->attrs
, ATTR_HIDDEN
)) flags
|= 4; /* LIBFLAG_FHIDDEN */
340 put_str( indent
, "HKCR\n" );
341 put_str( indent
++, "{\n" );
343 put_str( indent
, "NoRemove Typelib\n" );
344 put_str( indent
++, "{\n" );
345 put_str( indent
, "NoRemove '%s'\n", format_uuid( typelib_uuid
));
346 put_str( indent
++, "{\n" );
347 put_str( indent
, "'%u.%u' = s '%s'\n",
348 MAJORVERSION(version
), MINORVERSION(version
), descr
? descr
: typelib
->name
);
349 put_str( indent
++, "{\n" );
350 expr
= get_attrp( typelib
->attrs
, ATTR_ID
);
353 sprintf(id_part
, "\\%d", expr
->cval
);
354 resname
= strmake("%s\\%d", typelib_name
, expr
->cval
);
356 put_str( indent
, "'%x' { %s = s '%%MODULE%%%s' }\n",
357 lcid_expr
? lcid_expr
->cval
: 0, pointer_size
== 8 ? "win64" : "win32", id_part
);
358 put_str( indent
, "FLAGS = s '%u'\n", flags
);
359 put_str( --indent
, "}\n" );
360 put_str( --indent
, "}\n" );
361 put_str( --indent
, "}\n" );
363 put_str( indent
, "NoRemove Interface\n" );
364 put_str( indent
++, "{\n" );
365 write_typelib_interfaces( typelib
);
366 put_str( --indent
, "}\n" );
368 put_str( indent
, "NoRemove CLSID\n" );
369 put_str( indent
++, "{\n" );
370 write_coclasses( typelib
->stmts
, typelib
);
371 put_str( --indent
, "}\n" );
373 write_progids( typelib
->stmts
);
374 put_str( --indent
, "}\n" );
376 add_output_to_resources( "WINE_REGISTRY", resname
);