OpenCBM
plugin.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2007,2008 Spiro Trikaliotis
8  *
9  */
10 
20 #include <windows.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <direct.h>
24 
25 #include <getopt.h>
26 
27 #include "archlib.h"
28 #include "archlib-windows.h"
29 #include "cbmioctl.h"
30 #include "configuration.h"
31 #include "version.h"
32 #include "arch.h"
33 #include "i_opencbm.h"
34 
35 #include "libmisc.h"
36 
38 #define DBG_USERMODE
39 
41 #define DBG_PROGNAME "INSTCBM.EXE"
42 
44 #define DBG_IS_DEBUG_C
45 
46 #include "debug.h"
47 
48 #include "instcbm.h"
49 
50 #include "opencbm-plugin.h"
51 
61 #define PLUGIN_PREFIX "opencbm-"
62 
72 #define PLUGIN_SUFFIX ".dll"
73 
95 static char *
96 malloc_plugin_file_name(const char *PluginName)
97 {
98  char * filename = NULL;
99 
100  FUNC_ENTER();
101 
102  do {
103  filename = cbmlibmisc_stralloc( sizeof(PLUGIN_PREFIX) - 1
104  + strlen(PluginName)
105  + sizeof(PLUGIN_SUFFIX) - 1 );
106 
107  if (filename == NULL)
108  break;
109 
110  strcpy(filename, PLUGIN_PREFIX);
111  strcat(filename, PluginName);
112  strcat(filename, PLUGIN_SUFFIX);
113 
114  } while (0);
115 
116  FUNC_LEAVE_STRING(filename);
117 }
118 
136 static BOOL
137 PluginAlreadyInList(const char * const PluginName, cbm_install_parameter_t * InstallParameter)
138 {
139  BOOL exists = FALSE;
140  cbm_install_parameter_plugin_t * currentPlugin;
141 
142  FUNC_ENTER();
143 
144  DBG_ASSERT(InstallParameter != NULL);
145  DBG_ASSERT(PluginName != NULL);
146 
147  for (currentPlugin = InstallParameter->PluginList; currentPlugin != NULL; currentPlugin = currentPlugin->Next) {
148  if (strcmp(currentPlugin->Name, PluginName) == 0) {
149  exists = TRUE;
150  break;
151  }
152  }
153 
154  FUNC_LEAVE_BOOL(exists);
155 }
156 
177 static void
178 PluginAddToList(cbm_install_parameter_t * InstallParameter, cbm_install_parameter_plugin_t * Plugin)
179 {
180  cbm_install_parameter_plugin_t * previousPlugin;
181 
182  FUNC_ENTER();
183 
184  DBG_ASSERT(InstallParameter != NULL);
185  DBG_ASSERT(Plugin != NULL);
186 
187  Plugin->Next = NULL;
188 
189  previousPlugin = (cbm_install_parameter_plugin_t *) & InstallParameter->PluginList;
190 
191  while (previousPlugin->Next) {
192  previousPlugin = previousPlugin->Next;
193  }
194 
195  DBG_ASSERT(previousPlugin);
196 
197  previousPlugin->Next = Plugin;
198 
199  FUNC_LEAVE();
200 }
201 
213 void
215 {
216  cbm_install_parameter_plugin_t * currentPlugin;
217  cbm_install_parameter_plugin_t * nextPlugin;
218 
219  FUNC_ENTER();
220 
221  DBG_ASSERT(InstallParameter != NULL);
222 
223  nextPlugin = InstallParameter->PluginList;
224 
225  while (nextPlugin != NULL) {
226  currentPlugin = nextPlugin;
227 
228  nextPlugin = currentPlugin->Next;
229 
230  free(currentPlugin->Name);
231  free(currentPlugin->FileName);
232  free(currentPlugin->OptionMemory);
233  free(currentPlugin);
234  }
235 
236  FUNC_LEAVE();
237 }
238 
260 static int CBMAPIDECL
261 getopt_long_callback(int Argc,
262  char * const Argv[],
263  const char *Optstring,
264  const struct option *Longopts)
265 {
266  int retValue;
267 
268  FUNC_ENTER();
269 
270  retValue = getopt_long(Argc, Argv, Optstring, Longopts, NULL);
271 
272  FUNC_LEAVE_INT(retValue);
273 }
274 
276 GetPluginData(const char * const PluginName, cbm_install_parameter_t * InstallParameter, int Argc, char * const Argv[])
277 {
278  HINSTANCE library = NULL;
279  char *plugin_file_name = NULL;
280  void *option_memory = NULL;
281 
282  BOOL error = TRUE;
283 
284  cbm_install_parameter_plugin_t * returnValue = NULL;
285 
286  FUNC_ENTER();
287 
288  do {
289  unsigned int option_memory_size = 0;
290 
291  opencbm_plugin_install_process_commandline_t * opencbm_plugin_install_process_commandline;
292  opencbm_plugin_install_get_needed_files_t * opencbm_plugin_install_get_needed_files;
293 
294  cbm_install_parameter_plugin_t * pluginData;
295 
297 
298  memset(&commandLineData, 0, sizeof(commandLineData));
299 
300  if (PluginAlreadyInList(PluginName, InstallParameter)) {
301  fprintf(stderr, "Please, do not add plugin '%s' multiple times!\n", PluginName);
302  break;
303  }
304 
305  pluginData = malloc(sizeof(*pluginData));
306  if ( ! pluginData)
307  break;
308 
309  memset(pluginData, 0, sizeof(*pluginData));
310 
311  plugin_file_name = malloc_plugin_file_name(PluginName);
312 
313  if (plugin_file_name == NULL)
314  break;
315 
316  /*
317  * Load the DLL. Make sure that we do not get a warning dialog
318  * if a dependancy DLL is not found.
319  */
320 
321  {
322  UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
323 
324  library = LoadLibrary(plugin_file_name);
325 
326  SetErrorMode(oldErrorMode);
327  }
328 
329  if (library == NULL) {
330  fprintf(stderr, "Error loading plugin '%s', ABORTING!.\n\n", PluginName);
331  DBG_ERROR((DBG_PREFIX "Error loading plugin '%s', ABORTING!", PluginName));
332  break;
333  }
334 
335  opencbm_plugin_install_process_commandline = (void *) GetProcAddress(library, "opencbm_plugin_install_process_commandline");
336  opencbm_plugin_install_get_needed_files = (void *) GetProcAddress(library, "opencbm_plugin_install_get_needed_files");
337 
338  if (0 == (opencbm_plugin_install_process_commandline && opencbm_plugin_install_get_needed_files))
339  break;
340 
341  option_memory_size = opencbm_plugin_install_process_commandline(&commandLineData);
342 
343  /* make sure option_memory_size is at least 1,
344  * because malloc(0) can return either NULL or a valid memory block.
345  * This way, we are consistent, regardless of how malloc() handles this.
346  */
347 
348  option_memory_size = (option_memory_size > 0) ? option_memory_size : 1;
349 
350  option_memory = malloc(option_memory_size);
351 
352  if (option_memory == NULL)
353  break;
354 
355  memset(option_memory, 0, option_memory_size);
356 
357  commandLineData.Argc = Argc;
358  commandLineData.Argv = Argv;
359  commandLineData.OptArg = &optarg;
360  commandLineData.OptInd = &optind;
361  commandLineData.OptErr = &opterr;
362  commandLineData.OptOpt = &optopt;
363  commandLineData.OptionMemory = option_memory;
364  commandLineData.GetoptLongCallback = &getopt_long_callback;
365  commandLineData.InstallParameter = InstallParameter;
366 
367  error = opencbm_plugin_install_process_commandline(&commandLineData);
368 
369  if ( ! error && pluginData) {
370  pluginData->Name = cbmlibmisc_strdup(PluginName);
371  pluginData->FileName = cbmlibmisc_strdup(plugin_file_name);
372 
373  if (pluginData->Name == NULL || pluginData->FileName == NULL) {
374  error = TRUE;
375  }
376  }
377 
378  if (error) {
379  free(pluginData->FileName);
380  free(pluginData->Name);
381  free(pluginData);
382 
383  free(commandLineData.OptionMemory);
384 
385  break;
386  }
387 
388  pluginData->OptionMemory = commandLineData.OptionMemory;
389 
390  error = TRUE; // assume error unless proven otherwise
391 
392  {
393  int needed_files_length = opencbm_plugin_install_get_needed_files(&commandLineData, NULL);
394 
395  pluginData->NeededFiles = malloc(needed_files_length);
396 
397  if (NULL == pluginData->NeededFiles)
398  break;
399 
400  opencbm_plugin_install_get_needed_files(&commandLineData, pluginData->NeededFiles);
401 
402  error = FALSE;
403  }
404 
405  returnValue = pluginData;
406 
407  } while (0);
408 
409  if (library) {
410  FreeLibrary(library);
411  }
412 
413  free(plugin_file_name);
414 
415  if (error) {
416  free(option_memory);
417  }
418 
420 }
421 
446 BOOL
448  const char * const PluginName,
449  int Argc,
450  char * const Argv[])
451 {
452  cbm_install_parameter_plugin_t *pluginParameter;
453 
454  BOOL error = TRUE;
455 
456  FUNC_ENTER();
457 
458  pluginParameter = GetPluginData(PluginName, InstallParameter, Argc, Argv);
459 
460  error = pluginParameter == NULL ? TRUE : FALSE;
461 
462  if ( ! error ) {
463  PluginAddToList(InstallParameter, pluginParameter);
464  }
465 
466  FUNC_LEAVE_BOOL(error);
467 }
468 
485 BOOL
487 {
488  BOOL error = FALSE;
489  WIN32_FIND_DATA finddata;
490  HANDLE findhandle;
491 
492  const char *findfilename = NULL;
493 
494  FUNC_ENTER();
495 
496  do {
497  findfilename = malloc_plugin_file_name("*");
498 
499  if ( ! findfilename) {
500  error = TRUE;
501  break;
502  }
503 
504  findhandle = FindFirstFile(findfilename, &finddata);
505 
506  do {
507  if (findhandle != INVALID_HANDLE_VALUE) {
508  BOOL quit = FALSE;
509 
510  do {
511  if (finddata.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
512  /* extract the plugin name from the file name */
513 
514  cbm_install_parameter_plugin_t * pluginParameter = NULL;
515 
516  int len = strlen(finddata.cFileName) + 1;
517  char *pluginName = malloc(len);
518 
519  if (pluginName == NULL) {
520  error = TRUE;
521  break;
522  }
523 
524  strcpy(pluginName, finddata.cFileName + sizeof(PLUGIN_PREFIX) - 1);
525  pluginName[strlen(pluginName) - (sizeof(PLUGIN_SUFFIX) - 1)] = '\0';
526 
527  pluginParameter = GetPluginData(pluginName, InstallParameter, 1, NULL);
528 
529  if (pluginParameter) {
530  PluginAddToList(InstallParameter, pluginParameter);
531  }
532  else {
533  error = TRUE;
534  }
535 
536  free(pluginName);
537  }
538 
539  if (FindNextFile(findhandle, &finddata) == 0) {
540  quit = TRUE;
541  }
542  } while ( ! quit);
543 
544  FindClose(findhandle);
545 
546  }
547  } while (0);
548  } while (0);
549 
550  cbmlibmisc_strfree(findfilename);
551 
552  FUNC_LEAVE_BOOL(error);
553 }
554 
574 static BOOL CBMAPIDECL
575 get_all_installed_plugins_callback(cbm_install_parameter_t * InstallParameter, const char * PluginName)
576 {
577  FUNC_LEAVE_BOOL(ProcessPluginCommandlineAndAddIt(InstallParameter, PluginName, 1, NULL));
578 }
579 
595 BOOL
597 {
598  HMODULE openCbmDllHandle = NULL;
599  BOOL error = TRUE;
600  opencbm_configuration_handle configuration_handle = NULL;
601 
602  FUNC_ENTER();
603 
604  do {
605  opencbm_plugin_get_all_plugin_names_context_t opencbm_plugin_get_all_plugin_names_context;
606  opencbm_plugin_get_all_plugin_names_t * opencbm_plugin_get_all_plugin_names;
607 
608  openCbmDllHandle = LoadLocalOpenCBMDll();
609  if (openCbmDllHandle == NULL) {
610  DBG_PRINT((DBG_PREFIX "Could not open the OpenCBM DLL."));
611  fprintf(stderr, "Could not open the OpenCBM DLL.");
612  break;
613  }
614 
615  opencbm_plugin_get_all_plugin_names = (opencbm_plugin_get_all_plugin_names_t *)
616  GetProcAddress(openCbmDllHandle, "opencbm_plugin_get_all_plugin_names");
617 
618  if ( ! opencbm_plugin_get_all_plugin_names ) {
619  break;
620  }
621 
622  opencbm_plugin_get_all_plugin_names_context.Callback = get_all_installed_plugins_callback;
623  opencbm_plugin_get_all_plugin_names_context.InstallParameter = InstallParameter;
624 
625  if ( opencbm_plugin_get_all_plugin_names(&opencbm_plugin_get_all_plugin_names_context) ) {
626  break;
627  }
628 
629  error = FALSE;
630 
631  } while (0);
632 
633  if (openCbmDllHandle) {
634  FreeLibrary(openCbmDllHandle);
635  }
636 
637  opencbm_configuration_close(configuration_handle);
638 
639  FUNC_LEAVE_BOOL(error);
640 }
641 
663 BOOL PluginForAll(cbm_install_parameter_t * InstallParameter, PluginForAll_Callback_t * Callback, void * Context)
664 {
665  cbm_install_parameter_plugin_t * plugin = NULL;
666 
667  BOOL error = FALSE;
668 
669  FUNC_ENTER();
670 
671  for (plugin = InstallParameter->PluginList; (plugin != NULL) && ! error; plugin = plugin->Next) {
672  printf("Using plugin: '%s' with filename '%s'.\n", plugin->Name, plugin->FileName);
673  error = Callback(plugin, Context);
674  }
675 
676  FUNC_LEAVE_BOOL(error);
677 }
struct cbm_install_parameter_plugin_s cbm_install_parameter_plugin_t
Definition: instcbm.h:27
BOOL PluginForAll_Callback_t(cbm_install_parameter_plugin_t *PluginInstallParameter, void *Context)
Definition: instcbm.h:43
#define FUNC_LEAVE_INT(_xxx)
Definition: debug.h:358
Header for installation routines.
char * cbmlibmisc_strdup(const char *const OldString)
Duplicate a given string.
Definition: libstring.c:84
Define makros for debugging purposes.
struct CbmPluginInstallProcessCommandlineData_s CbmPluginInstallProcessCommandlineData_t
Definition: instcbm.h:25
#define CBMAPIDECL
Definition: opencbm.h:85
void PluginListFree(cbm_install_parameter_t *InstallParameter)
Free all the memory occupied by plugin management.
Definition: plugin.c:214
void cbmlibmisc_strfree(const char *String)
Free a string.
Definition: libstring.c:172
HMODULE LoadLocalOpenCBMDll(void)
@@@
Definition: instcbm.c:1479
Plugin DLL interface.
BOOL get_all_plugins(cbm_install_parameter_t *InstallParameter)
Get all the plugins.
Definition: plugin.c:486
Define the IOCTL codes for the opencbm driver.
#define FUNC_LEAVE()
Definition: debug.h:349
Definition: getopt.h:94
struct cbm_install_parameter_s cbm_install_parameter_t
Definition: instcbm.h:23
unsigned int CBMAPIDECL opencbm_plugin_install_get_needed_files(CbmPluginInstallProcessCommandlineData_t *Data, opencbm_plugin_install_neededfiles_t *Destination)
@@@
#define FUNC_LEAVE_PTR(_xxx, _TYPE)
Definition: debug.h:376
char * cbmlibmisc_stralloc(unsigned int Length)
allocate memory for a string of a given size
Definition: libstring.c:41
Shared library / DLL for accessing the driver Read configuration file.
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
BOOL get_all_installed_plugins(cbm_install_parameter_t *InstallParameter)
Get all the installed plugins.
Definition: plugin.c:596
#define FUNC_LEAVE_BOOL(_xxx)
Definition: debug.h:354
#define PLUGIN_SUFFIX
name suffix for the plugin executable
Definition: plugin.c:72
unsigned int CBMAPIDECL opencbm_plugin_install_process_commandline(CbmPluginInstallProcessCommandlineData_t *Data)
@@@
#define DBG_ERROR(_xxx)
Definition: debug.h:397
EXTERN BOOL CBMAPIDECL opencbm_plugin_get_all_plugin_names(opencbm_plugin_get_all_plugin_names_context_t *Context)
@@@
Defining OpenCBM version.
#define FUNC_ENTER()
Definition: debug.h:347
#define DBG_PREFIX
Definition: debug.h:320
#define FUNC_LEAVE_STRING(_xxx)
Definition: debug.h:368
Define makros and functions which account for differences between the different architectures.
Internal API for opencbm installation.
BOOL ProcessPluginCommandlineAndAddIt(cbm_install_parameter_t *InstallParameter, const char *const PluginName, int Argc, char *const Argv[])
Process the command-line parameters for a plugin and add that plugin to the plugin list...
Definition: plugin.c:447
BOOL PluginForAll(cbm_install_parameter_t *InstallParameter, PluginForAll_Callback_t *Callback, void *Context)
Execute a callback function for all plugins in the plugin list.
Definition: plugin.c:663
Some functions for string handling.
#define PLUGIN_PREFIX
name prefix for the plugin executable
Definition: plugin.c:61
#define DBG_PRINT(_xxx)
Definition: debug.h:403
int opencbm_configuration_close(opencbm_configuration_handle Handle)
Close the configuration file.