plugin.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id: plugin.c 1393 2007-11-22 18:26:05Z martin $
00005  begin       : Thu Apr 03 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #include "plugin_p.h"
00033 #include <gwenhywfar/buffer.h>
00034 #include <gwenhywfar/debug.h>
00035 #include <gwenhywfar/directory.h>
00036 #include <gwenhywfar/pathmanager.h>
00037 #include <gwenhywfar/gwenhywfar.h>
00038 
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #ifdef HAVE_UNISTD_H
00042 # include <unistd.h>
00043 #endif
00044 #include <errno.h>
00045 #include <string.h>
00046 #ifdef HAVE_STRINGS_H
00047 # include <strings.h>
00048 #endif
00049 #include <ctype.h>
00050 
00051 #ifdef OS_WIN32
00052 # include <windows.h>
00053 #endif
00054 
00055 static GWEN_PLUGIN_MANAGER_LIST *gwen_plugin_manager__list=0;
00056 
00057 
00058 GWEN_INHERIT_FUNCTIONS(GWEN_PLUGIN)
00059 GWEN_LIST_FUNCTIONS(GWEN_PLUGIN, GWEN_Plugin)
00060 GWEN_INHERIT_FUNCTIONS(GWEN_PLUGIN_MANAGER)
00061 GWEN_LIST_FUNCTIONS(GWEN_PLUGIN_MANAGER, GWEN_PluginManager)
00062 
00063 
00064 
00065 int GWEN_Plugin_ModuleInit(){
00066   gwen_plugin_manager__list=GWEN_PluginManager_List_new();
00067   return 0;
00068 }
00069 
00070 
00071 
00072 int GWEN_Plugin_ModuleFini(){
00073   GWEN_PluginManager_List_free(gwen_plugin_manager__list);
00074   return 0;
00075 }
00076 
00077 
00078 
00079 GWEN_PLUGIN *GWEN_Plugin_new(GWEN_PLUGIN_MANAGER *pm,
00080                              const char *name,
00081                              const char *fileName){
00082   GWEN_PLUGIN *p;
00083 
00084   assert(pm);
00085   assert(name);
00086   GWEN_NEW_OBJECT(GWEN_PLUGIN, p);
00087   DBG_MEM_INC("GWEN_PLUGIN", 0);
00088   p->refCount=1;
00089   GWEN_INHERIT_INIT(GWEN_PLUGIN, p);
00090   GWEN_LIST_INIT(GWEN_PLUGIN, p);
00091   p->manager=pm;
00092   p->name=strdup(name);
00093   if (fileName)
00094     p->fileName=strdup(fileName);
00095 
00096   return p;
00097 }
00098 
00099 
00100 
00101 void GWEN_Plugin_free(GWEN_PLUGIN *p){
00102   if (p) {
00103     DBG_MEM_DEC("GWEN_PLUGIN");
00104     assert(p->refCount);
00105     if (--(p->refCount)==0) {
00106       GWEN_INHERIT_FINI(GWEN_PLUGIN, p);
00107       free(p->name);
00108       free(p->fileName);
00109       if (p->libLoader) {
00110         GWEN_LibLoader_CloseLibrary(p->libLoader);
00111         GWEN_LibLoader_free(p->libLoader);
00112       }
00113       GWEN_LIST_FINI(GWEN_PLUGIN, p);
00114       GWEN_FREE_OBJECT(p);
00115     } /* if refCount reaches zero */
00116   } /* if p */
00117 }
00118 
00119 
00120 
00121 void GWEN_Plugin_Attach(GWEN_PLUGIN *p){
00122   assert(p);
00123   assert(p->refCount);
00124   DBG_MEM_INC("GWEN_PLUGIN", 1);
00125   p->refCount++;
00126 }
00127 
00128 
00129 
00130 GWEN_PLUGIN_MANAGER *GWEN_Plugin_GetManager(const GWEN_PLUGIN *p){
00131   assert(p);
00132   return p->manager;
00133 }
00134 
00135 
00136 
00137 const char *GWEN_Plugin_GetName(const GWEN_PLUGIN *p){
00138   assert(p);
00139   return p->name;
00140 }
00141 
00142 
00143 
00144 const char *GWEN_Plugin_GetFileName(const GWEN_PLUGIN *p){
00145   assert(p);
00146   return p->fileName;
00147 }
00148 
00149 
00150 
00151 GWEN_LIBLOADER *GWEN_Plugin_GetLibLoader(const GWEN_PLUGIN *p){
00152   assert(p);
00153   return p->libLoader;
00154 }
00155 
00156 
00157 
00158 void GWEN_Plugin_SetLibLoader(GWEN_PLUGIN *p, GWEN_LIBLOADER *ll){
00159   assert(p);
00160   p->libLoader=ll;
00161 }
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 GWEN_PLUGIN_MANAGER *GWEN_PluginManager_new(const char *name,
00171                                             const char *destLib){
00172   GWEN_PLUGIN_MANAGER *pm;
00173 
00174   assert(name);
00175   assert(destLib);
00176   GWEN_NEW_OBJECT(GWEN_PLUGIN_MANAGER, pm);
00177   DBG_MEM_INC("GWEN_PLUGIN_MANAGER", 0);
00178   GWEN_INHERIT_INIT(GWEN_PLUGIN_MANAGER, pm);
00179   GWEN_LIST_INIT(GWEN_PLUGIN_MANAGER, pm);
00180   pm->name=strdup(name);
00181   pm->destLib=strdup(destLib);
00182   pm->plugins=GWEN_Plugin_List_new();
00183 
00184   return pm;
00185 }
00186 
00187 
00188 
00189 void GWEN_PluginManager_free(GWEN_PLUGIN_MANAGER *pm){
00190   if (pm) {
00191     DBG_MEM_DEC("GWEN_PLUGIN_MANAGER");
00192     GWEN_Plugin_List_free(pm->plugins);
00193     GWEN_INHERIT_FINI(GWEN_PLUGIN_MANAGER, pm);
00194     free(pm->destLib);
00195     free(pm->name);
00196     GWEN_LIST_FINI(GWEN_PLUGIN_MANAGER, pm);
00197     GWEN_FREE_OBJECT(pm);
00198   }
00199 }
00200 
00201 
00202 
00203 const char *GWEN_PluginManager_GetName(const GWEN_PLUGIN_MANAGER *pm){
00204   assert(pm);
00205   return pm->name;
00206 }
00207 
00208 
00209 
00210 int GWEN_PluginManager_AddPath(GWEN_PLUGIN_MANAGER *pm,
00211                                const char *callingLib,
00212                                const char *s){
00213   assert(pm);
00214   return GWEN_PathManager_AddPath(callingLib,
00215                                   pm->destLib,
00216                                   pm->name,
00217                                   s);
00218 }
00219 
00220 
00221 
00222 int GWEN_PluginManager_AddRelPath(GWEN_PLUGIN_MANAGER *pm,
00223                                   const char *callingLib,
00224                                   const char *s,
00225                                   GWEN_PATHMANAGER_RELMODE rm) {
00226   assert(pm);
00227   return GWEN_PathManager_AddRelPath(callingLib,
00228                                      pm->destLib,
00229                                      pm->name,
00230                                      s,
00231                                      rm);
00232 }
00233 
00234 
00235 
00236 int GWEN_PluginManager_InsertPath(GWEN_PLUGIN_MANAGER *pm,
00237                                   const char *callingLib,
00238                                   const char *s) {
00239   assert(pm);
00240   return GWEN_PathManager_InsertPath(callingLib,
00241                                      pm->destLib,
00242                                      pm->name,
00243                                      s);
00244 }
00245 
00246 
00247 
00248 int GWEN_PluginManager_RemovePath(GWEN_PLUGIN_MANAGER *pm,
00249                                   const char *callingLib,
00250                                   const char *s) {
00251   assert(pm);
00252   return GWEN_PathManager_RemovePath(callingLib,
00253                                      pm->destLib,
00254                                      pm->name,
00255                                      s);
00256 }
00257 
00258 
00259 
00260 int GWEN_PluginManager_AddPathFromWinReg(GWEN_PLUGIN_MANAGER *pm,
00261                                          const char *callingLib,
00262                                          const char *keypath,
00263                                          const char *varname){
00264 #ifdef OS_WIN32
00265   HKEY hkey;
00266   TCHAR nbuffer[MAX_PATH];
00267   BYTE vbuffer[MAX_PATH];
00268   DWORD nsize;
00269   DWORD vsize;
00270   DWORD typ;
00271   int i;
00272 
00273   assert(pm);
00274 
00275   snprintf(nbuffer, sizeof(nbuffer), keypath);
00276 
00277   /* open the key */
00278   if (RegOpenKey(HKEY_LOCAL_MACHINE, nbuffer, &hkey)){
00279     DBG_INFO(GWEN_LOGDOMAIN, "RegOpenKey %s failed.", keypath);
00280     return 1;
00281   }
00282 
00283   /* find the variablename  */
00284   for (i=0;; i++) {
00285     nsize=sizeof(nbuffer);
00286     vsize=sizeof(vbuffer);
00287     if (ERROR_SUCCESS!=RegEnumValue(hkey,
00288                                     i,    /* index */
00289                                     nbuffer,
00290                                     &nsize,
00291                                     0,       /* reserved */
00292                                     &typ,
00293                                     vbuffer,
00294                                     &vsize))
00295       break;
00296     if (strcasecmp(nbuffer, varname)==0 && typ==REG_SZ) {
00297       /* variable found */
00298       RegCloseKey(hkey);
00299       return GWEN_PathManager_AddPath(callingLib,
00300                                       pm->destLib,
00301                                       pm->name,
00302                                       (char*)vbuffer);
00303     }
00304   } /* for */
00305 
00306   RegCloseKey(hkey);
00307   DBG_INFO(GWEN_LOGDOMAIN,
00308            "In RegKey \"%s\" the variable \"%s\" does not exist",
00309            keypath, varname);
00310   return 1;
00311 
00312 #else /* OS_WIN32 */
00313   return 0;
00314 #endif /* OS_WIN32 */
00315 }
00316 
00317 
00318 
00319 GWEN_PLUGIN *GWEN_PluginManager_LoadPlugin(GWEN_PLUGIN_MANAGER *pm,
00320                                            const char *modname){
00321   GWEN_LIBLOADER *ll;
00322   GWEN_PLUGIN *plugin;
00323   GWEN_PLUGIN_FACTORYFN fn;
00324   void *p;
00325   GWEN_BUFFER *nbuf;
00326   const char *s;
00327   const char *fname;
00328   int err;
00329   GWEN_STRINGLIST *sl;
00330   GWEN_STRINGLISTENTRY *se;
00331 
00332   assert(pm);
00333   ll=GWEN_LibLoader_new();
00334   sl=GWEN_PathManager_GetPaths(pm->destLib, pm->name);
00335   if (sl==NULL) {
00336     DBG_ERROR(GWEN_LOGDOMAIN, "No paths for plugins (%s)", pm->name);
00337     GWEN_LibLoader_free(ll);
00338     return NULL;
00339   }
00340   nbuf=GWEN_Buffer_new(0, 128, 0, 1);
00341   s=modname;
00342   while(*s) GWEN_Buffer_AppendByte(nbuf, tolower(*(s++)));
00343   se=GWEN_StringList_FirstEntry(sl);
00344   fname=0;
00345   while(se) {
00346     fname=GWEN_StringListEntry_Data(se);
00347     assert(fname);
00348     if (GWEN_LibLoader_OpenLibraryWithPath(ll, fname,
00349                                            GWEN_Buffer_GetStart(nbuf))==0)
00350       break;
00351     else {
00352       DBG_DEBUG(GWEN_LOGDOMAIN,
00353                 "Could not load plugin \"%s\" from \"%s\"", modname, fname);
00354     }
00355     se=GWEN_StringListEntry_Next(se);
00356   }
00357   if (!se) {
00358     DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" not found.", modname);
00359     GWEN_Buffer_free(nbuf);
00360     GWEN_StringList_free(sl);
00361     GWEN_LibLoader_free(ll);
00362     return NULL;
00363   }
00364   GWEN_Buffer_free(nbuf);
00365 
00366   /* create name of init function */
00367   nbuf=GWEN_Buffer_new(0, 128, 0, 1);
00368   s=pm->name;
00369   while(*s) GWEN_Buffer_AppendByte(nbuf, tolower(*(s++)));
00370   GWEN_Buffer_AppendByte(nbuf, '_');
00371   s=modname;
00372   while(*s) GWEN_Buffer_AppendByte(nbuf, tolower(*(s++)));
00373   GWEN_Buffer_AppendString(nbuf, "_factory");
00374 
00375   /* resolve name of factory function */
00376   err=GWEN_LibLoader_Resolve(ll, GWEN_Buffer_GetStart(nbuf), &p);
00377   if (err) {
00378     DBG_ERROR_ERR(GWEN_LOGDOMAIN, err);
00379     GWEN_Buffer_free(nbuf);
00380     GWEN_LibLoader_CloseLibrary(ll);
00381     GWEN_StringList_free(sl);
00382     GWEN_LibLoader_free(ll);
00383     return 0;
00384   }
00385   GWEN_Buffer_free(nbuf);
00386 
00387   fn=(GWEN_PLUGIN_FACTORYFN)p;
00388   assert(fn);
00389   plugin=fn(pm, modname, fname);
00390   if (!plugin) {
00391     DBG_ERROR(GWEN_LOGDOMAIN, "Error in plugin: No plugin created");
00392     GWEN_LibLoader_CloseLibrary(ll);
00393     GWEN_StringList_free(sl);
00394     GWEN_LibLoader_free(ll);
00395     return 0;
00396   }
00397 
00398   /* store libloader */
00399   GWEN_StringList_free(sl);
00400   GWEN_Plugin_SetLibLoader(plugin, ll);
00401   return plugin;
00402 }
00403 
00404 
00405 
00406 GWEN_PLUGIN *GWEN_PluginManager_LoadPluginFile(GWEN_PLUGIN_MANAGER *pm,
00407                                                const char *modname,
00408                                                const char *fname){
00409   GWEN_LIBLOADER *ll;
00410   GWEN_PLUGIN *plugin;
00411   GWEN_PLUGIN_FACTORYFN fn;
00412   void *p;
00413   GWEN_BUFFER *nbuf;
00414   const char *s;
00415   int err;
00416 
00417   ll=GWEN_LibLoader_new();
00418   if (GWEN_LibLoader_OpenLibrary(ll, fname)) {
00419     DBG_INFO(GWEN_LOGDOMAIN,
00420              "Could not load plugin \"%s\" (%s)", modname, fname);
00421     GWEN_LibLoader_free(ll);
00422     return 0;
00423   }
00424 
00425   /* create name of init function */
00426   nbuf=GWEN_Buffer_new(0, 128, 0, 1);
00427   s=pm->name;
00428   while(*s) GWEN_Buffer_AppendByte(nbuf, tolower(*(s++)));
00429   GWEN_Buffer_AppendByte(nbuf, '_');
00430   s=modname;
00431   while(*s) GWEN_Buffer_AppendByte(nbuf, tolower(*(s++)));
00432   GWEN_Buffer_AppendString(nbuf, "_factory");
00433 
00434   /* resolve name of factory function */
00435   err=GWEN_LibLoader_Resolve(ll, GWEN_Buffer_GetStart(nbuf), &p);
00436   if (err) {
00437     DBG_INFO_ERR(GWEN_LOGDOMAIN, err);
00438     GWEN_Buffer_free(nbuf);
00439     GWEN_LibLoader_CloseLibrary(ll);
00440     GWEN_LibLoader_free(ll);
00441     return 0;
00442   }
00443   GWEN_Buffer_free(nbuf);
00444 
00445   fn=(GWEN_PLUGIN_FACTORYFN)p;
00446   assert(fn);
00447   plugin=fn(pm, modname, fname);
00448   if (!plugin) {
00449     DBG_INFO(GWEN_LOGDOMAIN, "Error in plugin: No plugin created");
00450     GWEN_LibLoader_CloseLibrary(ll);
00451     GWEN_LibLoader_free(ll);
00452     return 0;
00453   }
00454 
00455   /* store libloader */
00456   GWEN_Plugin_SetLibLoader(plugin, ll);
00457 
00458   return plugin;
00459 }
00460 
00461 
00462 
00463 GWEN_PLUGIN *GWEN_PluginManager__FindPlugin(GWEN_PLUGIN_MANAGER *pm,
00464                                             const char *s){
00465   GWEN_PLUGIN *p;
00466 
00467   assert(pm);
00468   p=GWEN_Plugin_List_First(pm->plugins);
00469   while(p) {
00470     if (strcasecmp(p->name, s)==0)
00471       break;
00472     p=GWEN_Plugin_List_Next(p);
00473   }
00474 
00475   return p;
00476 }
00477 
00478 
00479 
00480 GWEN_PLUGIN *GWEN_PluginManager_GetPlugin(GWEN_PLUGIN_MANAGER *pm,
00481                                           const char *s){
00482   GWEN_PLUGIN *p;
00483 
00484   p=GWEN_PluginManager__FindPlugin(pm, s);
00485   if (p)
00486     return p;
00487   p=GWEN_PluginManager_LoadPlugin(pm, s);
00488   if (p) {
00489     GWEN_Plugin_List_Add(p, pm->plugins);
00490     return p;
00491   }
00492   DBG_INFO(GWEN_LOGDOMAIN, "Plugin \"%s\" not found", s);
00493   return 0;
00494 }
00495 
00496 
00497 
00498 GWEN_PLUGIN_MANAGER *GWEN_PluginManager_FindPluginManager(const char *s){
00499   GWEN_PLUGIN_MANAGER *pm;
00500 
00501   pm=GWEN_PluginManager_List_First(gwen_plugin_manager__list);
00502   while(pm) {
00503     if (strcasecmp(pm->name, s)==0)
00504       break;
00505     pm=GWEN_PluginManager_List_Next(pm);
00506   }
00507 
00508   return pm;
00509 }
00510 
00511 
00512 
00513 int GWEN_PluginManager_Register(GWEN_PLUGIN_MANAGER *pm){
00514   GWEN_PLUGIN_MANAGER *tpm;
00515   int rv;
00516 
00517   assert(gwen_plugin_manager__list);
00518   assert(pm);
00519   tpm=GWEN_PluginManager_FindPluginManager(pm->name);
00520   if (tpm) {
00521     DBG_ERROR(GWEN_LOGDOMAIN,
00522               "Plugin type \"%s\" already registered",
00523               pm->name);
00524     return -1;
00525   }
00526 
00527   rv=GWEN_PathManager_DefinePath(pm->destLib, pm->name);
00528   if (rv) {
00529     DBG_INFO(GWEN_LOGDOMAIN, "Could not define path for plugin [%s:%s]",
00530              pm->destLib, pm->name);
00531     return rv;
00532   }
00533 
00534   GWEN_PluginManager_List_Add(pm, gwen_plugin_manager__list);
00535   DBG_INFO(GWEN_LOGDOMAIN,
00536            "Plugin type \"%s\" registered",
00537            pm->name);
00538   return 0;
00539 }
00540 
00541 
00542 
00543 int GWEN_PluginManager_Unregister(GWEN_PLUGIN_MANAGER *pm){
00544   GWEN_PLUGIN_MANAGER *tpm;
00545   int rv;
00546 
00547   assert(gwen_plugin_manager__list);
00548   assert(pm);
00549   tpm=GWEN_PluginManager_FindPluginManager(pm->name);
00550   if (!tpm) {
00551     DBG_ERROR(GWEN_LOGDOMAIN,
00552               "Plugin type \"%s\" not registered",
00553               pm->name);
00554     return -1;
00555   }
00556 
00557   rv=GWEN_PathManager_UndefinePath(pm->destLib, pm->name);
00558   if (rv) {
00559     DBG_INFO(GWEN_LOGDOMAIN, "Could not undefine path for plugin [%s:%s]",
00560              pm->destLib, pm->name);
00561     return rv;
00562   }
00563 
00564   GWEN_PluginManager_List_Del(pm);
00565   DBG_INFO(GWEN_LOGDOMAIN,
00566            "Plugin type \"%s\" unregistered",
00567            pm->name);
00568   return 0;
00569 }
00570 
00571 
00572 
00573 GWEN_PLUGIN_DESCRIPTION_LIST2*
00574 GWEN_PluginManager_GetPluginDescrs(GWEN_PLUGIN_MANAGER *pm){
00575   GWEN_PLUGIN_DESCRIPTION_LIST2 *pl;
00576   GWEN_STRINGLIST *sl;
00577   GWEN_STRINGLISTENTRY *se;
00578 
00579   sl=GWEN_PathManager_GetPaths(pm->destLib, pm->name);
00580   if (sl==NULL) {
00581     DBG_ERROR(GWEN_LOGDOMAIN, "No paths for plugins (%s)", pm->name);
00582     return NULL;
00583   }
00584   se=GWEN_StringList_FirstEntry(sl);
00585   if (!se) {
00586     DBG_ERROR(GWEN_LOGDOMAIN, "No paths given");
00587     GWEN_StringList_free(sl);
00588     return 0;
00589   }
00590 
00591   pl=GWEN_PluginDescription_List2_new();
00592   while(se) {
00593     int rv;
00594     const char *path;
00595 
00596     path=GWEN_StringListEntry_Data(se);
00597     assert(path);
00598     rv=GWEN_LoadPluginDescrsByType(path, pm->name, pl);
00599     if (rv) {
00600       DBG_INFO(GWEN_LOGDOMAIN,
00601                "Error loading plugin description in \"%s\"", path);
00602     }
00603     se=GWEN_StringListEntry_Next(se);
00604   } /* while */
00605 
00606   if (GWEN_PluginDescription_List2_GetSize(pl)==0) {
00607     GWEN_PluginDescription_List2_free(pl);
00608     GWEN_StringList_free(sl);
00609     return 0;
00610   }
00611 
00612   GWEN_StringList_free(sl);
00613   return pl;
00614 }
00615 
00616 
00617 GWEN_STRINGLIST *GWEN_PluginManager_GetPaths(const GWEN_PLUGIN_MANAGER *pm){
00618   assert(pm);
00619   return GWEN_PathManager_GetPaths(pm->destLib, pm->name);
00620 }
00621 
00622 
00623 
00624 GWEN_PLUGIN_DESCRIPTION*
00625 GWEN_PluginManager_GetPluginDescr(GWEN_PLUGIN_MANAGER *pm,
00626                                   const char *modName) {
00627   GWEN_PLUGIN_DESCRIPTION_LIST2 *dl;
00628 
00629   dl=GWEN_PluginManager_GetPluginDescrs(pm);
00630   if (dl==0)
00631     return 0;
00632   else {
00633     GWEN_PLUGIN_DESCRIPTION_LIST2_ITERATOR *dit;
00634 
00635     dit=GWEN_PluginDescription_List2_First(dl);
00636     if (dit) {
00637       GWEN_PLUGIN_DESCRIPTION *d;
00638 
00639       d=GWEN_PluginDescription_List2Iterator_Data(dit);
00640       while(d) {
00641         if (strcasecmp(GWEN_PluginDescription_GetName(d), modName)==0)
00642           break;
00643         d=GWEN_PluginDescription_List2Iterator_Next(dit);
00644       }
00645       GWEN_PluginDescription_List2Iterator_free(dit);
00646 
00647       if (d) {
00648         d=GWEN_PluginDescription_dup(d);
00649         GWEN_PluginDescription_List2_freeAll(dl);
00650         return d;
00651       }
00652     }
00653     GWEN_PluginDescription_List2_freeAll(dl);
00654   }
00655 
00656   return 0;
00657 }
00658 
00659 
00660 
00661 
00662 
00663 

Generated on Fri Apr 11 01:53:47 2008 for gwenhywfar by  doxygen 1.5.5