Preparing a release
[gpgol.git] / src / engine.c
1 /* engine.c - Crypto engine dispatcher
2  *      Copyright (C) 2007, 2008 g10 Code GmbH
3  *
4  * This file is part of GpgOL.
5  *
6  * GpgOL is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 
9  * of the License, or (at your option) any later version.
10  *  
11  * GpgOL 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <errno.h>
27 #include <assert.h>
28 #define WIN32_LEAN_AND_MEAN 
29 #include <windows.h>
30
31 #include "common.h"
32 #include "engine.h"
33 #include "engine-gpgme.h"
34 #include "engine-assuan.h"
35
36
37 #define FILTER_BUFFER_SIZE 4096
38
39
40 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
41                                        SRCNAME, __func__, __LINE__); \
42                         } while (0)
43
44 #define debug_filter        (opt.enable_debug & DBG_FILTER)
45 #define debug_filter_extra  (opt.enable_debug & DBG_FILTER_EXTRA)
46
47 /* This variable indicates whether the assuan engine is used.  */
48 static int use_assuan;
49
50
51 /* Definition of the key object.  */
52 struct engine_keyinfo_s
53 {
54   struct {
55     gpgme_key_t key;
56   } gpgme;
57
58 };
59
60
61 /* Definition of the filter object.  This object shall only be
62    accessed by one thread. */
63 struct engine_filter_s
64 {
65   int use_assuan;          /* The same as the global USE_ASSUAN.  */
66
67   struct {
68     CRITICAL_SECTION lock; /* The lock for the this object. */
69     HANDLE condvar;        /* Manual reset event signaled if LENGTH > 0.  */
70     int nonblock;          /* Put gpgme data cb in non blocking mode.  */
71     size_t length;         /* Number of bytes in BUFFER waiting to be
72                               send down the pipe.  */
73     char buffer[FILTER_BUFFER_SIZE];
74     int got_eof;         /* End of file has been indicated.  */
75     /* These objects are only in this structure because we
76        use this structure's lock to protect them.  */
77     int ready;           /* Set to true if the gpgme process has finished.  */
78     HANDLE ready_event;  /* And the corresponding event.  */
79     gpg_error_t status;  /* Status of the gpgme process.  */
80   } in;
81
82   struct {
83     CRITICAL_SECTION lock; /* The lock for the this object. */
84     HANDLE condvar;        /* Manual reset event signaled if LENGTH == 0.  */
85     int nonblock;          /* Put gpgme data cb in non blocking mode.  */
86     size_t length;         /* Number of bytes in BUFFER waiting to be
87                               send back to the caller.  */
88     char buffer[FILTER_BUFFER_SIZE];
89   } out;
90
91   /* Flag to push an extra LF out.  */
92   int add_extra_lf;
93
94   /* The data sink as set by engine_create_filter.  */
95   int (*outfnc) (void *, const void *, size_t);
96   void *outfncdata;
97
98   /* Objects to be released by engine_wait/cancel.  */
99   struct gpgme_data_cbs cb_inbound;  /* Callback structure for gpgme.  */
100   struct gpgme_data_cbs cb_outbound; /* Ditto.  */
101   gpgme_data_t indata;               /* Input data.  */
102   gpgme_data_t outdata;              /* Output data.  */
103   void *cancel_data;                 /* Used by engine_cancel.  */
104
105   /* A pointer used convey information from engine_encrypt_prepare to
106      engine_encrypt_start.  */
107   struct engine_assuan_encstate_s *encstate;
108
109   /* Counter used to optimize voluntary thread switching. */
110   ULONG switch_counter;
111 };
112
113
114 static void
115 take_in_lock (engine_filter_t filter, const char *func)
116 {
117   EnterCriticalSection (&filter->in.lock);
118   if (debug_filter_extra)
119     log_debug ("%s:%s: in.lock taken\n", SRCNAME, func);
120 }
121
122 static void
123 release_in_lock (engine_filter_t filter, const char *func)
124 {
125   LeaveCriticalSection (&filter->in.lock);
126   if (debug_filter_extra)
127     log_debug ("%s:%s: in.lock released\n", SRCNAME, func);
128 }
129
130 static void
131 take_out_lock (engine_filter_t filter, const char *func)
132 {
133   EnterCriticalSection (&filter->out.lock);
134   if (debug_filter_extra)
135     log_debug ("%s:%s: out.lock taken\n", SRCNAME, func);
136 }
137
138 static void
139 release_out_lock (engine_filter_t filter, const char *func)
140 {
141   LeaveCriticalSection (&filter->out.lock);
142   if (debug_filter_extra)
143     log_debug ("%s:%s: out.lock released\n", SRCNAME, func);
144 }
145
146
147
148
149 \f
150 /* Create a new filter object. */
151 static engine_filter_t 
152 create_filter (void)
153 {
154   engine_filter_t filter;
155
156   filter = xcalloc (1, sizeof *filter);
157
158   InitializeCriticalSection (&filter->in.lock);
159   filter->in.condvar = CreateEvent (NULL, TRUE, 0, NULL);
160   if (!filter->in.condvar)
161     log_error_w32 (-1, "%s:%s: create in.condvar failed", SRCNAME, __func__);
162
163   InitializeCriticalSection (&filter->out.lock);
164   filter->out.condvar = CreateEvent (NULL, TRUE, 0, NULL);
165   if (!filter->out.condvar)
166     log_error_w32 (-1, "%s:%s: create out.condvar failed", SRCNAME, __func__);
167
168   /* Create an automatic event (it only used one time so the type is
169      actually not important).  */
170   filter->in.ready_event = CreateEvent (NULL, 0, 0, NULL);
171   if (!filter->in.ready_event)
172     log_error_w32 (-1, "%s:%s: CreateEvent failed", SRCNAME, __func__);
173
174   /* If we are using the assuan engine we need to make the gpgme read
175      callback non blocking.  */
176   if (use_assuan)
177     {
178       filter->use_assuan = 1;
179       filter->in.nonblock = 1;
180     }
181
182   return filter;
183 }
184
185
186 static void
187 release_filter (engine_filter_t filter)
188 {
189   if (filter)
190     {
191       if (filter->in.condvar)
192         CloseHandle (filter->in.condvar);
193       if (filter->out.condvar)
194         CloseHandle (filter->out.condvar);
195       if (filter->in.ready_event)
196         CloseHandle (filter->in.ready_event);
197       gpgme_data_release (filter->indata);
198       gpgme_data_release (filter->outdata);
199       xfree (filter);
200     }
201 }
202
203
204 /* This is a wraper around SwitchToThread, a syscall we unfortunately
205    need due to the lack of an sophisticated event system.  The wrapper
206    calls SwitchToThread but after a couple of immediate folliwing
207    switches, it introduces a short delays.  */
208 static void
209 switch_threads (engine_filter_t filter)
210 {
211   ULONG count;
212
213   count = InterlockedExchangeAdd (&filter->switch_counter, 1);
214   if (count > 5)
215     {
216       InterlockedExchange (&filter->switch_counter, 5);
217       SleepEx (50, TRUE); 
218     }
219   else if (!SwitchToThread ())
220     {
221       /* No runable other thread: Fall asleep. */
222       SleepEx (5, TRUE);
223     }
224 }
225
226 /* Call this fucntion if some action has been done.  */
227 static void
228 clear_switch_threads (engine_filter_t filter)
229 {
230   InterlockedExchange (&filter->switch_counter, 0);
231 }
232
233
234 /* This read callback is used by GPGME to read data from a filter
235    object.  The function should return the number of bytes read, 0 on
236    EOF, and -1 on error.  If an error occurs, ERRNO should be set to
237    describe the type of the error.  */
238 static ssize_t
239 filter_gpgme_read_cb (void *handle, void *buffer, size_t size)
240 {
241   engine_filter_t filter = handle;
242   int nbytes;
243
244   if (!filter || !buffer || !size)
245     {
246       errno = EINVAL;
247       return (ssize_t)(-1);
248     }
249
250   if (debug_filter)
251     log_debug ("%s:%s: enter\n",  SRCNAME, __func__);
252   take_in_lock (filter, __func__);
253   while (!filter->in.length)
254     {
255       if (filter->in.got_eof || filter->in.ready)
256         {
257           release_in_lock (filter, __func__);
258          if (debug_filter)
259             log_debug ("%s:%s: returning EOF\n", SRCNAME, __func__);
260           return 0; /* Return EOF. */
261         }
262       release_in_lock (filter, __func__);
263       if (filter->in.nonblock)
264         {
265           errno = EAGAIN;
266           if (debug_filter_extra)
267             log_debug ("%s:%s: leave; result=EAGAIN\n", SRCNAME, __func__);
268           switch_threads (filter);
269           return -1;
270         }
271       else
272         clear_switch_threads (filter);
273       if (debug_filter)
274         log_debug ("%s:%s: waiting for in.condvar\n", SRCNAME, __func__);
275       WaitForSingleObject (filter->in.condvar, 500);
276       take_in_lock (filter, __func__);
277       if (debug_filter)
278         log_debug ("%s:%s: continuing\n", SRCNAME, __func__);
279     }
280      
281   if (debug_filter)
282     log_debug ("%s:%s: requested read size=%d (filter.in.length=%d)\n",
283                SRCNAME, __func__, (int)size, (int)filter->in.length);
284   nbytes = size < filter->in.length ? size : filter->in.length;
285   memcpy (buffer, filter->in.buffer, nbytes);
286   if (filter->in.length > nbytes)
287     memmove (filter->in.buffer, filter->in.buffer + nbytes, 
288              filter->in.length - nbytes);
289   filter->in.length -= nbytes;
290   release_in_lock (filter, __func__);
291
292   if (debug_filter)
293     log_debug ("%s:%s: leave; result=%d\n",
294                SRCNAME, __func__, (int)nbytes);
295   
296   return nbytes;
297 }
298
299
300 /* This write callback is used by GPGME to write data to the filter
301    object.  The function should return the number of bytes written,
302    and -1 on error.  If an error occurs, ERRNO should be set to
303    describe the type of the error.  */
304 static ssize_t
305 filter_gpgme_write_cb (void *handle, const void *buffer, size_t size)
306 {
307   engine_filter_t filter = handle;
308   int nbytes;
309
310   if (!filter || !buffer || !size)
311     {
312       errno = EINVAL;
313       return (ssize_t)(-1);
314     }
315
316   if (debug_filter)
317     log_debug ("%s:%s: enter\n",  SRCNAME, __func__);
318   take_out_lock (filter, __func__);
319   while (filter->out.length)
320     {
321       release_out_lock (filter, __func__);
322       if (filter->out.nonblock)
323         {
324           errno = EAGAIN;
325           if (debug_filter_extra)
326             log_debug ("%s:%s: leave; result=EAGAIN\n", SRCNAME, __func__);
327           return -1;
328         }
329       if (debug_filter)
330         log_debug ("%s:%s: waiting for out.condvar\n", SRCNAME, __func__);
331       WaitForSingleObject (filter->out.condvar, 500);
332       take_out_lock (filter, __func__);
333       if (debug_filter)
334         log_debug ("%s:%s: continuing\n", SRCNAME, __func__);
335     }
336
337   if (debug_filter)
338     log_debug ("%s:%s: requested write size=%d\n",
339                SRCNAME, __func__, (int)size);
340   nbytes = size < FILTER_BUFFER_SIZE ? size : FILTER_BUFFER_SIZE;
341   memcpy (filter->out.buffer, buffer, nbytes);
342   filter->out.length = nbytes;
343   release_out_lock (filter, __func__);
344
345   if (debug_filter)
346     log_debug ("%s:%s: leave; result=%d\n", SRCNAME, __func__, (int)nbytes);
347   return nbytes;
348 }
349
350
351 /* Store a cancel parameter into FILTER.  Only use by the engine backends. */
352 void
353 engine_private_set_cancel (engine_filter_t filter, void *cancel_data)
354 {
355   filter->cancel_data = cancel_data;
356 }
357
358
359 /* This function is called by the gpgme backend to notify a filter
360    object about the final status of an operation.  It may only be
361    called by the engine-gpgme.c module. */
362 void
363 engine_private_finished (engine_filter_t filter, gpg_error_t status)
364 {
365   if (!filter)
366     {
367       log_debug ("%s:%s: called without argument\n", SRCNAME, __func__);
368       return;
369     }
370   if (debug_filter)
371     log_debug ("%s:%s: filter %p: process terminated: %s <%s>\n", 
372                SRCNAME, __func__, filter, 
373                gpg_strerror (status), gpg_strsource (status));
374   
375   take_in_lock (filter, __func__);
376   filter->in.ready = 1;
377   filter->in.status = status;
378   filter->cancel_data = NULL;
379   if (!SetEvent (filter->in.ready_event))
380     log_error_w32 (-1, "%s:%s: SetEvent failed", SRCNAME, __func__);
381   release_in_lock (filter, __func__);
382   if (debug_filter)
383     log_debug ("%s:%s: leaving\n", SRCNAME, __func__);
384 }
385
386
387
388
389 \f
390 /* Initialize the engine dispatcher.  */
391 int
392 engine_init (void)
393 {
394   gpg_error_t err;
395
396   err = op_gpgme_basic_init ();
397   if (err)
398     return err;
399
400   err = op_assuan_init ();
401   if (err)
402     {
403       use_assuan = 0;
404       MessageBox (NULL,
405                   _("The user interface server is not available or does "
406                     "not work.  Using an internal user interface.\n\n"
407                     "This is limited to the PGP/MIME protocol and "
408                     "thus S/MIME protected message are not readable."),
409                   _("GpgOL"), MB_ICONWARNING|MB_OK);
410       err = op_gpgme_init ();
411     }
412   else
413     use_assuan = 1;
414
415   return err;
416 }
417
418
419 /* Shutdown the engine dispatcher.  */
420 void
421 engine_deinit (void)
422 {
423   op_assuan_deinit ();
424   op_gpgme_deinit ();
425 }
426
427
428 \f
429 /* Filter the INDATA of length INDATA and write the output using
430    OUTFNC.  OUTFNCDATA is passed as first argument to OUTFNC, followed
431    by the data to be written and its length.  FILTER is an object
432    returned for example by engine_encrypt_start.  The function returns
433    0 on success or an error code on error.
434
435    Passing INDATA as NULL and INDATALEN as 0, the filter will be
436    flushed, that is all remaining stuff will be written to OUTFNC.
437    This indicates EOF and the filter won't accept anymore input.  */
438 int
439 engine_filter (engine_filter_t filter, const void *indata, size_t indatalen)
440 {
441   gpg_error_t err;
442   int nbytes;
443
444   if (debug_filter)
445     log_debug ("%s:%s: enter; filter=%p\n", SRCNAME, __func__, filter); 
446   /* Our implementation is for now straightforward without any
447      additional buffer filling etc.  */
448   if (!filter || !filter->outfnc)
449     return gpg_error (GPG_ERR_INV_VALUE);
450   if (filter->in.length > FILTER_BUFFER_SIZE
451       || filter->out.length > FILTER_BUFFER_SIZE)
452     return gpg_error (GPG_ERR_BUG);
453   if (filter->in.got_eof)
454     return gpg_error (GPG_ERR_CONFLICT); /* EOF has already been indicated.  */
455
456   if (debug_filter)
457     log_debug ("%s:%s: indata=%p indatalen=%d outfnc=%p\n",
458                SRCNAME, __func__, indata, (int)indatalen, filter->outfnc); 
459   for (;;)
460     {
461       int any;
462
463       /* If there is something to write out, do this now to make space
464          for more data.  */
465       any = 0;
466       take_out_lock (filter, __func__);
467       while (filter->out.length)
468         {
469           if (debug_filter)
470             log_debug ("%s:%s: pushing %d bytes to the outfnc\n",
471                        SRCNAME, __func__, filter->out.length); 
472           nbytes = filter->outfnc (filter->outfncdata, 
473                                    filter->out.buffer, filter->out.length);
474           if (nbytes == -1)
475             {
476               if (debug_filter)
477                 log_debug ("%s:%s: error writing data\n", SRCNAME, __func__);
478               release_out_lock (filter, __func__);
479               return gpg_error (GPG_ERR_EIO);
480             }
481           assert (nbytes <= filter->out.length && nbytes >= 0);
482           if (nbytes < filter->out.length)
483             memmove (filter->out.buffer, filter->out.buffer + nbytes,
484                      filter->out.length - nbytes); 
485           filter->out.length -= nbytes;
486           any = 1;
487         }
488       if (!PulseEvent (filter->out.condvar))
489         log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__);
490       release_out_lock (filter, __func__);
491
492       if (any)
493         clear_switch_threads (filter);
494       else
495         switch_threads (filter);
496
497       any = 0;
498       take_in_lock (filter, __func__);
499       if (!indata && !indatalen)
500         {
501           filter->in.got_eof = 1;
502           /* Flush requested.  Tell the output function to also flush.  */
503           nbytes = filter->outfnc (filter->outfncdata, NULL, 0);
504           if (nbytes == -1)
505             {
506               log_debug ("%s:%s: error flushing data\n", SRCNAME, __func__);
507               err = gpg_error (GPG_ERR_EIO);
508             }
509           else
510             err = 0;
511           release_in_lock (filter, __func__);
512           return err; 
513         }
514
515       /* Fill the input buffer, relinquish control to the callback
516          processor and loop until all input data has been
517          processed.  */
518       if (!filter->in.length && indatalen)
519         {
520           filter->in.length = (indatalen > FILTER_BUFFER_SIZE
521                                ? FILTER_BUFFER_SIZE : indatalen);
522           memcpy (filter->in.buffer, indata, filter->in.length);
523           indata    += filter->in.length;
524           indatalen -= filter->in.length;
525           any = 1;
526         }
527       /* Terminate the loop if the filter queue is empty OR the filter
528          is ready and there is nothing left for output.  */
529       if (!filter->in.length || (filter->in.ready && !filter->out.length))
530         {
531           release_in_lock (filter, __func__);
532           err = filter->in.status;
533           break;  /* the loop.  */
534         }
535       if (!PulseEvent (filter->in.condvar))
536         log_error_w32 (-1, "%s:%s: PulseEvent(in) failed", SRCNAME, __func__);
537       release_in_lock (filter, __func__);
538       if (any)
539         clear_switch_threads (filter);
540       else
541         switch_threads (filter);
542     }
543
544   if (debug_filter)
545     log_debug ("%s:%s: leave; err=%d\n", SRCNAME, __func__, err); 
546   return err;
547 }
548
549
550 /* Dummy data sink used if caller does not need an output
551    function.  */
552 static int
553 dummy_outfnc (void *opaque, const void *data, size_t datalen)
554 {
555   (void)opaque;
556   (void)data;
557   return (int)datalen;
558 }
559
560
561 /* Create a new filter object which uses OUTFNC as its data sink.  If
562    OUTFNC is called with NULL/0 for the data to be written, the
563    function should do a flush.  OUTFNC is expected to return the
564    number of bytes actually written or -1 on error.  It may return 0
565    to indicate that no data has been written and the caller shall try
566    again.  OUTFNC and OUTFNCDATA are internally used by the engine
567    even after the call to this function.  There lifetime only ends
568    after an engine_wait or engine_cancel. */
569 int
570 engine_create_filter (engine_filter_t *r_filter,
571                       int (*outfnc) (void *, const void *, size_t),
572                       void *outfncdata)
573 {
574   gpg_error_t err;
575   engine_filter_t filter;
576
577   filter = create_filter ();
578   filter->cb_inbound.read = filter_gpgme_read_cb;
579   filter->cb_outbound.write = filter_gpgme_write_cb;
580   filter->outfnc = outfnc? outfnc : dummy_outfnc;
581   filter->outfncdata = outfncdata;
582
583   err = gpgme_data_new_from_cbs (&filter->indata, 
584                                  &filter->cb_inbound, filter);
585   if (err)
586     goto failure;
587
588   err = gpgme_data_new_from_cbs (&filter->outdata,
589                                  &filter->cb_outbound, filter);
590   if (err)
591     goto failure;
592
593   *r_filter = filter;
594   return 0;
595
596  failure:
597   release_filter (filter);
598   return err;
599 }
600
601
602 /* Set the FILTER in a mode which pushes an extra lineffed out.  */
603 void
604 engine_request_exra_lf (engine_filter_t filter)
605 {
606   filter->add_extra_lf = 1;
607 }
608
609
610 /* Wait for FILTER to finish.  Returns 0 on success.  FILTER is not
611    valid after the function has returned success.  */
612 int
613 engine_wait (engine_filter_t filter)
614 {
615   gpg_error_t err;
616   int more;
617   int nbytes; 
618
619   if (!filter || !filter->outfnc)
620     return gpg_error (GPG_ERR_INV_VALUE);
621
622   /* If we are here, engine_filter is not anymore called but there is
623      likely stuff in the output buffer which needs to be written
624      out.  */
625   /* Argh, Busy waiting.  As soon as we change fromCritical Sections
626      to a kernel based objects we should use WaitOnMultipleObjects to
627      wait for the out.lock as well as for the ready_event.  */
628   do 
629     {
630       more = 0;
631       take_out_lock (filter, __func__);
632       if (filter->out.length)
633         {
634           nbytes = filter->outfnc (filter->outfncdata, 
635                                    filter->out.buffer, filter->out.length);
636           if (nbytes < 0)
637             {
638               log_error ("%s:%s: error writing data\n", SRCNAME, __func__);
639               release_out_lock (filter, __func__);
640               return gpg_error (GPG_ERR_EIO);
641             }
642          
643           assert (nbytes <= filter->out.length && nbytes >= 0);
644           if (nbytes < filter->out.length)
645             memmove (filter->out.buffer, filter->out.buffer + nbytes,
646                      filter->out.length - nbytes); 
647           filter->out.length -= nbytes;
648           if (filter->out.length)
649             {
650               if (debug_filter_extra)
651                 log_debug ("%s:%s: still %d pending bytes for outfnc\n",
652                            SRCNAME, __func__, filter->out.length);
653               more = 1;
654             }
655         }
656       if (!PulseEvent (filter->out.condvar))
657         log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__);
658       release_out_lock (filter, __func__);
659       take_in_lock (filter, __func__);
660       if (!filter->in.ready)
661         more = 1;
662       release_in_lock (filter, __func__);
663       if (more)
664         SwitchToThread ();
665     }
666   while (more);
667
668   /* If requested write an extra LF, so that the MIME parser sees a
669      complete line.  */
670   if (filter->add_extra_lf)
671     {
672       int extra_written = 0;
673       do 
674         {
675           more = 0;
676           take_out_lock (filter, __func__);
677           if (!extra_written)
678             {
679               nbytes = filter->outfnc (filter->outfncdata, "\n", 1);
680               if (nbytes < 0)
681                 {
682                   log_error ("%s:%s: error writing extra lf\n", 
683                              SRCNAME, __func__);
684                   release_out_lock (filter, __func__);
685                   return gpg_error (GPG_ERR_EIO);
686                 }
687               if (!nbytes)
688                 {
689                   if (debug_filter_extra)
690                     log_debug ("%s:%s: extra lf still pending for outfnc\n",
691                                SRCNAME, __func__);
692                   more = 1;
693                 }
694               else
695                 extra_written = 1;
696             }
697           if (!PulseEvent (filter->out.condvar))
698             log_error_w32 (-1, "%s:%s: PulseEvent(out) failed",
699                            SRCNAME, __func__);
700           release_out_lock (filter, __func__);
701           take_in_lock (filter, __func__);
702           if (!filter->in.ready)
703             more = 1;
704           release_in_lock (filter, __func__);
705           if (more)
706             SwitchToThread ();
707         }
708       while (more);
709     }
710
711   if (WaitForSingleObject (filter->in.ready_event, INFINITE) != WAIT_OBJECT_0)
712     {
713       log_error_w32 (-1, "%s:%s: WFSO failed", SRCNAME, __func__);
714       return gpg_error (GPG_ERR_GENERAL);
715     }
716   err = filter->in.status;
717   log_debug ("%s:%s: filter %p ready: %s", SRCNAME, __func__, 
718              filter, gpg_strerror (err));
719
720   if (!err)
721     release_filter (filter);
722   return err;
723 }
724
725
726 /* Cancel FILTER. */
727 void
728 engine_cancel (engine_filter_t filter)
729 {
730   void *cancel_data;
731
732   if (!filter)
733     return;
734   
735   /* First we need to cancel a possible prepared encrypt operation. */
736   engine_encrypt_start (filter, 1);
737
738   take_in_lock (filter, __func__);
739   cancel_data = filter->cancel_data;
740   filter->cancel_data = NULL;
741   filter->in.ready = 1;
742   release_in_lock (filter, __func__);
743   if (cancel_data)
744     {
745       log_debug ("%s:%s: filter %p: sending cancel command to backend",
746                  SRCNAME, __func__, filter);
747       if (filter->use_assuan)
748         engine_assuan_cancel (cancel_data);
749       else
750         engine_gpgme_cancel (cancel_data);
751       if (WaitForSingleObject (filter->in.ready_event, INFINITE)
752           != WAIT_OBJECT_0)
753         log_error_w32 (-1, "%s:%s: WFSO failed", SRCNAME, __func__);
754       else
755         log_debug ("%s:%s: filter %p: backend has been canceled", 
756                    SRCNAME, __func__,  filter);
757     }
758   log_debug ("%s:%s: filter %p: canceled", SRCNAME, __func__, filter);
759   release_filter (filter);
760 }
761
762
763
764 /* Start an encryption operation to all RECIPEINTS using PROTOCOL
765    RECIPIENTS is a NULL terminated array of rfc2822 addresses.  FILTER
766    is an object created by engine_create_filter.  The caller needs to
767    call engine_wait to finish the operation.  A filter object may not
768    be reused after having been used through this function.  However,
769    the lifetime of the filter object lasts until the final engine_wait
770    or engine_cancel.  On return the protocol to be used is stored at
771    R_PROTOCOL.  This is a two part fucntion.  engine_encrypt_prepare
772    needs to be called first followed by engine_encrypt_start.  The
773    latter command has just one argument CANCEL which can be set to
774    true to cancel the prepared command.  */
775 int
776 engine_encrypt_prepare (engine_filter_t filter, HWND hwnd,
777                         protocol_t req_protocol, char **recipients,
778                         protocol_t *r_protocol)
779 {
780   gpg_error_t err;
781   protocol_t used_protocol;
782
783   *r_protocol = req_protocol;
784   if (filter->use_assuan)
785     {
786       err = op_assuan_encrypt (req_protocol, filter->indata, filter->outdata,
787                                filter, hwnd, recipients, &used_protocol,
788                                &filter->encstate);
789       if (!err)
790         *r_protocol = used_protocol;
791     }
792   else
793     err = op_gpgme_encrypt (req_protocol, filter->indata, filter->outdata,
794                             filter, hwnd, recipients);
795       
796   return err;
797 }
798
799 /* See engine_encrypt_prepare.  */
800 int
801 engine_encrypt_start (engine_filter_t filter, int cancel)
802 {
803   gpg_error_t err;
804
805   if (filter->use_assuan)
806     {
807       err = op_assuan_encrypt_bottom (filter->encstate, cancel);
808       filter->encstate = NULL;
809     }
810   else
811     err = 0; /* This is a dummy here.  */
812       
813   return err;
814 }
815
816
817 /* Start an detached signing operation.  FILTER is an object created
818    by engine_create_filter.  The caller needs to call engine_wait to
819    finish the operation.  A filter object may not be reused after
820    having been used through this function.  However, the lifetime of
821    the filter object lasts until the final engine_wait or
822    engine_cancel.  SENDER is the sender's mailbox or NULL.  On return
823    the protocol to be used is stored at R_PROTOCOL. */
824 int
825 engine_sign_start (engine_filter_t filter, HWND hwnd, protocol_t protocol,
826                    const char *sender, protocol_t *r_protocol)
827 {
828   gpg_error_t err;
829   protocol_t used_protocol;
830
831   if (filter->use_assuan)
832     {
833       err = op_assuan_sign (protocol, filter->indata, filter->outdata,
834                             filter, hwnd, sender, &used_protocol);
835       if (!err)
836         *r_protocol = used_protocol;
837     }
838   else
839     {
840       err = op_gpgme_sign (protocol, filter->indata, filter->outdata,
841                            filter, hwnd);
842       if (!err)
843         *r_protocol = (protocol == GPGME_PROTOCOL_UNKNOWN?
844                        GPGME_PROTOCOL_OpenPGP : protocol);
845     }
846   return err;
847 }
848
849
850 /* Start an decrypt operation.  FILTER is an object created by
851    engine_create_filter.  The caller needs to call engine_wait to
852    finish the operation.  A filter object may not be reused after
853    having been used through this function.  However, the lifetime of
854    the filter object lasts until the final engine_wait or
855    engine_cancel.  */
856 int
857 engine_decrypt_start (engine_filter_t filter, HWND hwnd, protocol_t protocol,
858                       int with_verify)
859 {
860   gpg_error_t err;
861
862   if (filter->use_assuan)
863     err = op_assuan_decrypt (protocol, filter->indata, filter->outdata,
864                             filter, hwnd, with_verify);
865   else
866     err = op_gpgme_decrypt (protocol, filter->indata, filter->outdata,
867                             filter, hwnd, with_verify);
868   return err;
869 }
870
871
872 /* Start a verify operation.  FILTER is an object created by
873    engine_create_filter; an output function is not required. SIGNATURE
874    is the detached signature or NULL if FILTER delivers an opaque
875    signature.  The caller needs to call engine_wait to finish the
876    operation.  A filter object may not be reused after having been
877    used through this function.  However, the lifetime of the filter
878    object lasts until the final engine_wait or engine_cancel.  */
879 int
880 engine_verify_start (engine_filter_t filter, HWND hwnd, const char *signature,
881                      size_t sig_len, protocol_t protocol)
882 {
883   gpg_error_t err;
884
885   if (!signature && !filter->use_assuan)
886     {
887       log_error ("%s:%s: opaque signatures are not supported "
888                  "by the internal backend\n",
889                  SRCNAME, __func__);
890       return gpg_error (GPG_ERR_NOT_SUPPORTED);
891     }
892
893   if (filter->use_assuan && !signature)
894     err = op_assuan_verify (protocol, filter->indata, NULL, 0,
895                             filter->outdata, filter, hwnd);
896   else if (filter->use_assuan)
897     err = op_assuan_verify (protocol, filter->indata, signature, sig_len,
898                             NULL, filter, hwnd);
899   else
900     err = op_gpgme_verify (protocol, filter->indata, signature, sig_len,
901                            filter, hwnd);
902   return err;
903 }
904
905
906 /* Fire up the key manager.  Returns 0 on success.  */
907 int
908 engine_start_keymanager (HWND hwnd)
909 {
910   if (use_assuan)
911     return op_assuan_start_keymanager (hwnd);
912   else
913     return gpg_error (GPG_ERR_NOT_SUPPORTED);
914 }