ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

proxy.c
Go to the documentation of this file.
00001 /*
00002  * IDL Compiler
00003  *
00004  * Copyright 2002 Ove Kaaven
00005  * Copyright 2004 Mike McCormack
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "config.h"
00023 #include "wine/port.h"
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #ifdef HAVE_UNISTD_H
00028 # include <unistd.h>
00029 #endif
00030 #include <string.h>
00031 #include <ctype.h>
00032 
00033 #include "widl.h"
00034 #include "utils.h"
00035 #include "parser.h"
00036 #include "header.h"
00037 #include "typegen.h"
00038 #include "expr.h"
00039 
00040 #define END_OF_LIST(list)       \
00041   do {                          \
00042     if (list) {                 \
00043       while (NEXT_LINK(list))   \
00044         list = NEXT_LINK(list); \
00045     }                           \
00046   } while(0)
00047 
00048 static FILE* proxy;
00049 static int indent = 0;
00050 
00051 static void print_proxy( const char *format, ... ) __attribute__((format (printf, 1, 2)));
00052 static void print_proxy( const char *format, ... )
00053 {
00054   va_list va;
00055   va_start( va, format );
00056   print( proxy, indent, format, va );
00057   va_end( va );
00058 }
00059 
00060 static void write_stubdescproto(void)
00061 {
00062   print_proxy( "static const MIDL_STUB_DESC Object_StubDesc;\n");
00063   print_proxy( "\n");
00064 }
00065 
00066 static void write_stubdesc(int expr_eval_routines)
00067 {
00068   print_proxy( "static const MIDL_STUB_DESC Object_StubDesc =\n{\n");
00069   indent++;
00070   print_proxy( "0,\n");
00071   print_proxy( "NdrOleAllocate,\n");
00072   print_proxy( "NdrOleFree,\n");
00073   print_proxy( "{0}, 0, 0, %s, 0,\n", expr_eval_routines ? "ExprEvalRoutines" : "0");
00074   print_proxy( "__MIDL_TypeFormatString.Format,\n");
00075   print_proxy( "1, /* -error bounds_check flag */\n");
00076   print_proxy( "0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001);
00077   print_proxy( "0,\n");
00078   print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n");
00079   print_proxy( "0,\n");
00080   print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
00081   print_proxy( "0,  /* notify & notify_flag routine table */\n");
00082   print_proxy( "1,  /* Flags */\n");
00083   print_proxy( "0,  /* Reserved3 */\n");
00084   print_proxy( "0,  /* Reserved4 */\n");
00085   print_proxy( "0   /* Reserved5 */\n");
00086   indent--;
00087   print_proxy( "};\n");
00088   print_proxy( "\n");
00089 }
00090 
00091 static void init_proxy(const statement_list_t *stmts)
00092 {
00093   if (proxy) return;
00094   if(!(proxy = fopen(proxy_name, "w")))
00095     error("Could not open %s for output\n", proxy_name);
00096   print_proxy( "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
00097   print_proxy( "\n");
00098   print_proxy( "#define __midl_proxy\n");
00099   print_proxy( "#include \"objbase.h\"\n");
00100   print_proxy( "\n");
00101   print_proxy( "#ifndef DECLSPEC_HIDDEN\n");
00102   print_proxy( "#define DECLSPEC_HIDDEN\n");
00103   print_proxy( "#endif\n");
00104   print_proxy( "\n");
00105 }
00106 
00107 static void clear_output_vars( const var_list_t *args )
00108 {
00109   const var_t *arg;
00110 
00111   if (!args) return;
00112   LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
00113   {
00114       if (is_attr(arg->attrs, ATTR_IN)) continue;
00115       if (!is_attr(arg->attrs, ATTR_OUT)) continue;
00116       if (is_ptr(arg->type))
00117       {
00118           if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_BASIC) continue;
00119           if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_ENUM) continue;
00120       }
00121       print_proxy( "if (%s) MIDL_memset( %s, 0, sizeof( *%s ));\n", arg->name, arg->name, arg->name );
00122   }
00123 }
00124 
00125 static int need_delegation(const type_t *iface)
00126 {
00127     const type_t *parent = type_iface_get_inherit( iface );
00128     return parent && type_iface_get_inherit(parent) && (parent->ignore || is_local( parent->attrs ));
00129 }
00130 
00131 static int get_delegation_indirect(const type_t *iface, const type_t ** delegate_to)
00132 {
00133   const type_t * cur_iface;
00134   for (cur_iface = iface; cur_iface != NULL; cur_iface = type_iface_get_inherit(cur_iface))
00135     if (need_delegation(cur_iface))
00136     {
00137       if(delegate_to)
00138         *delegate_to = type_iface_get_inherit(cur_iface);
00139       return 1;
00140     }
00141   return 0;
00142 }
00143 
00144 static int need_delegation_indirect(const type_t *iface)
00145 {
00146   return get_delegation_indirect(iface, NULL);
00147 }
00148 
00149 static void free_variable( const var_t *arg, const char *local_var_prefix )
00150 {
00151   unsigned int type_offset = arg->type->typestring_offset;
00152   type_t *type = arg->type;
00153 
00154   write_parameter_conf_or_var_exprs(proxy, indent, local_var_prefix, PHASE_FREE, arg, FALSE);
00155 
00156   switch (typegen_detect_type(type, arg->attrs, TDT_IGNORE_STRINGS))
00157   {
00158   case TGT_ENUM:
00159   case TGT_BASIC:
00160     break;
00161 
00162   case TGT_STRUCT:
00163     if (get_struct_fc(type) != RPC_FC_STRUCT)
00164       print_proxy("/* FIXME: %s code for %s struct type 0x%x missing */\n", __FUNCTION__, arg->name, get_struct_fc(type) );
00165     break;
00166 
00167   case TGT_IFACE_POINTER:
00168   case TGT_POINTER:
00169   case TGT_ARRAY:
00170     print_proxy( "NdrClearOutParameters( &__frame->_StubMsg, ");
00171     fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
00172     fprintf(proxy, "(void *)%s );\n", arg->name );
00173     break;
00174 
00175   default:
00176     print_proxy("/* FIXME: %s code for %s type %d missing */\n", __FUNCTION__, arg->name, type_get_type(type) );
00177   }
00178 }
00179 
00180 static void proxy_free_variables( var_list_t *args, const char *local_var_prefix )
00181 {
00182   const var_t *arg;
00183 
00184   if (!args) return;
00185   LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
00186     if (is_attr(arg->attrs, ATTR_OUT))
00187     {
00188       free_variable( arg, local_var_prefix );
00189       fprintf(proxy, "\n");
00190     }
00191 }
00192 
00193 static void gen_proxy(type_t *iface, const var_t *func, int idx,
00194                       unsigned int proc_offset)
00195 {
00196   type_t *rettype = type_function_get_rettype(func->type);
00197   int has_ret = !is_void(rettype);
00198   int has_full_pointer = is_full_pointer_function(func);
00199   const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
00200   const var_list_t *args = type_get_function_args(func->type);
00201   if (!callconv) callconv = "STDMETHODCALLTYPE";
00202 
00203   indent = 0;
00204   if (is_interpreted_func( iface, func ))
00205   {
00206       if (get_stub_mode() == MODE_Oif && !is_callas( func->attrs )) return;
00207       write_type_decl_left(proxy, type_function_get_rettype(func->type));
00208       print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
00209       write_args(proxy, args, iface->name, 1, TRUE);
00210       print_proxy( ")\n");
00211       write_client_call_routine( proxy, iface, func, "Object", proc_offset );
00212       return;
00213   }
00214   print_proxy( "static void __finally_%s_%s_Proxy( struct __proxy_frame *__frame )\n",
00215                iface->name, get_name(func) );
00216   print_proxy( "{\n");
00217   indent++;
00218   if (has_full_pointer) write_full_pointer_free(proxy, indent, func);
00219   print_proxy( "NdrProxyFreeBuffer( __frame->This, &__frame->_StubMsg );\n" );
00220   indent--;
00221   print_proxy( "}\n");
00222   print_proxy( "\n");
00223 
00224   write_type_decl_left(proxy, rettype);
00225   print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
00226   write_args(proxy, args, iface->name, 1, TRUE);
00227   print_proxy( ")\n");
00228   print_proxy( "{\n");
00229   indent ++;
00230   print_proxy( "struct __proxy_frame __f, * const __frame = &__f;\n" );
00231   /* local variables */
00232   if (has_ret) {
00233     print_proxy( "%s", "" );
00234     write_type_decl_left(proxy, rettype);
00235     print_proxy( " _RetVal;\n");
00236   }
00237   print_proxy( "RPC_MESSAGE _RpcMessage;\n" );
00238   if (has_ret) {
00239     if (decl_indirect(rettype))
00240       print_proxy("void *_p_%s = &%s;\n",
00241                  "_RetVal", "_RetVal");
00242   }
00243   print_proxy( "\n");
00244 
00245   print_proxy( "RpcExceptionInit( __proxy_filter, __finally_%s_%s_Proxy );\n", iface->name, get_name(func) );
00246   print_proxy( "__frame->This = This;\n" );
00247 
00248   if (has_full_pointer)
00249     write_full_pointer_init(proxy, indent, func, FALSE);
00250 
00251   /* FIXME: trace */
00252   clear_output_vars( type_get_function_args(func->type) );
00253 
00254   print_proxy( "RpcTryExcept\n" );
00255   print_proxy( "{\n" );
00256   indent++;
00257   print_proxy( "NdrProxyInitialize(This, &_RpcMessage, &__frame->_StubMsg, &Object_StubDesc, %d);\n", idx);
00258   write_pointer_checks( proxy, indent, func );
00259 
00260   print_proxy( "RpcTryFinally\n" );
00261   print_proxy( "{\n" );
00262   indent++;
00263 
00264   write_remoting_arguments(proxy, indent, func, "", PASS_IN, PHASE_BUFFERSIZE);
00265 
00266   print_proxy( "NdrProxyGetBuffer(This, &__frame->_StubMsg);\n" );
00267 
00268   write_remoting_arguments(proxy, indent, func, "", PASS_IN, PHASE_MARSHAL);
00269 
00270   print_proxy( "NdrProxySendReceive(This, &__frame->_StubMsg);\n" );
00271   fprintf(proxy, "\n");
00272   print_proxy( "__frame->_StubMsg.BufferStart = _RpcMessage.Buffer;\n" );
00273   print_proxy( "__frame->_StubMsg.BufferEnd   = __frame->_StubMsg.BufferStart + _RpcMessage.BufferLength;\n\n" );
00274 
00275   print_proxy("if ((_RpcMessage.DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n");
00276   indent++;
00277   print_proxy("NdrConvert( &__frame->_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset );
00278   indent--;
00279   fprintf(proxy, "\n");
00280 
00281   write_remoting_arguments(proxy, indent, func, "", PASS_OUT, PHASE_UNMARSHAL);
00282 
00283   if (has_ret)
00284   {
00285       if (decl_indirect(rettype))
00286           print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", "_RetVal", "_RetVal");
00287       else if (is_ptr(rettype) || is_array(rettype))
00288           print_proxy("%s = 0;\n", "_RetVal");
00289       write_remoting_arguments(proxy, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL);
00290   }
00291 
00292   indent--;
00293   print_proxy( "}\n");
00294   print_proxy( "RpcFinally\n" );
00295   print_proxy( "{\n" );
00296   indent++;
00297   print_proxy( "__finally_%s_%s_Proxy( __frame );\n", iface->name, get_name(func) );
00298   indent--;
00299   print_proxy( "}\n");
00300   print_proxy( "RpcEndFinally\n" );
00301   indent--;
00302   print_proxy( "}\n" );
00303   print_proxy( "RpcExcept(__frame->_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)\n" );
00304   print_proxy( "{\n" );
00305   if (has_ret) {
00306     indent++;
00307     proxy_free_variables( type_get_function_args(func->type), "" );
00308     print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" );
00309     indent--;
00310   }
00311   print_proxy( "}\n" );
00312   print_proxy( "RpcEndExcept\n" );
00313 
00314   if (has_ret) {
00315     print_proxy( "return _RetVal;\n" );
00316   }
00317   indent--;
00318   print_proxy( "}\n");
00319   print_proxy( "\n");
00320 }
00321 
00322 static void gen_stub(type_t *iface, const var_t *func, const char *cas,
00323                      unsigned int proc_offset)
00324 {
00325   const var_t *arg;
00326   int has_ret = !is_void(type_function_get_rettype(func->type));
00327   int has_full_pointer = is_full_pointer_function(func);
00328 
00329   if (is_interpreted_func( iface, func )) return;
00330 
00331   indent = 0;
00332   print_proxy( "struct __frame_%s_%s_Stub\n{\n", iface->name, get_name(func));
00333   indent++;
00334   print_proxy( "__DECL_EXCEPTION_FRAME\n" );
00335   print_proxy( "MIDL_STUB_MESSAGE _StubMsg;\n");
00336   print_proxy( "%s * _This;\n", iface->name );
00337   declare_stub_args( proxy, indent, func );
00338   indent--;
00339   print_proxy( "};\n\n" );
00340 
00341   print_proxy( "static void __finally_%s_%s_Stub(", iface->name, get_name(func) );
00342   print_proxy( " struct __frame_%s_%s_Stub *__frame )\n{\n", iface->name, get_name(func) );
00343   indent++;
00344   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_FREE);
00345   if (has_full_pointer)
00346     write_full_pointer_free(proxy, indent, func);
00347   indent--;
00348   print_proxy( "}\n\n" );
00349 
00350   print_proxy( "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
00351   indent++;
00352   print_proxy( "IRpcStubBuffer* This,\n");
00353   print_proxy( "IRpcChannelBuffer *_pRpcChannelBuffer,\n");
00354   print_proxy( "PRPC_MESSAGE _pRpcMessage,\n");
00355   print_proxy( "DWORD* _pdwStubPhase)\n");
00356   indent--;
00357   print_proxy( "{\n");
00358   indent++;
00359   print_proxy( "struct __frame_%s_%s_Stub __f, * const __frame = &__f;\n\n",
00360                iface->name, get_name(func) );
00361 
00362   print_proxy("__frame->_This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n\n", iface->name);
00363 
00364   /* FIXME: trace */
00365 
00366   print_proxy("NdrStubInitialize(_pRpcMessage, &__frame->_StubMsg, &Object_StubDesc, _pRpcChannelBuffer);\n");
00367   fprintf(proxy, "\n");
00368   print_proxy( "RpcExceptionInit( 0, __finally_%s_%s_Stub );\n", iface->name, get_name(func) );
00369 
00370   write_parameters_init(proxy, indent, func, "__frame->");
00371 
00372   print_proxy("RpcTryFinally\n");
00373   print_proxy("{\n");
00374   indent++;
00375   if (has_full_pointer)
00376     write_full_pointer_init(proxy, indent, func, TRUE);
00377   print_proxy("if ((_pRpcMessage->DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n");
00378   indent++;
00379   print_proxy("NdrConvert( &__frame->_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset );
00380   indent--;
00381   fprintf(proxy, "\n");
00382 
00383   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_IN, PHASE_UNMARSHAL);
00384   fprintf(proxy, "\n");
00385 
00386   assign_stub_out_args( proxy, indent, func, "__frame->" );
00387 
00388   print_proxy("*_pdwStubPhase = STUB_CALL_SERVER;\n");
00389   fprintf(proxy, "\n");
00390   print_proxy( "%s", has_ret ? "__frame->_RetVal = " : "" );
00391   if (cas) fprintf(proxy, "%s_%s_Stub", iface->name, cas);
00392   else fprintf(proxy, "__frame->_This->lpVtbl->%s", get_name(func));
00393   fprintf(proxy, "(__frame->_This");
00394 
00395   if (type_get_function_args(func->type))
00396   {
00397       LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
00398           fprintf(proxy, ", %s__frame->%s", is_array(arg->type) && !type_array_is_decl_as_ptr(arg->type) ? "*" :"" , arg->name);
00399   }
00400   fprintf(proxy, ");\n");
00401   fprintf(proxy, "\n");
00402   print_proxy("*_pdwStubPhase = STUB_MARSHAL;\n");
00403   fprintf(proxy, "\n");
00404 
00405   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE);
00406 
00407   if (!is_void(type_function_get_rettype(func->type)))
00408     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE);
00409 
00410   print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &__frame->_StubMsg);\n");
00411 
00412   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL);
00413   fprintf(proxy, "\n");
00414 
00415   /* marshall the return value */
00416   if (!is_void(type_function_get_rettype(func->type)))
00417     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL);
00418 
00419   indent--;
00420   print_proxy("}\n");
00421   print_proxy("RpcFinally\n");
00422   print_proxy("{\n");
00423   indent++;
00424   print_proxy( "__finally_%s_%s_Stub( __frame );\n", iface->name, get_name(func) );
00425   indent--;
00426   print_proxy("}\n");
00427   print_proxy("RpcEndFinally\n");
00428 
00429   print_proxy("_pRpcMessage->BufferLength = __frame->_StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer;\n");
00430   indent--;
00431 
00432   print_proxy("}\n");
00433   print_proxy("\n");
00434 }
00435 
00436 static void gen_stub_thunk( type_t *iface, const var_t *func, unsigned int proc_offset )
00437 {
00438     int has_ret = !is_void( type_function_get_rettype( func->type ));
00439     const var_t *arg, *callas = is_callas( func->attrs );
00440     const var_list_t *args = type_get_function_args( func->type );
00441 
00442     indent = 0;
00443     print_proxy( "void __RPC_API %s_%s_Thunk( PMIDL_STUB_MESSAGE pStubMsg )\n",
00444                  iface->name, get_name(func) );
00445     print_proxy( "{\n");
00446     indent++;
00447     write_func_param_struct( proxy, iface, func->type,
00448                              "*pParamStruct = (struct _PARAM_STRUCT *)pStubMsg->StackTop", has_ret );
00449     print_proxy( "%s%s_%s_Stub( pParamStruct->This",
00450                  has_ret ? "pParamStruct->_RetVal = " : "", iface->name, callas->name );
00451     indent++;
00452     if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
00453     {
00454         fprintf( proxy, ",\n%*spParamStruct->%s", 4 * indent, "", arg->name );
00455     }
00456     fprintf( proxy, " );\n" );
00457     indent--;
00458     indent--;
00459     print_proxy( "}\n\n");
00460 }
00461 
00462 int count_methods(const type_t *iface)
00463 {
00464     const statement_t *stmt;
00465     int count = 0;
00466 
00467     if (type_iface_get_inherit(iface))
00468         count = count_methods(type_iface_get_inherit(iface));
00469 
00470     STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
00471         const var_t *func = stmt->u.var;
00472         if (!is_callas(func->attrs)) count++;
00473     }
00474     return count;
00475 }
00476 
00477 static const statement_t * get_callas_source(const type_t * iface, const var_t * def)
00478 {
00479   const statement_t * source;
00480   STATEMENTS_FOR_EACH_FUNC( source, type_iface_get_stmts(iface)) {
00481     const var_t * cas = is_callas(source->u.var->attrs );
00482     if (cas && !strcmp(def->name, cas->name))
00483       return source;
00484   }
00485   return NULL;
00486 }
00487 
00488 static void write_proxy_procformatstring_offsets( const type_t *iface, int skip )
00489 {
00490     const statement_t *stmt;
00491 
00492     if (type_iface_get_inherit(iface))
00493         write_proxy_procformatstring_offsets( type_iface_get_inherit(iface), need_delegation(iface));
00494     else
00495         return;
00496 
00497     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
00498     {
00499         const var_t *func = stmt->u.var;
00500         int missing = 0;
00501 
00502         if (is_callas(func->attrs)) continue;
00503         if (is_local(func->attrs))
00504         {
00505             const statement_t * callas_source = get_callas_source(iface, func);
00506             if (!callas_source)
00507                 missing = 1;
00508             else
00509                 func = callas_source->u.var;
00510         }
00511         if (skip || missing)
00512             print_proxy( "(unsigned short)-1,  /* %s::%s */\n", iface->name, get_name(func));
00513         else
00514             print_proxy( "%u,  /* %s::%s */\n", func->procstring_offset, iface->name, get_name(func));
00515     }
00516 }
00517 
00518 static int write_proxy_methods(type_t *iface, int skip)
00519 {
00520   const statement_t *stmt;
00521   int i = 0;
00522 
00523   if (type_iface_get_inherit(iface))
00524     i = write_proxy_methods(type_iface_get_inherit(iface),
00525                             need_delegation(iface));
00526   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
00527     const var_t *func = stmt->u.var;
00528     if (!is_callas(func->attrs)) {
00529       if (skip || (is_local(func->attrs) && !get_callas_source(iface, func)))
00530           print_proxy( "0,  /* %s::%s */\n", iface->name, get_name(func));
00531       else if (is_interpreted_func( iface, func ) &&
00532                !is_local( func->attrs ) &&
00533                type_iface_get_inherit(iface))
00534           print_proxy( "(void *)-1,  /* %s::%s */\n", iface->name, get_name(func));
00535       else
00536           print_proxy( "%s_%s_Proxy,\n", iface->name, get_name(func));
00537       i++;
00538     }
00539   }
00540   return i;
00541 }
00542 
00543 static int write_stub_methods(type_t *iface, int skip)
00544 {
00545   const statement_t *stmt;
00546   int i = 0;
00547 
00548   if (type_iface_get_inherit(iface))
00549     i = write_stub_methods(type_iface_get_inherit(iface), need_delegation(iface));
00550   else
00551     return i; /* skip IUnknown */
00552 
00553   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
00554     const var_t *func = stmt->u.var;
00555     if (!is_callas(func->attrs)) {
00556       int missing = 0;
00557       const char * fname = get_name(func);
00558       if(is_local(func->attrs)) {
00559         const statement_t * callas_source = get_callas_source(iface, func);
00560         if(!callas_source)
00561           missing = 1;
00562         else
00563           fname = get_name(callas_source->u.var);
00564       }
00565       if (i) fprintf(proxy,",\n");
00566       if (skip || missing) print_proxy("STUB_FORWARDING_FUNCTION");
00567       else if (is_interpreted_func( iface, func ))
00568           print_proxy( "(PRPC_STUB_FUNCTION)%s", get_stub_mode() == MODE_Oif ? "NdrStubCall2" : "NdrStubCall" );
00569       else print_proxy( "%s_%s_Stub", iface->name, fname);
00570       i++;
00571     }
00572   }
00573   return i;
00574 }
00575 
00576 static void write_thunk_methods( type_t *iface, int skip )
00577 {
00578     const statement_t *stmt;
00579 
00580     if (type_iface_get_inherit( iface ))
00581         write_thunk_methods( type_iface_get_inherit(iface), need_delegation(iface) );
00582     else
00583         return; /* skip IUnknown */
00584 
00585     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
00586     {
00587         var_t *func = stmt->u.var;
00588         const statement_t * callas_source = NULL;
00589 
00590         if (is_callas(func->attrs)) continue;
00591         if (is_local(func->attrs)) callas_source = get_callas_source(iface, func);
00592 
00593         if (!skip && callas_source && is_interpreted_func( iface, func ))
00594             print_proxy( "%s_%s_Thunk,\n", iface->name, get_name(callas_source->u.var) );
00595         else
00596             print_proxy( "0, /* %s::%s */\n", iface->name, get_name(func) );
00597     }
00598 }
00599 
00600 static void write_proxy(type_t *iface, unsigned int *proc_offset)
00601 {
00602   int count;
00603   const statement_t *stmt;
00604   int first_func = 1;
00605   int needs_stub_thunks = 0;
00606   int needs_inline_stubs = need_inline_stubs( iface ) || need_delegation( iface );
00607 
00608   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
00609     var_t *func = stmt->u.var;
00610     if (first_func) {
00611       fprintf(proxy, "/*****************************************************************************\n");
00612       fprintf(proxy, " * %s interface\n", iface->name);
00613       fprintf(proxy, " */\n");
00614       first_func = 0;
00615     }
00616     if (!is_local(func->attrs)) {
00617       const var_t *cas = is_callas(func->attrs);
00618       const char *cname = cas ? cas->name : NULL;
00619       int idx = func->type->details.function->idx;
00620       if (cname) {
00621           const statement_t *stmt2;
00622           STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) {
00623               const var_t *m = stmt2->u.var;
00624               if (!strcmp(m->name, cname))
00625               {
00626                   idx = m->type->details.function->idx;
00627                   break;
00628               }
00629           }
00630       }
00631       func->procstring_offset = *proc_offset;
00632       gen_proxy(iface, func, idx, *proc_offset);
00633       gen_stub(iface, func, cname, *proc_offset);
00634       if (cas && is_interpreted_func( iface, func ))
00635       {
00636           needs_stub_thunks = 1;
00637           gen_stub_thunk(iface, func, *proc_offset);
00638       }
00639       *proc_offset += get_size_procformatstring_func( iface, func );
00640     }
00641   }
00642 
00643   count = count_methods(iface);
00644 
00645   print_proxy( "static const unsigned short %s_FormatStringOffsetTable[] =\n", iface->name );
00646   print_proxy( "{\n" );
00647   indent++;
00648   write_proxy_procformatstring_offsets( iface, 0 );
00649   indent--;
00650   print_proxy( "};\n\n" );
00651 
00652   /* proxy info */
00653   if (get_stub_mode() == MODE_Oif)
00654   {
00655       print_proxy( "static const MIDL_STUBLESS_PROXY_INFO %s_ProxyInfo =\n", iface->name );
00656       print_proxy( "{\n" );
00657       indent++;
00658       print_proxy( "&Object_StubDesc,\n" );
00659       print_proxy( "__MIDL_ProcFormatString.Format,\n" );
00660       print_proxy( "&%s_FormatStringOffsetTable[-3],\n", iface->name );
00661       print_proxy( "0,\n" );
00662       print_proxy( "0,\n" );
00663       print_proxy( "0\n" );
00664       indent--;
00665       print_proxy( "};\n\n" );
00666   }
00667 
00668   /* proxy vtable */
00669   print_proxy( "static %sCINTERFACE_PROXY_VTABLE(%d) _%sProxyVtbl =\n",
00670                need_delegation_indirect(iface) ? "" : "const ", count, iface->name);
00671   print_proxy( "{\n");
00672   indent++;
00673   print_proxy( "{\n");
00674   indent++;
00675   if (get_stub_mode() == MODE_Oif) print_proxy( "&%s_ProxyInfo,\n", iface->name );
00676   print_proxy( "&IID_%s,\n", iface->name);
00677   indent--;
00678   print_proxy( "},\n");
00679   print_proxy( "{\n");
00680   indent++;
00681   write_proxy_methods(iface, FALSE);
00682   indent--;
00683   print_proxy( "}\n");
00684   indent--;
00685   print_proxy( "};\n\n");
00686 
00687   /* stub thunk table */
00688   if (needs_stub_thunks)
00689   {
00690       print_proxy( "static const STUB_THUNK %s_StubThunkTable[] =\n", iface->name);
00691       print_proxy( "{\n");
00692       indent++;
00693       write_thunk_methods( iface, 0 );
00694       indent--;
00695       print_proxy( "};\n\n");
00696   }
00697 
00698   /* server info */
00699   print_proxy( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", iface->name );
00700   print_proxy( "{\n" );
00701   indent++;
00702   print_proxy( "&Object_StubDesc,\n" );
00703   print_proxy( "0,\n" );
00704   print_proxy( "__MIDL_ProcFormatString.Format,\n" );
00705   print_proxy( "&%s_FormatStringOffsetTable[-3],\n", iface->name );
00706   if (needs_stub_thunks)
00707       print_proxy( "&%s_StubThunkTable[-3],\n", iface->name );
00708   else
00709       print_proxy( "0,\n" );
00710   print_proxy( "0,\n" );
00711   print_proxy( "0,\n" );
00712   print_proxy( "0\n" );
00713   indent--;
00714   print_proxy( "};\n\n" );
00715 
00716   /* stub vtable */
00717   if (needs_inline_stubs)
00718   {
00719       print_proxy( "static const PRPC_STUB_FUNCTION %s_table[] =\n", iface->name);
00720       print_proxy( "{\n");
00721       indent++;
00722       write_stub_methods(iface, FALSE);
00723       fprintf(proxy, "\n");
00724       indent--;
00725       fprintf(proxy, "};\n\n");
00726   }
00727   print_proxy( "static %sCInterfaceStubVtbl _%sStubVtbl =\n",
00728                need_delegation_indirect(iface) ? "" : "const ", iface->name);
00729   print_proxy( "{\n");
00730   indent++;
00731   print_proxy( "{\n");
00732   indent++;
00733   print_proxy( "&IID_%s,\n", iface->name);
00734   print_proxy( "&%s_ServerInfo,\n", iface->name );
00735   print_proxy( "%d,\n", count);
00736   if (needs_inline_stubs) print_proxy( "&%s_table[-3]\n", iface->name );
00737   else print_proxy( "0\n" );
00738   indent--;
00739   print_proxy( "},\n");
00740   print_proxy( "{\n");
00741   indent++;
00742   print_proxy( "CStdStubBuffer_%s\n", need_delegation_indirect(iface) ? "DELEGATING_METHODS" : "METHODS");
00743   indent--;
00744   print_proxy( "}\n");
00745   indent--;
00746   print_proxy( "};\n");
00747   print_proxy( "\n");
00748 }
00749 
00750 static int does_any_iface(const statement_list_t *stmts, type_pred_t pred)
00751 {
00752   const statement_t *stmt;
00753 
00754   if (stmts)
00755     LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
00756     {
00757       if (stmt->type == STMT_LIBRARY)
00758       {
00759           if (does_any_iface(stmt->u.lib->stmts, pred))
00760               return TRUE;
00761       }
00762       else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
00763       {
00764         if (pred(stmt->u.type))
00765           return TRUE;
00766       }
00767     }
00768 
00769   return FALSE;
00770 }
00771 
00772 int need_proxy(const type_t *iface)
00773 {
00774     if (!is_object( iface )) return 0;
00775     if (is_local( iface->attrs )) return 0;
00776     if (is_attr( iface->attrs, ATTR_OLEAUTOMATION )) return 0;
00777     if (is_attr( iface->attrs, ATTR_DISPINTERFACE )) return 0;
00778     return 1;
00779 }
00780 
00781 int need_stub(const type_t *iface)
00782 {
00783   return !is_object(iface) && !is_local(iface->attrs);
00784 }
00785 
00786 int need_proxy_file(const statement_list_t *stmts)
00787 {
00788   return does_any_iface(stmts, need_proxy);
00789 }
00790 
00791 int need_inline_stubs(const type_t *iface)
00792 {
00793     const statement_t *stmt;
00794 
00795     if (get_stub_mode() == MODE_Os) return 1;
00796 
00797     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
00798     {
00799         const var_t *func = stmt->u.var;
00800         if (is_local( func->attrs )) continue;
00801         if (!is_interpreted_func( iface, func )) return 1;
00802     }
00803     return 0;
00804 }
00805 
00806 static int need_proxy_and_inline_stubs(const type_t *iface)
00807 {
00808     const statement_t *stmt;
00809 
00810     if (!need_proxy( iface )) return 0;
00811     if (get_stub_mode() == MODE_Os) return 1;
00812 
00813     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
00814     {
00815         const var_t *func = stmt->u.var;
00816         if (is_local( func->attrs )) continue;
00817         if (!is_interpreted_func( iface, func )) return 1;
00818     }
00819     return 0;
00820 }
00821 
00822 int need_stub_files(const statement_list_t *stmts)
00823 {
00824   return does_any_iface(stmts, need_stub);
00825 }
00826 
00827 int need_inline_stubs_file(const statement_list_t *stmts)
00828 {
00829   return does_any_iface(stmts, need_inline_stubs);
00830 }
00831 
00832 static void write_proxy_stmts(const statement_list_t *stmts, unsigned int *proc_offset)
00833 {
00834   const statement_t *stmt;
00835   if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
00836   {
00837     if (stmt->type == STMT_LIBRARY)
00838       write_proxy_stmts(stmt->u.lib->stmts, proc_offset);
00839     else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
00840     {
00841       if (need_proxy(stmt->u.type))
00842         write_proxy(stmt->u.type, proc_offset);
00843     }
00844   }
00845 }
00846 
00847 static int cmp_iid( const void *ptr1, const void *ptr2 )
00848 {
00849     const type_t * const *iface1 = ptr1;
00850     const type_t * const *iface2 = ptr2;
00851     const UUID *uuid1 = get_attrp( (*iface1)->attrs, ATTR_UUID );
00852     const UUID *uuid2 = get_attrp( (*iface2)->attrs, ATTR_UUID );
00853     return memcmp( uuid1, uuid2, sizeof(UUID) );
00854 }
00855 
00856 static void build_iface_list( const statement_list_t *stmts, type_t **ifaces[], int *count )
00857 {
00858     const statement_t *stmt;
00859 
00860     if (!stmts) return;
00861     LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
00862     {
00863         if (stmt->type == STMT_LIBRARY)
00864             build_iface_list(stmt->u.lib->stmts, ifaces, count);
00865         else if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
00866         {
00867             type_t *iface = stmt->u.type;
00868             if (type_iface_get_inherit(iface) && need_proxy(iface))
00869             {
00870                 *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) );
00871                 (*ifaces)[(*count)++] = iface;
00872             }
00873         }
00874     }
00875 }
00876 
00877 static type_t **sort_interfaces( const statement_list_t *stmts, int *count )
00878 {
00879     type_t **ifaces = NULL;
00880 
00881     *count = 0;
00882     build_iface_list( stmts, &ifaces, count );
00883     qsort( ifaces, *count, sizeof(*ifaces), cmp_iid );
00884     return ifaces;
00885 }
00886 
00887 static void write_proxy_routines(const statement_list_t *stmts)
00888 {
00889   int expr_eval_routines;
00890   unsigned int proc_offset = 0;
00891   char *file_id = proxy_token;
00892   int i, count, have_baseiid = 0;
00893   type_t **interfaces;
00894   const type_t * delegate_to;
00895 
00896   print_proxy( "#ifndef __REDQ_RPCPROXY_H_VERSION__\n");
00897   print_proxy( "#define __REQUIRED_RPCPROXY_H_VERSION__ %u\n", get_stub_mode() == MODE_Oif ? 475 : 440);
00898   print_proxy( "#endif\n");
00899   print_proxy( "\n");
00900   if (get_stub_mode() == MODE_Oif) print_proxy( "#define USE_STUBLESS_PROXY\n");
00901   print_proxy( "#include \"rpcproxy.h\"\n");
00902   print_proxy( "#ifndef __RPCPROXY_H_VERSION__\n");
00903   print_proxy( "#error This code needs a newer version of rpcproxy.h\n");
00904   print_proxy( "#endif /* __RPCPROXY_H_VERSION__ */\n");
00905   print_proxy( "\n");
00906   print_proxy( "#include \"%s\"\n", header_name);
00907   print_proxy( "\n");
00908 
00909   if (does_any_iface(stmts, need_proxy_and_inline_stubs))
00910   {
00911       write_exceptions( proxy );
00912       print_proxy( "\n");
00913       print_proxy( "struct __proxy_frame\n");
00914       print_proxy( "{\n");
00915       print_proxy( "    __DECL_EXCEPTION_FRAME\n");
00916       print_proxy( "    MIDL_STUB_MESSAGE _StubMsg;\n");
00917       print_proxy( "    void             *This;\n");
00918       print_proxy( "};\n");
00919       print_proxy( "\n");
00920       print_proxy("static int __proxy_filter( struct __proxy_frame *__frame )\n");
00921       print_proxy( "{\n");
00922       print_proxy( "    return (__frame->_StubMsg.dwStubPhase != PROXY_SENDRECEIVE);\n");
00923       print_proxy( "}\n");
00924       print_proxy( "\n");
00925   }
00926 
00927   write_formatstringsdecl(proxy, indent, stmts, need_proxy);
00928   write_stubdescproto();
00929   write_proxy_stmts(stmts, &proc_offset);
00930 
00931   expr_eval_routines = write_expr_eval_routines(proxy, proxy_token);
00932   if (expr_eval_routines)
00933       write_expr_eval_routine_list(proxy, proxy_token);
00934   write_user_quad_list(proxy);
00935   write_stubdesc(expr_eval_routines);
00936 
00937   print_proxy( "#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32);
00938   print_proxy( "#error Currently only Wine and WIN32 are supported.\n");
00939   print_proxy( "#endif\n");
00940   print_proxy( "\n");
00941   write_procformatstring(proxy, stmts, need_proxy);
00942   write_typeformatstring(proxy, stmts, need_proxy);
00943 
00944   interfaces = sort_interfaces(stmts, &count);
00945   fprintf(proxy, "static const CInterfaceProxyVtbl* const _%s_ProxyVtblList[] =\n", file_id);
00946   fprintf(proxy, "{\n");
00947   for (i = 0; i < count; i++)
00948       fprintf(proxy, "    (const CInterfaceProxyVtbl*)&_%sProxyVtbl,\n", interfaces[i]->name);
00949   fprintf(proxy, "    0\n");
00950   fprintf(proxy, "};\n");
00951   fprintf(proxy, "\n");
00952 
00953   fprintf(proxy, "static const CInterfaceStubVtbl* const _%s_StubVtblList[] =\n", file_id);
00954   fprintf(proxy, "{\n");
00955   for (i = 0; i < count; i++)
00956       fprintf(proxy, "    &_%sStubVtbl,\n", interfaces[i]->name);
00957   fprintf(proxy, "    0\n");
00958   fprintf(proxy, "};\n");
00959   fprintf(proxy, "\n");
00960 
00961   fprintf(proxy, "static PCInterfaceName const _%s_InterfaceNamesList[] =\n", file_id);
00962   fprintf(proxy, "{\n");
00963   for (i = 0; i < count; i++)
00964       fprintf(proxy, "    \"%s\",\n", interfaces[i]->name);
00965   fprintf(proxy, "    0\n");
00966   fprintf(proxy, "};\n");
00967   fprintf(proxy, "\n");
00968 
00969   for (i = 0; i < count; i++)
00970       if ((have_baseiid = get_delegation_indirect( interfaces[i], NULL ))) break;
00971 
00972   if (have_baseiid)
00973   {
00974       fprintf(proxy, "static const IID * _%s_BaseIIDList[] =\n", file_id);
00975       fprintf(proxy, "{\n");
00976       for (i = 0; i < count; i++)
00977       {
00978           if (get_delegation_indirect(interfaces[i], &delegate_to))
00979               fprintf( proxy, "    &IID_%s,  /* %s */\n", delegate_to->name, interfaces[i]->name );
00980           else
00981               fprintf( proxy, "    0,\n" );
00982       }
00983       fprintf(proxy, "    0\n");
00984       fprintf(proxy, "};\n");
00985       fprintf(proxy, "\n");
00986   }
00987 
00988   fprintf(proxy, "static int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id);
00989   fprintf(proxy, "{\n");
00990   fprintf(proxy, "    int low = 0, high = %d;\n", count - 1);
00991   fprintf(proxy, "\n");
00992   fprintf(proxy, "    while (low <= high)\n");
00993   fprintf(proxy, "    {\n");
00994   fprintf(proxy, "        int pos = (low + high) / 2;\n");
00995   fprintf(proxy, "        int res = IID_GENERIC_CHECK_IID(_%s, pIID, pos);\n", file_id);
00996   fprintf(proxy, "        if (!res) { *pIndex = pos; return 1; }\n");
00997   fprintf(proxy, "        if (res > 0) low = pos + 1;\n");
00998   fprintf(proxy, "        else high = pos - 1;\n");
00999   fprintf(proxy, "    }\n");
01000   fprintf(proxy, "    return 0;\n");
01001   fprintf(proxy, "}\n");
01002   fprintf(proxy, "\n");
01003 
01004   fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo DECLSPEC_HIDDEN =\n", file_id);
01005   fprintf(proxy, "{\n");
01006   fprintf(proxy, "    (const PCInterfaceProxyVtblList*)_%s_ProxyVtblList,\n", file_id);
01007   fprintf(proxy, "    (const PCInterfaceStubVtblList*)_%s_StubVtblList,\n", file_id);
01008   fprintf(proxy, "    _%s_InterfaceNamesList,\n", file_id);
01009   if (have_baseiid) fprintf(proxy, "    _%s_BaseIIDList,\n", file_id);
01010   else fprintf(proxy, "    0,\n");
01011   fprintf(proxy, "    _%s_IID_Lookup,\n", file_id);
01012   fprintf(proxy, "    %d,\n", count);
01013   fprintf(proxy, "    %d,\n", get_stub_mode() == MODE_Oif ? 2 : 1);
01014   fprintf(proxy, "    0,\n");
01015   fprintf(proxy, "    0,\n");
01016   fprintf(proxy, "    0,\n");
01017   fprintf(proxy, "    0\n");
01018   fprintf(proxy, "};\n");
01019 }
01020 
01021 void write_proxies(const statement_list_t *stmts)
01022 {
01023   if (!do_proxies) return;
01024   if (do_everything && !need_proxy_file(stmts)) return;
01025 
01026   init_proxy(stmts);
01027   if(!proxy) return;
01028 
01029   if (do_win32 && do_win64)
01030   {
01031       fprintf(proxy, "\n#ifndef _WIN64\n\n");
01032       pointer_size = 4;
01033       write_proxy_routines( stmts );
01034       fprintf(proxy, "\n#else /* _WIN64 */\n\n");
01035       pointer_size = 8;
01036       write_proxy_routines( stmts );
01037       fprintf(proxy, "\n#endif /* _WIN64 */\n");
01038   }
01039   else if (do_win32)
01040   {
01041       pointer_size = 4;
01042       write_proxy_routines( stmts );
01043   }
01044   else if (do_win64)
01045   {
01046       pointer_size = 8;
01047       write_proxy_routines( stmts );
01048   }
01049 
01050   fclose(proxy);
01051 }

Generated on Sun May 27 2012 04:37:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.