Encryption basically works.
[gpgme.git] / complus / igpgme.c
1 /* igpgme.c - COM+ class IGpgme
2  *      Copyright (C) 2001 g10 Code GmbH
3  *
4  * This file is part of GPGME.
5  *
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.
10  *
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.
15  *
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
19  */
20
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <time.h>
29 #include <windows.h>
30
31 #include "../gpgme/gpgme.h"
32
33 /* FIXME: Put them into an extra header */
34 void *_gpgme_malloc (size_t n );
35 void *_gpgme_calloc (size_t n, size_t m );
36 void *_gpgme_realloc (void *p, size_t n);
37 char *_gpgme_strdup (const char *p);
38 void  _gpgme_free ( void *a );
39
40
41
42 #define INITGUID
43 #include "igpgme.h"
44
45 /*
46  * Declare the interface implementation structures
47  */
48 typedef struct IGpgmeImpl IGpgmeImpl;
49 typedef struct IClassFactoryImpl IClassFactoryImpl;
50
51
52 struct IGpgmeImpl {
53     /* IUnknown required stuff */
54     ICOM_VFIELD (IGpgme);
55     DWORD        ref;
56     /* Delegation to IDispatch */
57     struct {
58         IUnknown *disp;
59         ITypeInfo *tinfo;
60     } std_disp;
61     /* Our stuff */
62     GpgmeCtx mainctx;
63     GpgmeData plaintext;
64     int plaintext_given_as_bstr;
65     GpgmeData ciphertext;
66     int ciphertext_is_armored;
67     GpgmeRecipients rset;
68 };
69
70
71 struct IClassFactoryImpl {
72     /* IUnknown fields */
73     ICOM_VFIELD(IClassFactory);
74     DWORD       ref;
75 };
76
77 /**********************************************************
78  **************  helper functions  ************************
79  *********************************************************/
80 static HRESULT
81 map_gpgme_error (GpgmeError err)
82 {
83     HRESULT hr;
84
85     if (!err)
86         return 0;
87     if ( err < 0 || err > 0x1000 ) {
88         fprintf (stderr,"*** GpgmeError `%s' mapped to GPGME_General_Error\n",
89                  gpgme_strerror (err) );
90         err = GPGME_General_Error;
91     }
92     hr = MAKE_HRESULT (SEVERITY_ERROR, FACILITY_ITF, 0x1000 + err);
93     fprintf (stderr,"*** GpgmeError `%s' mapped to %lx\n",
94              gpgme_strerror (err), (unsigned long)hr );
95     return hr;
96 }
97
98
99 /**********************************************************
100  **************  IGpgme Implementation  *******************
101  *********************************************************/
102
103 static HRESULT WINAPI
104 m_IGpgme_QueryInterface (IGpgme *iface, REFIID refiid, LPVOID *obj)
105 {
106     ICOM_THIS (IGpgmeImpl,iface);
107
108     /*fprintf (stderr,"*** m_IGpgme_QueryInterface(%p,%s)",
109       This, debugstr_guid(refiid));*/
110     if ( IsEqualGUID (&IID_IUnknown, refiid)
111          || IsEqualGUID (&IID_IGpgme, refiid) ) {
112         *obj = This;
113         IGpgme_AddRef (iface);
114         fprintf (stderr," -> got %p\n", *obj);
115         return 0;
116     }
117     else if ( IsEqualGUID (&IID_IDispatch, refiid) ) {
118         HRESULT hr = IDispatch_QueryInterface (This->std_disp.disp,
119                                                refiid, obj);
120         /*fprintf (stderr," -> delegated, hr=%lx, got %p\n",
121            hr, hr? NULL: *obj);*/
122         return hr;
123     }
124     /*fprintf (stderr," -> none\n");*/
125     *obj = NULL;
126     return E_NOINTERFACE;
127 }
128
129
130 static ULONG WINAPI
131 m_IGpgme_AddRef (IGpgme *iface)
132 {
133     ICOM_THIS (IGpgmeImpl,iface);
134         
135     return ++This->ref;
136 }
137
138
139 static ULONG WINAPI
140 m_IGpgme_Release (IGpgme *iface)
141 {
142     ICOM_THIS (IGpgmeImpl,iface);
143         
144     if (--This->ref)
145         return This->ref;
146
147     gpgme_release (This->mainctx); This->mainctx = NULL;
148     gpgme_data_release (This->plaintext); This->plaintext = NULL;
149     gpgme_data_release (This->ciphertext); This->ciphertext = NULL;
150     gpgme_recipients_release (This->rset); This->rset = NULL;
151     if (This->std_disp.disp)
152         IDispatch_Release (This->std_disp.disp);
153     if (This->std_disp.tinfo)
154         ITypeInfo_Release (This->std_disp.tinfo);
155     HeapFree(GetProcessHeap(),0,iface);
156     return 0;
157 }
158
159
160 static HRESULT WINAPI
161 m_stub_IDispatch_GetTypeInfoCount (IGpgme *iface, unsigned int *pctinfo)
162 {
163     return E_NOTIMPL;
164 }
165
166 static HRESULT WINAPI
167 m_stub_IDispatch_GetTypeInfo (IGpgme *iface, UINT iTInfo,
168                               LCID lcid, ITypeInfo **ppTInfo)
169 {
170     return E_NOTIMPL;
171 }
172
173 static HRESULT WINAPI 
174 m_stub_IDispatch_GetIDsOfNames (IGpgme *iface, REFIID riid, 
175                                 LPOLESTR *rgszNames, UINT cNames, 
176                                 LCID lcid, DISPID *rgDispId)
177 {
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI 
182 m_stub_IDispatch_Invoke (IGpgme *iface, DISPID dispIdMember, 
183                          REFIID riid, LCID lcid, WORD wFlags,
184                          DISPPARAMS *pDispParams, VARIANT *pVarResult, 
185                          EXCEPINFO *pExepInfo,  UINT *puArgErr)
186 {
187   return E_NOTIMPL;
188 }
189
190
191
192 static HRESULT WINAPI
193 m_IGpgme_GetVersion (IGpgme *iface, BSTR *retvat)
194 {
195     return E_NOTIMPL;
196 }
197
198 static HRESULT WINAPI
199 m_IGpgme_GetEngineInfo (IGpgme *iface, BSTR *retval)
200 {
201     return E_NOTIMPL;
202 }
203
204
205 static HRESULT WINAPI
206 m_IGpgme_Cancel (IGpgme *iface)
207 {
208     return E_NOTIMPL;
209 }
210
211
212 static HRESULT WINAPI
213 m_IGpgme_SetArmor (IGpgme *iface, BOOL yes)
214 {
215     ICOM_THIS (IGpgmeImpl,iface);
216
217     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
218     gpgme_set_armor (This->mainctx, yes);
219     return 0;
220 }
221
222 static HRESULT WINAPI
223 m_IGpgme_GetArmor (IGpgme *iface, BOOL *retval)
224 {
225     ICOM_THIS (IGpgmeImpl,iface);
226
227     *retval = gpgme_get_armor (This->mainctx);
228     return 0;
229 }
230
231
232 static HRESULT WINAPI
233 m_IGpgme_SetTextmode (IGpgme *iface, BOOL yes)
234 {
235     ICOM_THIS (IGpgmeImpl,iface);
236
237     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
238     gpgme_set_textmode (This->mainctx, yes);
239     return 0;
240 }
241
242 static HRESULT WINAPI
243 m_IGpgme_GetTextmode (IGpgme *iface, BOOL *retval)
244 {
245     return E_NOTIMPL;
246 }
247
248
249 /* 
250  * Put the data from VAL into a a Gpgme data object, which is passed by
251  * reference.  Valid types of the Variant are: BSTR, SAFEARRAY of BYTE and
252  * SAFEARRAY of VARIANTS of signed or unsigned integers.
253  */
254 static HRESULT WINAPI
255 set_data_from_variant (GpgmeData *data, VARIANT val, int *given_as_bstr)
256 {
257     GpgmeError err = 0;
258     HRESULT hr;
259     unsigned char *buf;
260     SAFEARRAY *array;
261     size_t len;
262     int i;
263
264     if ( val.vt == VT_BSTR) {
265         len = bstrtoutf8 (val.u.bstrVal, NULL, 0);
266         buf = _gpgme_malloc (len);
267         if (!buf) 
268             return E_OUTOFMEMORY;
269         
270         if (bstrtoutf8 (val.u.bstrVal, buf, len) < 0) {
271             fprintf (stderr,"problem with bstrtoutf8\n");
272             _gpgme_free (buf);
273             return E_FAIL;
274         }
275
276         fprintf (stderr,"Got a BSTR (utf8):");
277         for (i=0; i < len; i++)
278             fprintf (stderr, " %0X", buf[i] );
279         putc ('\n', stderr);
280         gpgme_data_release (*data); *data = NULL; 
281         err = gpgme_data_new_from_mem (data, buf, len, 0 /*no need to copy*/ );
282         if (!err && given_as_bstr)
283             *given_as_bstr = 1;
284     }
285     else if ( val.vt == (VT_ARRAY|VT_UI1)) {
286         array = val.u.parray;
287
288         fprintf (stderr,"Got an ARRAY of bytes:");
289         hr = SafeArrayAccessData (array, (void**)&buf);
290         if (hr) {
291             fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr);
292             return hr;
293         }
294         len = array->rgsabound[0].cElements;
295         for (i=0; i < len; i++)
296             fprintf (stderr, " %0X", buf[i] );
297         putc ('\n', stderr);
298         
299         gpgme_data_release (*data); *data = NULL; 
300         err = gpgme_data_new_from_mem (data, buf, len, 1 );
301         SafeArrayUnaccessData (array);
302         if (given_as_bstr)
303             *given_as_bstr = 0;
304     }
305     else if ( val.vt == (VT_ARRAY|VT_VARIANT)) {
306         VARIANT *vp;
307         array = val.u.parray;
308
309         fprintf (stderr,"Got an ARRAY of VARIANTS:");
310         hr = SafeArrayAccessData (array, (void**)&vp);
311         if (hr) {
312             fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr);
313             return hr;
314         }
315         len = array->rgsabound[0].cElements;
316         /* allocate the array using the gpgme allocator so that we can
317          * later use a new without the copy set*/
318         buf = _gpgme_malloc (len);
319         if (!buf) {
320             SafeArrayUnaccessData (array);
321             return E_OUTOFMEMORY;
322         }
323         /* coerce all array elements into rawtext */
324         for (i=0; i < len; i++) {
325             switch (vp[i].vt) {
326               case VT_I1:   buf[i] = (BYTE)vp[i].u.cVal; break; 
327               case VT_I2:   buf[i] = ((UINT)vp[i].u.iVal) & 0xff; break; 
328               case VT_I4:   buf[i] = ((ULONG)vp[i].u.lVal) & 0xff; break; 
329               case VT_INT:  buf[i] = ((UINT)vp[i].u.intVal) & 0xff; break; 
330               case VT_UI1:  buf[i] = vp[i].u.bVal; break; 
331               case VT_UI2:  buf[i] = vp[i].u.uiVal & 0xff; break; 
332               case VT_UI4:  buf[i] = vp[i].u.ulVal & 0xff; break; 
333               case VT_UINT: buf[i] = vp[i].u.uintVal & 0xff; break; 
334               default: 
335                 fprintf (stderr, "Invalid value in array as pos %d\n", i);
336                 _gpgme_free (buf);
337                 SafeArrayUnaccessData (array);
338                 return E_INVALIDARG; 
339             }
340         }
341
342         for (i=0; i < len; i++)
343             fprintf (stderr, " %0X", buf[i] );
344         putc ('\n', stderr);
345         
346         gpgme_data_release (*data); *data = NULL;
347         err = gpgme_data_new_from_mem (data, buf, len, 0);
348         SafeArrayUnaccessData (array);
349         if (given_as_bstr)
350             *given_as_bstr = 0;
351     }
352     else {
353         fprintf (stderr, "Got a variant type = %d (0x%x)\n",
354                  (int)val.vt, (int)val.vt );
355         return E_INVALIDARG; /* not a safearray of bytes */
356     }
357     return map_gpgme_error (err);
358 }
359
360
361 static HRESULT WINAPI
362 set_data_to_variant (GpgmeData data, VARIANT *retval, int use_bstr)
363 {
364     GpgmeError err;
365     HRESULT hr;
366     SAFEARRAY *array;
367     char *p;
368     size_t nread, len;
369     int i;
370
371     /* Get some info on the data */
372     err = gpgme_data_rewind (data);
373     if (err ) {
374         fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err);
375         return map_gpgme_error (err);
376     }
377     err = gpgme_data_read (data, NULL, 0, &nread);
378     if (err && err != GPGME_EOF ) {
379         fprintf (stderr, "*** gpgme_data_read [length] failed: %d\n", err);
380         return map_gpgme_error (err);
381     }
382     len = nread;  /*(eof returns a length of 0)*/
383     fprintf (stderr,"*** %d bytes are availabe\n", (int)len);
384
385     /* convert it to the target data type */
386     if (use_bstr) {
387         BSTR bs;
388         unsigned char *helpbuf;
389
390         fprintf (stderr,"   using BSTR\n");
391         /* It is easier to allocate some helper storage */
392         helpbuf = _gpgme_malloc (len);
393         if (!helpbuf) 
394             return E_OUTOFMEMORY;
395         err = gpgme_data_read (data, helpbuf, len, &nread);
396         if (err ) {
397             _gpgme_free (helpbuf);
398             fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err);
399             return map_gpgme_error (err);
400         }
401
402         bs = SysAllocStringLen (NULL, len+1);
403         if (!bs) {
404             _gpgme_free (helpbuf);
405             return E_OUTOFMEMORY;
406         }
407
408         for (i=0, p=helpbuf; i < len; i++, p++) 
409             bs[i] = *p;
410         bs[i] = 0;
411         _gpgme_free (helpbuf);
412
413         /* Ready */
414         VariantInit (retval);
415         retval->vt = VT_BSTR;
416         retval->u.bstrVal = bs;
417     }
418 #if 0
419     else if (use_byte_array) {
420         array = SafeArrayCreateVector (VT_UI1, 0, len);
421         if (!array)
422             return E_OUTOFMEMORY;
423
424         p = NULL;
425         hr = SafeArrayAccessData (array, (void**)&p);
426         if (hr) {
427             fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr);
428             SafeArrayDestroyData (array);
429             SafeArrayDestroy (array);
430             return hr;
431         }
432         if (len) {
433             err = gpgme_data_read (data, p, len, &nread);
434             if (err ) {
435                 SafeArrayUnaccessData (array);
436                 SafeArrayDestroyData (array);
437                 SafeArrayDestroy (array);
438                 fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n",
439                          err);
440                 return map_gpgme_error (err);
441             }
442         }
443         SafeArrayUnaccessData (array);
444         
445         /* pass the data to the caller */
446         VariantInit (retval);
447         retval->vt = (VT_ARRAY|VT_UI1);
448         retval->u.parray = array;
449     }
450 #endif
451     else { /* Create an array of variants of bytes */
452         VARIANT *v;
453         unsigned char *helpbuf;
454
455         /* It is easier to allocate some helper storage */
456         helpbuf = _gpgme_malloc (len);
457         if (!helpbuf)
458             return E_OUTOFMEMORY;
459         err = gpgme_data_read (data, helpbuf, len, &nread);
460         if (err ) {
461             _gpgme_free (helpbuf);
462             fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err);
463             return map_gpgme_error (err);
464         }
465
466         /* The create the array */
467         array = SafeArrayCreateVector (VT_VARIANT, 0, len);
468         if (!array) {
469             _gpgme_free (helpbuf);
470             return E_OUTOFMEMORY;
471         }
472         
473         v = NULL;
474         hr = SafeArrayAccessData (array, (void**)&v);
475         if (hr) {
476             fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr);
477             _gpgme_free (helpbuf);
478             SafeArrayDestroyData (array);
479             SafeArrayDestroy (array);
480             return hr;
481         }
482
483         for (p=helpbuf; len; len--, v++) {
484             VariantInit (v);
485             v->vt = VT_UI1;
486             v->u.bVal = *p;
487         }
488         SafeArrayUnaccessData (array);
489         _gpgme_free (helpbuf);
490         
491         /* pass the data to the caller */
492         VariantInit (retval);
493         retval->vt = (VT_ARRAY|VT_VARIANT);
494         retval->u.parray = array;
495     }
496     return 0;
497 }
498
499
500 static HRESULT WINAPI
501 m_IGpgme_SetPlaintext (IGpgme *iface, VARIANT val)
502 {
503     ICOM_THIS (IGpgmeImpl,iface);
504
505     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
506     return set_data_from_variant (&This->plaintext, val,
507                                   &This->plaintext_given_as_bstr); 
508 }
509
510
511 static HRESULT WINAPI
512 m_IGpgme_GetPlaintext (IGpgme *iface, VARIANT *retval)
513 {
514     ICOM_THIS (IGpgmeImpl,iface);
515
516     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
517     return set_data_to_variant (This->plaintext, retval,
518                                 This->plaintext_given_as_bstr);
519 }
520
521 static HRESULT WINAPI
522 m_IGpgme_SetCiphertext (IGpgme *iface, VARIANT val)
523 {
524     ICOM_THIS (IGpgmeImpl,iface);
525
526     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
527     return set_data_from_variant (&This->ciphertext, val, NULL); 
528 }
529
530 static HRESULT WINAPI
531 m_IGpgme_GetCiphertext (IGpgme *iface, VARIANT *retval)
532 {
533     ICOM_THIS (IGpgmeImpl,iface);
534
535     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
536     return set_data_to_variant (This->ciphertext, retval,
537                                 This->ciphertext_is_armored);
538 }
539
540 static HRESULT WINAPI
541 m_IGpgme_ClearRecipients (IGpgme *iface)
542 {
543     ICOM_THIS (IGpgmeImpl,iface);
544
545     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
546     gpgme_recipients_release (This->rset); This->rset = NULL;
547     return 0;
548 }
549
550
551 static HRESULT WINAPI
552 m_IGpgme_AddRecipient (IGpgme *iface, BSTR name, signed short int trust)
553 {
554     GpgmeError err;
555     int n;
556     char *p;
557     ICOM_THIS (IGpgmeImpl,iface);
558     
559     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p, %d)\n", This, (int)trust);
560     if (!This->rset) {
561         err = gpgme_recipients_new (&This->rset);
562         if (err)
563             return map_gpgme_error (err);
564     }
565
566     n = bstrtoutf8 (name, NULL, 0);
567     p = HeapAlloc (GetProcessHeap(), 0, n );
568     if (!p) {
569         fprintf (stderr,"HeapAlloc failed: ec=%d\n", (int)GetLastError () );
570         return E_OUTOFMEMORY;
571     }
572     if (bstrtoutf8 (name, p, n) < 0) {
573         fprintf (stderr,"problem with bstrtoutf8\n");
574         HeapFree (GetProcessHeap(), 0, p);
575         return E_FAIL;
576     }
577     fprintf (stderr,"*** adding name `%s'\n", p);
578     err = gpgme_recipients_add_name (This->rset, p);
579     HeapFree (GetProcessHeap(), 0, p);
580     return map_gpgme_error (err);
581 }
582
583 static HRESULT WINAPI
584 m_IGpgme_ResetSignKeys (IGpgme *iface)
585 {
586     ICOM_THIS (IGpgmeImpl,iface);
587
588     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
589
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI
594 m_IGpgme_AddSignKey (IGpgme *iface, BSTR name)
595 {
596     ICOM_THIS (IGpgmeImpl,iface);
597
598     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
599
600     return E_NOTIMPL;
601 }
602
603 static HRESULT WINAPI
604 m_IGpgme_Encrypt (IGpgme *iface)
605 {
606     GpgmeError err;
607     ICOM_THIS (IGpgmeImpl,iface);
608
609     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
610     gpgme_data_release (This->ciphertext);
611     err = gpgme_data_new (&This->ciphertext);
612     if (err)
613         return map_gpgme_error (err);
614
615     
616     This->ciphertext_is_armored = gpgme_get_armor (This->mainctx);
617     err = gpgme_op_encrypt (This->mainctx, This->rset,
618                             This->plaintext, This->ciphertext);
619 #if 0
620     if (!err ) {
621         char buf[100];
622         size_t nread;
623
624         err = gpgme_data_rewind ( This->ciphertext );
625         if (err ) 
626             fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err);
627         while ( !(err = gpgme_data_read ( This->ciphertext,
628                                           buf, 100, &nread )) ) {
629             fwrite ( buf, nread, 1, stderr );
630         }
631         if (err != GPGME_EOF) 
632             fprintf (stderr, "*** gpgme_data_read failed: %d\n", err);
633         err = 0;
634     }
635 #endif
636
637     return map_gpgme_error (err);
638 }
639
640 static HRESULT WINAPI
641 m_IGpgme_Sign (IGpgme *iface, short int signmode)
642 {
643     ICOM_THIS (IGpgmeImpl,iface);
644
645     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
646
647     return E_NOTIMPL;
648 }
649
650 static HRESULT WINAPI
651 m_IGpgme_SignEncrypt (IGpgme *iface, short int signmode)
652 {
653     ICOM_THIS (IGpgmeImpl,iface);
654
655     fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );
656
657     return E_NOTIMPL;
658 }
659
660 #if 0
661 static HRESULT WINAPI
662 m_IGpgme_SetKeylistMode( GpgmeCtx c, BOOL mode )
663 {
664     return 0;
665 }
666
667
668 static HRESULT WINAPI
669 m_IGpgme_SetPassphraseCB (GpgmeCtx c,
670                           GpgmePassphraseCb cb, void *cb_value)
671 {
672     return 0;
673 }
674
675
676 static HRESULT WINAPI
677 m_IGpgme_SetProgressCB (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value)
678 {
679     return E_NOTIMPL;
680 }
681
682
683 static HRESULT WINAPI
684 m_IGpgme_SignersClear (GpgmeCtx c)
685 {
686     return 0;
687 }
688
689
690 static HRESULT WINAPI
691 m_IGpgme_SignersAdd (GpgmeCtx c, const GpgmeKey key)
692 {
693     return 0;
694 }
695
696
697 static HRESULT WINAPI
698 m_IGpgme_SignersEnum (const GpgmeCtx c, int seq)
699 {
700     return 0;
701 }
702
703
704 static HRESULT WINAPI
705 m_IGpgme_GetSigStatus(GpgmeCtx c, int idx,
706                                   GpgmeSigStat *r_stat, time_t *r_created );
707 {
708     return 0;
709 }
710
711
712 static HRESULT WINAPI
713 m_IGpgme_GetSigKey (GpgmeCtx c, int idx, GpgmeKey *r_key);
714 {
715     return 0;
716 }
717
718 static HRESULT WINAPI
719 m_IGpgme_GetNotation(IGpgme *c, BSTR *retval)
720 {
721     return 0;
722 }
723 #endif
724
725
726 static ICOM_VTABLE(IGpgme) igpgme_vtbl = 
727 {
728     /* IUnknown methods */
729     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
730     m_IGpgme_QueryInterface,
731     m_IGpgme_AddRef,
732     m_IGpgme_Release,
733     /* IDispatch methods */
734     m_stub_IDispatch_GetTypeInfoCount,
735     m_stub_IDispatch_GetTypeInfo,
736     m_stub_IDispatch_GetIDsOfNames,
737     m_stub_IDispatch_Invoke,
738     /* Our methods */
739     m_IGpgme_GetVersion,
740     m_IGpgme_GetEngineInfo,
741     m_IGpgme_Cancel,             
742     m_IGpgme_SetArmor,            
743     m_IGpgme_GetArmor,            
744     m_IGpgme_SetTextmode,         
745     m_IGpgme_GetTextmode,         
746     m_IGpgme_SetPlaintext,
747     m_IGpgme_GetPlaintext,
748     m_IGpgme_SetCiphertext,
749     m_IGpgme_GetCiphertext,
750     m_IGpgme_ClearRecipients,
751     m_IGpgme_AddRecipient,
752     m_IGpgme_ResetSignKeys,
753     m_IGpgme_AddSignKey,
754     m_IGpgme_Encrypt, 
755     m_IGpgme_Sign, 
756     m_IGpgme_SignEncrypt, 
757 /*    m_IGpgme_SetKeylistMode,      
758  *    m_IGpgme_SetPassphraseCB,    
759  *    m_IGpgme_SetProgressCB,      
760  *    m_IGpgme_SignersClear,       
761  *    m_IGpgme_SignersAdd,         
762  *    m_IGpgme_SignersEnum,        
763  *    m_IGpgme_GetSigStatus,        
764  *    m_IGpgme_GetSigKey,      
765  *    m_IGpgme_GetNotation
766  */
767 };
768
769
770
771 /***************************************************************
772  ******************  Gpgme Factory  ****************************
773  ***************************************************************/
774
775 static HRESULT WINAPI 
776 m_GpgmeFactory_QueryInterface (IClassFactory *iface,
777                                REFIID refiid, LPVOID *obj)
778 {
779     ICOM_THIS (IClassFactoryImpl,iface);
780
781     /*fprintf (stderr,"*** m_GpgmeFactory_QueryInterface(%p,%s)",
782       This, debugstr_guid(refiid));*/
783     if ( IsEqualGUID (&IID_IUnknown, refiid)
784          || IsEqualGUID (&IID_IClassFactory, refiid) ) {
785         *obj = This;
786         /*fprintf (stderr," -> got %p\n", obj);*/
787         return 0;
788     }
789     *obj = NULL;
790     /*fprintf (stderr," -> none\n");*/
791     return E_NOINTERFACE;
792 }
793
794 static ULONG WINAPI
795 m_GpgmeFactory_AddRef (IClassFactory *iface)
796 {
797     ICOM_THIS(IClassFactoryImpl,iface);
798     return ++(This->ref);
799 }
800
801 static ULONG WINAPI
802 m_GpgmeFactory_Release (IClassFactory *iface)
803 {
804     ICOM_THIS(IClassFactoryImpl,iface);
805     return --(This->ref);
806 }
807
808 static HRESULT WINAPI
809 m_GpgmeFactory_CreateInstance (IClassFactory *iface, IUnknown *outer,
810                                REFIID refiid, LPVOID *r_obj )
811 {
812     /*ICOM_THIS(IClassFactoryImpl,iface);*/
813
814     fprintf (stderr,"*** m_GpgmeFactory_CreateInstance(%s)",
815              debugstr_guid(refiid) );
816     if (   IsEqualGUID (&IID_IUnknown, refiid)
817         || IsEqualGUID (&IID_IGpgme, refiid) ) {
818         IGpgmeImpl *obj;
819         GpgmeCtx ctx;
820         GpgmeError err;
821
822
823         err = gpgme_new (&ctx);
824         if (err) {
825             fprintf (stderr," -> gpgme_new failed: %s\n", gpgme_strerror (err));
826             return E_OUTOFMEMORY;
827         }
828
829         obj = HeapAlloc (GetProcessHeap(), 0, sizeof *obj );
830         if ( !obj) {
831             fprintf (stderr," -> out of core\n");
832             gpgme_release (ctx);
833             return E_OUTOFMEMORY;
834         }
835         memset (obj, 0, sizeof *obj);
836
837         ICOM_VTBL(obj) = &igpgme_vtbl;
838         obj->ref = 1;
839         obj->mainctx = ctx;
840         {   /* Fixme: need to release some stuff on error */
841             HRESULT hr;
842             ITypeLib *pTypeLib;
843
844             hr = LoadRegTypeLib (&TLBID_Gpgcom, 1, 0, LANG_NEUTRAL, &pTypeLib);
845             if (hr) {
846                 fprintf (stderr," -> LoadRegTypeLib failed: %lx\n", hr);
847                 return hr;
848             }
849             hr = ITypeLib_GetTypeInfoOfGuid (pTypeLib, &IID_IGpgme,
850                                              &obj->std_disp.tinfo);
851             ITypeLib_Release (pTypeLib);
852             if (hr) {
853                 fprintf (stderr," -> GetTypeInfoOfGuid failed: %lx\n", hr);
854                 return hr;
855             }
856             hr = CreateStdDispatch ((IUnknown*)obj, obj, obj->std_disp.tinfo,
857                                      &obj->std_disp.disp);
858             if (hr) {
859                 fprintf (stderr," -> CreateStdDispatch failed: %lx\n", hr);
860                 return hr;
861             }
862         }
863
864         *r_obj = obj;
865         fprintf (stderr," -> created %p\n", obj );
866         return 0;
867     }
868     fprintf (stderr," -> no interface\n" );
869     *r_obj = NULL;
870     return E_NOINTERFACE;
871 }
872
873 static HRESULT WINAPI
874 m_GpgmeFactory_LockServer (IClassFactory *iface, BOOL dolock )
875 {
876     /*ICOM_THIS(IClassFactoryImpl,iface);*/
877     return 0;
878 }
879
880 static ICOM_VTABLE(IClassFactory) igpgme_factory_vtbl = {
881     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
882     m_GpgmeFactory_QueryInterface,
883     m_GpgmeFactory_AddRef,
884     m_GpgmeFactory_Release,
885     m_GpgmeFactory_CreateInstance,
886     m_GpgmeFactory_LockServer
887 };
888 static IClassFactoryImpl igpgme_CF = {&igpgme_factory_vtbl, 1 };
889
890
891 IClassFactory *
892 igpgme_factory_new ( CLSID *r_clsid )
893 {
894     *r_clsid = CLSID_Gpgme;
895     IClassFactory_AddRef((IClassFactory*)&igpgme_CF);
896     return (IClassFactory*)&igpgme_CF;
897 }
898
899 void
900 igpgme_factory_release ( IClassFactory *factory )
901 {
902     /* it's static - nothing to do */
903 }