1 /* gpgcom.c - COM+ component to access GnuPG
2 * Copyright (C) 2001 g10 Code GmbH
4 * This file is part of GPGME.
6 * GPGME is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GPGME is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
38 static void register_server (void);
39 static void unregister_server (void);
40 static void enter_complus (void);
43 enum cmd_and_opt_values { aNull = 0,
61 static ARGPARSE_OPTS opts[] = {
63 { 301, NULL, 0, N_("@Options:\n ") },
65 { oVerbose, "verbose", 0, N_("verbose") },
66 { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
67 { oOptions, "options" , 2, N_("read options from file")},
68 { oDebug, "debug" ,4|16, N_("set debugging flags")},
69 { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
70 { oGPGBinary, "gpg-program", 2 , "" },
71 { oRegServer, "RegServer" , 0, "" },
72 { oUnregServer, "UnregServer" , 0, "" },
73 { oEmbedding, "Embedding" , 0, "" },
80 my_strusage( int level )
84 case 11: p = "gpgcom";
86 case 13: p = VERSION; break;
87 /*case 17: p = PRINTABLE_OS_NAME; break;*/
89 _("Please report bugs to <gpgme-bugs@gnupg.org>.\n");
93 _("Usage: gpgcom [options] (-h for help)");
96 _("Syntax: gpgcom [options]\n"
97 "GnuPG COM+ component\n");
107 main (int argc, char **argv )
112 FILE *configfp = NULL;
113 char *configname = NULL;
114 unsigned configlineno;
116 int default_config =1;
121 set_strusage( my_strusage );
122 /*log_set_name ("gpa"); not yet implemented in logging.c */
124 opt.homedir = getenv("GNUPGHOME");
125 if( !opt.homedir || !*opt.homedir ) {
126 #ifdef HAVE_DRIVE_LETTERS
127 opt.homedir = "c:/gnupg";
129 opt.homedir = "~/.gnupg";
133 /* check whether we have a config file on the commandline */
138 pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
139 while( arg_parse( &pargs, opts) ) {
140 if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
142 else if( pargs.r_opt == oOptions ) {
143 /* yes there is one, so we do not try the default one, but
144 * read the option file when it is encountered at the commandline
148 else if( pargs.r_opt == oNoOptions )
149 default_config = 0; /* --no-options */
150 else if( pargs.r_opt == oHomedir )
151 opt.homedir = pargs.r.ret_str;
155 configname = make_filename(opt.homedir, "gpgme.conf", NULL );
162 pargs.flags= 1 | (1<<5); /* do not remove the args, allow one dash */
166 configfp = fopen( configname, "r" );
168 if( default_config ) {
170 log_info(_("NOTE: no default option file `%s'\n"),
174 log_error(_("option file `%s': %s\n"),
175 configname, strerror(errno) );
178 free(configname); configname = NULL;
180 if( parse_debug && configname )
181 log_info(_("reading options from `%s'\n"), configname );
185 while( optfile_parse( configfp, configname, &configlineno,
187 switch( pargs.r_opt ) {
188 case oQuiet: opt.quiet = 1; break;
189 case oVerbose: opt.verbose++; break;
191 case oDebug: opt.debug |= pargs.r.ret_ulong; break;
192 case oDebugAll: opt.debug = ~0; break;
195 /* config files may not be nested (silently ignore them) */
198 configname = xstrdup(pargs.r.ret_str);
202 case oNoGreeting: nogreeting = 1; break;
203 case oNoVerbose: opt.verbose = 0; break;
204 case oNoOptions: break; /* no-options */
205 case oHomedir: opt.homedir = pargs.r.ret_str; break;
206 case oGPGBinary: break;
208 case oRegServer: action = 1; break;
209 case oUnregServer: action = 2; break;
210 case oEmbedding: action = 3; break;
212 default : pargs.err = configfp? 1:2; break;
218 free(configname); configname = NULL;
221 free( configname ); configname = NULL;
222 if( log_get_errorcount(0) )
228 fprintf(stderr, "%s %s; %s\n",
229 strusage(11), strusage(13), strusage(14) );
230 fprintf(stderr, "%s\n", strusage(15) );
232 #ifdef IS_DEVELOPMENT_VERSION
233 log_info("NOTE: this is a development version!\n");
238 else if (action == 2 )
239 unregister_server ();
240 else if (action == 3 )
243 fprintf (stderr, "This is a COM+ component with no user interface.\n"
244 "gpgme --help will give you a list of options\n" );
253 register_progid ( const char *name )
258 /* Create a ProgID entry to point to the ClassID */
259 sprintf (buf, "%.400s", name);
260 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
261 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
264 sprintf (buf, "g10 Code's GnuPG made easy COMponent" );
265 if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, 0)) {
266 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
269 if (RegCloseKey (hk)) {
270 fprintf (stderr,"RegCloseKey() failed\n");
273 sprintf (buf, "%.400s\\CLSID", name);
274 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
275 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
278 sprintf (buf, "%.100s", debugstr_guid (&CLSID_Gpgme) );
279 if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) {
280 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
283 if (RegCloseKey (hk)) {
284 fprintf (stderr,"RegCloseKey() failed\n");
292 register_typelib (void)
300 if ( !GetModuleFileNameA (0, name, sizeof (name)-10) ) {
301 fprintf (stderr,"GetModuleFileName() failed: %d\n",
302 (int)GetLastError());
305 n = mbstowcs (NULL, name, strlen(name)+1);
306 wname = xmalloc ((n+1)*sizeof *wname);
307 mbstowcs (wname, name, strlen (name)+1);
309 hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
311 fprintf (stderr, "CoInitializeEx() failed: hr=%lu\n", hr);
313 hr = LoadTypeLibEx (wname, REGKIND_REGISTER, &pTypeLib);
315 fprintf (stderr, "LoadTypeLibEx() failed: hr=%lx\n", hr);
317 ITypeLib_Release (pTypeLib);
323 unregister_typelib (void)
325 UnRegisterTypeLib (&TLBID_Gpgcom, 1, 0, LANG_NEUTRAL, SYS_WIN32);
337 /* Create a key for the CLSID */
338 sprintf (buf, "CLSID\\%.100s", debugstr_guid (&CLSID_Gpgme) );
339 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
340 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
343 /* Store our class name as default value */
344 strcpy (buf, "Gpgme");
345 if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) {
346 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
350 /* Set the application ID */
351 sprintf (buf, "%.100s", debugstr_guid (&APPID_Gpgcom) );
352 if (RegSetValueExA (hk, "AppID", 0, REG_SZ, buf, strlen (buf))) {
353 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
356 if (RegCloseKey (hk)) {
357 fprintf (stderr,"RegCloseKey() failed\n");
362 /* Create the LocalServer32 subkey under the CLSID key */
363 sprintf (buf, "CLSID\\%.100s\\LocalServer32",
364 debugstr_guid (&CLSID_Gpgme) );
365 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
366 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
369 /* retrieve the module name and add it under the key */
370 if ( !GetModuleFileNameA (0, buf, sizeof (buf)-10) ) {
371 fprintf (stderr,"GetModuleFileName() failed\n");
374 if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) {
375 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
378 if (RegCloseKey (hk)) {
379 fprintf (stderr,"RegCloseKey() failed\n");
384 /* Create the ProgID subkey under the CLSID key */
385 sprintf (buf, "CLSID\\%.100s\\ProgID",
386 debugstr_guid (&CLSID_Gpgme) );
387 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
388 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
391 if (RegSetValueExA (hk, 0, 0, REG_SZ, "Gpgcom.Gpgme.1", 0)) {
392 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
395 if (RegCloseKey (hk)) {
396 fprintf (stderr,"RegCloseKey() failed\n");
400 /* Create the VersionIndependentProgID subkey under the CLSID key */
401 sprintf (buf, "CLSID\\%.100s\\VersionIndependentProgID",
402 debugstr_guid (&CLSID_Gpgme) );
403 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
404 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
407 if (RegSetValueExA (hk, 0, 0, REG_SZ, "Gpgcom.Gpgme", 0)) {
408 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
411 if (RegCloseKey (hk)) {
412 fprintf (stderr,"RegCloseKey() failed\n");
418 /* Create a key to store AppID info */
419 sprintf (buf, "AppID\\%.100s", debugstr_guid (&APPID_Gpgcom) );
420 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
421 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
424 /* Store the name as default value */
425 strcpy (buf, "Gpgcom");
426 if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) {
427 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
430 if (RegCloseKey (hk)) {
431 fprintf (stderr,"RegCloseKey() failed\n");
436 register_progid ("Gpgcom.Gpgme");
437 register_progid ("Gpgcom.Gpgme.1");
439 /* Create a convenience cross reference to the AppID */
440 sprintf (buf, "AppID\\gpgcom.exe");
441 if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) {
442 fprintf (stderr,"RegCreateKey(`%s') failed\n", buf);
445 sprintf (buf, "%.100s", debugstr_guid (&APPID_Gpgcom) );
446 if (RegSetValueExA (hk, "AppID", 0, REG_SZ, buf, strlen (buf))) {
447 fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf);
450 if (RegCloseKey (hk)) {
451 fprintf (stderr,"RegCloseKey() failed\n");
456 fprintf (stderr,"*** Component registered\n");
464 unregister_typelib ();
465 sprintf (buf, "CLSID\\%.100s\\LocalServer32",
466 debugstr_guid (&CLSID_Gpgme) );
467 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
468 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
470 sprintf (buf, "CLSID\\%.100s\\ProgID", debugstr_guid (&CLSID_Gpgme) );
471 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
472 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
474 sprintf (buf, "CLSID\\%.100s", debugstr_guid (&CLSID_Gpgme) );
475 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
476 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
478 sprintf (buf, "Gpgcom.Gpgme.1\\CLSID");
479 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
480 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
481 sprintf (buf, "Gpgcom.Gpgme.1");
482 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
483 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
485 sprintf (buf, "Gpgcom.Gpgme\\CLSID");
486 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
487 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
488 sprintf (buf, "Gpgcom.Gpgme");
489 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
490 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
493 sprintf (buf, "AppID\\%.100s", debugstr_guid (&APPID_Gpgcom) );
494 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
495 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
497 sprintf (buf, "AppID\\gpgcom.exe" );
498 if (RegDeleteKey (HKEY_CLASSES_ROOT, buf))
499 fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf);
501 fprintf (stderr,"*** component unregistered\n");
510 IClassFactory *factory;
514 fprintf (stderr,"*** enter enter_complus()\n");
515 CoInitializeEx (NULL, COINIT_MULTITHREADED);
516 running = CreateEvent (NULL, FALSE, FALSE, NULL );
517 fprintf (stderr,"*** CoInitialize() done; event=%lx\n", (unsigned long)running );
519 igpgme_register_exit_event (running);
520 factory = igpgme_factory_new ( &clsid );
521 fprintf (stderr,"*** igpgme_factory_new() done; got=%p\n", factory );
522 hr = CoRegisterClassObject (&clsid, (IUnknown*)factory,
524 REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, ® );
526 fprintf (stderr, "CoRegisterClassObject() failed: hr=%lx\n", hr);
529 hr = CoResumeClassObjects ();
531 fprintf (stderr, "CoRegisterClassObject() failed: hr=%lx\n", hr);
532 fprintf (stderr,"*** class object registered; waiting\n" );
534 WaitForSingleObject ( running, INFINITE );
535 fprintf (stderr,"*** shutting down\n" );
536 igpgme_register_exit_event (NULL);
537 CloseHandle (running);
538 CoRevokeClassObject ( reg );
539 fprintf (stderr,"*** class object revoked\n" );
540 igpgme_factory_release (factory);
541 fprintf (stderr,"*** factory released\n" );
543 fprintf (stderr,"*** leave enter_complus()\n" );