Commit ce3abe8c authored by Alexandre Julliard's avatar Alexandre Julliard

widl: Add support for generating a .rgs registration script for the defined interfaces.

parent 233814c2
......@@ -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;
......
/*
* 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment