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
22 #include "wine/port.h"
40 static const char *format_uuid( const UUID
*uuid
)
42 static char buffer
[40];
43 sprintf( buffer
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
44 uuid
->Data1
, uuid
->Data2
, uuid
->Data3
,
45 uuid
->Data4
[0], uuid
->Data4
[1], uuid
->Data4
[2], uuid
->Data4
[3],
46 uuid
->Data4
[4], uuid
->Data4
[5], uuid
->Data4
[6], uuid
->Data4
[7] );
50 static const char *get_coclass_threading( const type_t
*class )
52 static const char * const models
[] =
55 "Apartment", /* THREADING_APARTMENT */
56 "Neutral", /* THREADING_NEUTRAL */
57 "Single", /* THREADING_SINGLE */
58 "Free", /* THREADING_FREE */
59 "Both", /* THREADING_BOTH */
61 return models
[get_attrv( class->attrs
, ATTR_THREADING
)];
64 static int write_interface( const type_t
*iface
)
66 const UUID
*uuid
= get_attrp( iface
->attrs
, ATTR_UUID
);
69 if (!is_object( iface
)) return 0;
70 if (!type_iface_get_inherit(iface
)) /* special case for IUnknown */
72 put_str( indent
, "ForceRemove '%s' = s '%s'\n", format_uuid( uuid
), iface
->name
);
75 if (is_local( iface
->attrs
)) return 0;
76 put_str( indent
, "ForceRemove '%s' = s '%s'\n", format_uuid( uuid
), iface
->name
);
77 put_str( indent
, "{\n" );
79 put_str( indent
, "NumMethods = s %u\n", count_methods( iface
));
80 put_str( indent
, "ProxyStubClsid32 = s '%%CLSID_PSFactoryBuffer%%'\n" );
82 put_str( indent
, "}\n" );
86 static int write_interfaces( const statement_list_t
*stmts
)
88 const statement_t
*stmt
;
91 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
93 if (stmt
->type
== STMT_TYPE
&& type_get_type( stmt
->u
.type
) == TYPE_INTERFACE
)
94 count
+= write_interface( stmt
->u
.type
);
99 static int write_coclass( const type_t
*class, const typelib_t
*typelib
)
101 const UUID
*uuid
= get_attrp( class->attrs
, ATTR_UUID
);
102 const char *descr
= get_attrp( class->attrs
, ATTR_HELPSTRING
);
103 const char *progid
= get_attrp( class->attrs
, ATTR_PROGID
);
104 const char *vi_progid
= get_attrp( class->attrs
, ATTR_VIPROGID
);
105 const char *threading
= get_coclass_threading( class );
108 if (typelib
&& !threading
) return 0;
109 if (!descr
) descr
= class->name
;
111 put_str( indent
, "ForceRemove '%s' = s '%s'\n", format_uuid( uuid
), descr
);
112 put_str( indent
++, "{\n" );
113 if (threading
) put_str( indent
, "InprocServer32 = s '%%MODULE%%' { val ThreadingModel = s '%s' }\n",
115 if (progid
) put_str( indent
, "ProgId = s '%s'\n", progid
);
118 const UUID
*typelib_uuid
= get_attrp( typelib
->attrs
, ATTR_UUID
);
119 const unsigned int version
= get_attrv( typelib
->attrs
, ATTR_VERSION
);
120 put_str( indent
, "TypeLib = s '%s'\n", format_uuid( typelib_uuid
));
121 put_str( indent
, "Version = s '%u.%u'\n", MAJORVERSION(version
), MINORVERSION(version
) );
123 if (vi_progid
) put_str( indent
, "VersionIndependentProgId = s '%s'\n", vi_progid
);
124 put_str( --indent
, "}\n" );
128 static void write_coclasses( const statement_list_t
*stmts
, const typelib_t
*typelib
)
130 const statement_t
*stmt
;
132 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
134 if (stmt
->type
== STMT_TYPE
)
136 const type_t
*type
= stmt
->u
.type
;
137 if (type_get_type(type
) == TYPE_COCLASS
) write_coclass( type
, typelib
);
139 else if (stmt
->type
== STMT_LIBRARY
)
141 const typelib_t
*lib
= stmt
->u
.lib
;
142 write_coclasses( lib
->stmts
, lib
);
147 static int write_progid( const type_t
*class )
149 const UUID
*uuid
= get_attrp( class->attrs
, ATTR_UUID
);
150 const char *descr
= get_attrp( class->attrs
, ATTR_HELPSTRING
);
151 const char *progid
= get_attrp( class->attrs
, ATTR_PROGID
);
152 const char *vi_progid
= get_attrp( class->attrs
, ATTR_VIPROGID
);
155 if (!descr
) descr
= class->name
;
159 put_str( indent
, "'%s' = s '%s'\n", progid
, descr
);
160 put_str( indent
++, "{\n" );
161 put_str( indent
, "CLSID = s '%s'\n", format_uuid( uuid
) );
162 put_str( --indent
, "}\n" );
166 put_str( indent
, "'%s' = s '%s'\n", vi_progid
, descr
);
167 put_str( indent
++, "{\n" );
168 put_str( indent
, "CLSID = s '%s'\n", format_uuid( uuid
) );
169 if (progid
&& strcmp( progid
, vi_progid
)) put_str( indent
, "CurVer = s '%s'\n", progid
);
170 put_str( --indent
, "}\n" );
175 static void write_progids( const statement_list_t
*stmts
)
177 const statement_t
*stmt
;
179 if (stmts
) LIST_FOR_EACH_ENTRY( stmt
, stmts
, const statement_t
, entry
)
181 if (stmt
->type
== STMT_TYPE
)
183 const type_t
*type
= stmt
->u
.type
;
184 if (type_get_type(type
) == TYPE_COCLASS
) write_progid( type
);
186 else if (stmt
->type
== STMT_LIBRARY
)
188 write_progids( stmt
->u
.lib
->stmts
);
193 /* put a string into the resource file */
194 static inline void put_string( const char *str
)
198 unsigned char ch
= *str
++;
199 put_word( toupper(ch
) );
204 void write_regscript( const statement_list_t
*stmts
)
208 if (!do_regscript
) return;
209 if (do_everything
&& !need_proxy_file( stmts
)) return;
211 init_output_buffer();
213 put_str( indent
, "HKCR\n" );
214 put_str( indent
++, "{\n" );
216 put_str( indent
, "NoRemove Interface\n" );
217 put_str( indent
++, "{\n" );
218 count
= write_interfaces( stmts
);
219 put_str( --indent
, "}\n" );
221 put_str( indent
, "NoRemove CLSID\n" );
222 put_str( indent
++, "{\n" );
225 put_str( indent
, "ForceRemove '%%CLSID_PSFactoryBuffer%%' = s 'PSFactoryBuffer'\n" );
226 put_str( indent
++, "{\n" );
227 put_str( indent
, "InprocServer32 = s '%%MODULE%%' { val ThreadingModel = s 'Both' }\n" );
228 put_str( --indent
, "}\n" );
230 write_coclasses( stmts
, NULL
);
231 put_str( --indent
, "}\n" );
233 write_progids( stmts
);
234 put_str( --indent
, "}\n" );
236 if (strendswith( regscript_name
, ".res" )) /* create a binary resource file */
238 unsigned char *data
= output_buffer
;
239 size_t data_size
= output_buffer_pos
;
240 size_t header_size
= 5 * sizeof(unsigned int) + 2 * sizeof(unsigned short);
242 header_size
+= (strlen(regscript_token
) + strlen("WINE_REGISTRY") + 2) * sizeof(unsigned short);
244 init_output_buffer();
246 put_dword( 0 ); /* ResSize */
247 put_dword( 32 ); /* HeaderSize */
248 put_word( 0xffff ); /* ResType */
250 put_word( 0xffff ); /* ResName */
252 put_dword( 0 ); /* DataVersion */
253 put_word( 0 ); /* Memory options */
254 put_word( 0 ); /* Language */
255 put_dword( 0 ); /* Version */
256 put_dword( 0 ); /* Characteristics */
258 put_dword( data_size
); /* ResSize */
259 put_dword( (header_size
+ 3) & ~3 ); /* HeaderSize */
260 put_string( "WINE_REGISTRY" ); /* ResType */
261 put_string( regscript_token
); /* ResName */
263 put_dword( 0 ); /* DataVersion */
264 put_word( 0 ); /* Memory options */
265 put_word( 0 ); /* Language */
266 put_dword( 0 ); /* Version */
267 put_dword( 0 ); /* Characteristics */
269 put_data( data
, data_size
);
272 flush_output_buffer( regscript_name
);
276 FILE *f
= fopen( regscript_name
, "w" );
277 if (!f
) error( "Could not open %s for output\n", regscript_name
);
278 if (fwrite( output_buffer
, output_buffer_pos
, 1, f
) != output_buffer_pos
)
279 error( "Failed to write to %s\n", regscript_name
);
281 error( "Failed to write to %s\n", regscript_name
);