widl: Add support for generating a .rgs registration script for the defined interfaces.
This commit is contained in:
parent
233814c21e
commit
ce3abe8c0c
|
@ -9,6 +9,7 @@ C_SRCS = \
|
|||
hash.c \
|
||||
header.c \
|
||||
proxy.c \
|
||||
register.c \
|
||||
server.c \
|
||||
typegen.c \
|
||||
typelib.c \
|
||||
|
|
|
@ -39,6 +39,7 @@ extern void write_type_decl_left(FILE *f, type_t *t);
|
|||
extern int needs_space_after(type_t *t);
|
||||
extern int is_object(const type_t *iface);
|
||||
extern int is_local(const attr_list_t *list);
|
||||
extern int count_methods(const type_t *iface);
|
||||
extern int need_stub(const type_t *iface);
|
||||
extern int need_proxy(const type_t *iface);
|
||||
extern int need_stub_files(const statement_list_t *stmts);
|
||||
|
|
|
@ -332,6 +332,7 @@ input: gbl_statements { fix_incomplete();
|
|||
write_proxies($1);
|
||||
write_client($1);
|
||||
write_server($1);
|
||||
write_regscript($1);
|
||||
write_dlldata($1);
|
||||
write_local_stubs($1);
|
||||
}
|
||||
|
|
|
@ -490,7 +490,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
|
|||
print_proxy("\n");
|
||||
}
|
||||
|
||||
static int count_methods(type_t *iface)
|
||||
int count_methods(const type_t *iface)
|
||||
{
|
||||
const statement_t *stmt;
|
||||
int count = 0;
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Generation of dll registration scripts
|
||||
*
|
||||
* Copyright 2010 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "widl.h"
|
||||
#include "utils.h"
|
||||
#include "parser.h"
|
||||
#include "header.h"
|
||||
#include "typegen.h"
|
||||
|
||||
static int indent;
|
||||
|
||||
static const char *format_uuid( const UUID *uuid )
|
||||
{
|
||||
static char buffer[40];
|
||||
sprintf( buffer, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
uuid->Data1, uuid->Data2, uuid->Data3,
|
||||
uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3],
|
||||
uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int write_interface( const type_t *iface )
|
||||
{
|
||||
const UUID *uuid = get_attrp( iface->attrs, ATTR_UUID );
|
||||
|
||||
if (!type_iface_get_inherit( iface )) return 0;
|
||||
if (!need_proxy( iface )) return 0;
|
||||
if (!uuid) return 0;
|
||||
put_str( indent, "ForceRemove '%s' = s '%s'\n", format_uuid( uuid ), iface->name );
|
||||
put_str( indent, "{\n" );
|
||||
indent++;
|
||||
put_str( indent, "NumMethods = s %u\n", count_methods( iface ));
|
||||
put_str( indent, "ProxyStubClsid32 = s '%%CLSID_PSFactoryBuffer%%'\n" );
|
||||
indent--;
|
||||
put_str( indent, "}\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_interfaces( const statement_list_t *stmts )
|
||||
{
|
||||
const statement_t *stmt;
|
||||
int count = 0;
|
||||
|
||||
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
|
||||
{
|
||||
if (stmt->type == STMT_LIBRARY)
|
||||
count += write_interfaces( stmt->u.lib->stmts );
|
||||
else if (stmt->type == STMT_TYPE && type_get_type( stmt->u.type ) == TYPE_INTERFACE)
|
||||
count += write_interface( stmt->u.type );
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* put a string into the resource file */
|
||||
static inline void put_string( const char *str )
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
unsigned char ch = *str++;
|
||||
put_word( toupper(ch) );
|
||||
}
|
||||
put_word( 0 );
|
||||
}
|
||||
|
||||
void write_regscript( const statement_list_t *stmts )
|
||||
{
|
||||
int count;
|
||||
|
||||
if (!do_regscript) return;
|
||||
if (do_everything && !need_proxy_file( stmts )) return;
|
||||
|
||||
init_output_buffer();
|
||||
|
||||
put_str( indent, "HKCR\n" );
|
||||
put_str( indent++, "{\n" );
|
||||
|
||||
put_str( indent, "NoRemove Interface\n" );
|
||||
put_str( indent++, "{\n" );
|
||||
count = write_interfaces( stmts );
|
||||
put_str( --indent, "}\n" );
|
||||
|
||||
if (count)
|
||||
{
|
||||
put_str( indent, "NoRemove CLSID\n" );
|
||||
put_str( indent++, "{\n" );
|
||||
put_str( indent, "ForceRemove '%%CLSID_PSFactoryBuffer%%' = s 'PSFactoryBuffer'\n" );
|
||||
put_str( indent++, "{\n" );
|
||||
put_str( indent, "InprocServer32 = s '%%MODULE%%' { val ThreadingModel = s 'Both' }\n" );
|
||||
put_str( --indent, "}\n" );
|
||||
put_str( --indent, "}\n" );
|
||||
}
|
||||
|
||||
put_str( --indent, "}\n" );
|
||||
|
||||
if (strendswith( regscript_name, ".res" )) /* create a binary resource file */
|
||||
{
|
||||
unsigned char *data = output_buffer;
|
||||
size_t data_size = output_buffer_pos;
|
||||
size_t header_size = 5 * sizeof(unsigned int) + 2 * sizeof(unsigned short);
|
||||
|
||||
header_size += (strlen(regscript_token) + strlen("WINE_REGISTRY") + 2) * sizeof(unsigned short);
|
||||
|
||||
init_output_buffer();
|
||||
|
||||
put_dword( 0 ); /* ResSize */
|
||||
put_dword( 32 ); /* HeaderSize */
|
||||
put_word( 0xffff ); /* ResType */
|
||||
put_word( 0x0000 );
|
||||
put_word( 0xffff ); /* ResName */
|
||||
put_word( 0x0000 );
|
||||
put_dword( 0 ); /* DataVersion */
|
||||
put_word( 0 ); /* Memory options */
|
||||
put_word( 0 ); /* Language */
|
||||
put_dword( 0 ); /* Version */
|
||||
put_dword( 0 ); /* Characteristics */
|
||||
|
||||
put_dword( data_size ); /* ResSize */
|
||||
put_dword( (header_size + 3) & ~3 ); /* HeaderSize */
|
||||
put_string( "WINE_REGISTRY" ); /* ResType */
|
||||
put_string( regscript_token ); /* ResName */
|
||||
align_output( 4 );
|
||||
put_dword( 0 ); /* DataVersion */
|
||||
put_word( 0 ); /* Memory options */
|
||||
put_word( 0 ); /* Language */
|
||||
put_dword( 0 ); /* Version */
|
||||
put_dword( 0 ); /* Characteristics */
|
||||
|
||||
put_data( data, data_size );
|
||||
free( data );
|
||||
align_output( 4 );
|
||||
flush_output_buffer( regscript_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
FILE *f = fopen( regscript_name, "w" );
|
||||
if (!f) error( "Could not open %s for output\n", regscript_name );
|
||||
if (fwrite( output_buffer, output_buffer_pos, 1, f ) != output_buffer_pos)
|
||||
error( "Failed to write to %s\n", regscript_name );
|
||||
if (fclose( f ))
|
||||
error( "Failed to write to %s\n", regscript_name );
|
||||
}
|
||||
}
|
|
@ -326,6 +326,32 @@ void put_pword( unsigned int val )
|
|||
else put_dword( val );
|
||||
}
|
||||
|
||||
void put_str( int indent, const char *format, ... )
|
||||
{
|
||||
int n;
|
||||
va_list args;
|
||||
|
||||
check_output_buffer_space( 4 * indent );
|
||||
memset( output_buffer + output_buffer_pos, ' ', 4 * indent );
|
||||
output_buffer_pos += 4 * indent;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_t size = output_buffer_size - output_buffer_pos;
|
||||
va_start( args, format );
|
||||
n = vsnprintf( (char *)output_buffer + output_buffer_pos, size, format, args );
|
||||
va_end( args );
|
||||
if (n == -1) size *= 2;
|
||||
else if ((size_t)n >= size) size = n + 1;
|
||||
else
|
||||
{
|
||||
output_buffer_pos += n;
|
||||
return;
|
||||
}
|
||||
check_output_buffer_space( size );
|
||||
}
|
||||
}
|
||||
|
||||
void align_output( unsigned int align )
|
||||
{
|
||||
size_t size = align - (output_buffer_pos % align);
|
||||
|
|
|
@ -64,6 +64,7 @@ extern void put_word( unsigned short val );
|
|||
extern void put_dword( unsigned int val );
|
||||
extern void put_qword( unsigned int val );
|
||||
extern void put_pword( unsigned int val );
|
||||
extern void put_str( int indent, const char *format, ... ) __attribute__((format (printf, 2, 3)));
|
||||
extern void align_output( unsigned int align );
|
||||
|
||||
/* typelibs expect the minor version to be stored in the higher bits and
|
||||
|
|
|
@ -69,6 +69,7 @@ static const char usage[] =
|
|||
" --prefix-all=p Prefix names of client stubs / server functions with 'p'\n"
|
||||
" --prefix-client=p Prefix names of client stubs with 'p'\n"
|
||||
" --prefix-server=p Prefix names of server functions with 'p'\n"
|
||||
" -r Generate registration script\n"
|
||||
" -s Generate server stub\n"
|
||||
" -t Generate typelib\n"
|
||||
" -u Generate interface identifiers file\n"
|
||||
|
@ -101,6 +102,7 @@ int do_typelib = 0;
|
|||
int do_proxies = 0;
|
||||
int do_client = 0;
|
||||
int do_server = 0;
|
||||
int do_regscript = 0;
|
||||
int do_idfile = 0;
|
||||
int do_dlldata = 0;
|
||||
static int no_preprocess = 0;
|
||||
|
@ -122,6 +124,8 @@ char *client_name;
|
|||
char *client_token;
|
||||
char *server_name;
|
||||
char *server_token;
|
||||
char *regscript_name;
|
||||
char *regscript_token;
|
||||
static char *idfile_name;
|
||||
static char *idfile_token;
|
||||
char *temp_name;
|
||||
|
@ -152,7 +156,7 @@ enum {
|
|||
};
|
||||
|
||||
static const char short_options[] =
|
||||
"b:cC:d:D:EhH:I:m:No:pP:sS:tT:uU:VW";
|
||||
"b:cC:d:D:EhH:I:m:No:pP:rsS:tT:uU:VW";
|
||||
static const struct option long_options[] = {
|
||||
{ "dlldata", 1, NULL, DLLDATA_OPTION },
|
||||
{ "dlldata-only", 0, NULL, DLLDATA_ONLY_OPTION },
|
||||
|
@ -284,6 +288,7 @@ static void set_everything(int x)
|
|||
do_proxies = x;
|
||||
do_client = x;
|
||||
do_server = x;
|
||||
do_regscript = x;
|
||||
do_idfile = x;
|
||||
do_dlldata = x;
|
||||
}
|
||||
|
@ -584,6 +589,10 @@ int main(int argc,char *argv[])
|
|||
case 'P':
|
||||
proxy_name = xstrdup(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
do_everything = 0;
|
||||
do_regscript = 1;
|
||||
break;
|
||||
case 's':
|
||||
do_everything = 0;
|
||||
do_server = 1;
|
||||
|
@ -624,13 +633,15 @@ int main(int argc,char *argv[])
|
|||
if (!output_name) output_name = dup_basename(input_name, ".idl");
|
||||
|
||||
if (!do_everything &&
|
||||
do_header + do_typelib + do_proxies + do_client + do_server + do_idfile + do_dlldata == 1)
|
||||
do_header + do_typelib + do_proxies + do_client +
|
||||
do_server + do_regscript + do_idfile + do_dlldata == 1)
|
||||
{
|
||||
if (do_header) header_name = output_name;
|
||||
else if (do_typelib) typelib_name = output_name;
|
||||
else if (do_proxies) proxy_name = output_name;
|
||||
else if (do_client) client_name = output_name;
|
||||
else if (do_server) server_name = output_name;
|
||||
else if (do_regscript) regscript_name = output_name;
|
||||
else if (do_idfile) idfile_name = output_name;
|
||||
else if (do_dlldata) dlldata_name = output_name;
|
||||
}
|
||||
|
@ -698,6 +709,11 @@ int main(int argc,char *argv[])
|
|||
strcat(server_name, "_s.c");
|
||||
}
|
||||
|
||||
if (!regscript_name && do_regscript) {
|
||||
regscript_name = dup_basename(input_name, ".idl");
|
||||
strcat(regscript_name, "_r.rgs");
|
||||
}
|
||||
|
||||
if (!idfile_name && do_idfile) {
|
||||
idfile_name = dup_basename(input_name, ".idl");
|
||||
strcat(idfile_name, "_i.c");
|
||||
|
@ -706,6 +722,7 @@ int main(int argc,char *argv[])
|
|||
if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
|
||||
if (do_client) client_token = dup_basename_token(client_name,"_c.c");
|
||||
if (do_server) server_token = dup_basename_token(server_name,"_s.c");
|
||||
if (do_regscript) regscript_token = dup_basename_token(regscript_name,"_r.rgs");
|
||||
|
||||
add_widl_version_define();
|
||||
wpp_add_define("_WIN32", NULL);
|
||||
|
@ -784,6 +801,8 @@ static void rm_tempfile(void)
|
|||
unlink(client_name);
|
||||
if (do_server)
|
||||
unlink(server_name);
|
||||
if (do_regscript)
|
||||
unlink(regscript_name);
|
||||
if (do_idfile)
|
||||
unlink(idfile_name);
|
||||
if (do_proxies)
|
||||
|
|
|
@ -41,6 +41,7 @@ extern int do_typelib;
|
|||
extern int do_proxies;
|
||||
extern int do_client;
|
||||
extern int do_server;
|
||||
extern int do_regscript;
|
||||
extern int do_idfile;
|
||||
extern int do_dlldata;
|
||||
extern int old_names;
|
||||
|
@ -61,6 +62,8 @@ extern char *client_name;
|
|||
extern char *client_token;
|
||||
extern char *server_name;
|
||||
extern char *server_token;
|
||||
extern char *regscript_name;
|
||||
extern char *regscript_token;
|
||||
extern const char *prefix_client;
|
||||
extern const char *prefix_server;
|
||||
extern size_t pointer_size;
|
||||
|
@ -74,6 +77,7 @@ extern void write_id_data(const statement_list_t *stmts);
|
|||
extern void write_proxies(const statement_list_t *stmts);
|
||||
extern void write_client(const statement_list_t *stmts);
|
||||
extern void write_server(const statement_list_t *stmts);
|
||||
extern void write_regscript(const statement_list_t *stmts);
|
||||
extern void write_local_stubs(const statement_list_t *stmts);
|
||||
extern void write_dlldata(const statement_list_t *stmts);
|
||||
|
||||
|
|
|
@ -75,6 +75,12 @@ Only generate 32-bit, respectively 64-bit code (the default is to
|
|||
generate both 32-bit and 64-bit versions into the same destination
|
||||
file).
|
||||
.PP
|
||||
.B Registration script options:
|
||||
.IP "\fB-r\fR"
|
||||
Generate a registration script. The default output filename is
|
||||
\fIinfile\fB_r.rgs\fR. If the output file name ends in \fB.res\fR, a
|
||||
binary resource file containing the script is generated instead.
|
||||
.PP
|
||||
.B Dlldata file options:
|
||||
.IP "\fB--dlldata-only\fI name1 [name2...]"
|
||||
Regenerate the dlldata file from scratch using the specified proxy
|
||||
|
|
Loading…
Reference in New Issue