diff options
Diffstat (limited to '')
-rw-r--r-- | complus/igpgme.c | 903 |
1 files changed, 903 insertions, 0 deletions
diff --git a/complus/igpgme.c b/complus/igpgme.c new file mode 100644 index 00000000..5983ce8c --- /dev/null +++ b/complus/igpgme.c @@ -0,0 +1,903 @@ +/* igpgme.c - COM+ class IGpgme + * Copyright (C) 2001 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <time.h> +#include <windows.h> + +#include "../gpgme/gpgme.h" + +/* FIXME: Put them into an extra header */ +void *_gpgme_malloc (size_t n ); +void *_gpgme_calloc (size_t n, size_t m ); +void *_gpgme_realloc (void *p, size_t n); +char *_gpgme_strdup (const char *p); +void _gpgme_free ( void *a ); + + + +#define INITGUID +#include "igpgme.h" + +/* + * Declare the interface implementation structures + */ +typedef struct IGpgmeImpl IGpgmeImpl; +typedef struct IClassFactoryImpl IClassFactoryImpl; + + +struct IGpgmeImpl { + /* IUnknown required stuff */ + ICOM_VFIELD (IGpgme); + DWORD ref; + /* Delegation to IDispatch */ + struct { + IUnknown *disp; + ITypeInfo *tinfo; + } std_disp; + /* Our stuff */ + GpgmeCtx mainctx; + GpgmeData plaintext; + int plaintext_given_as_bstr; + GpgmeData ciphertext; + int ciphertext_is_armored; + GpgmeRecipients rset; +}; + + +struct IClassFactoryImpl { + /* IUnknown fields */ + ICOM_VFIELD(IClassFactory); + DWORD ref; +}; + +/********************************************************** + ************** helper functions ************************ + *********************************************************/ +static HRESULT +map_gpgme_error (GpgmeError err) +{ + HRESULT hr; + + if (!err) + return 0; + if ( err < 0 || err > 0x1000 ) { + fprintf (stderr,"*** GpgmeError `%s' mapped to GPGME_General_Error\n", + gpgme_strerror (err) ); + err = GPGME_General_Error; + } + hr = MAKE_HRESULT (SEVERITY_ERROR, FACILITY_ITF, 0x1000 + err); + fprintf (stderr,"*** GpgmeError `%s' mapped to %lx\n", + gpgme_strerror (err), (unsigned long)hr ); + return hr; +} + + +/********************************************************** + ************** IGpgme Implementation ******************* + *********************************************************/ + +static HRESULT WINAPI +m_IGpgme_QueryInterface (IGpgme *iface, REFIID refiid, LPVOID *obj) +{ + ICOM_THIS (IGpgmeImpl,iface); + + /*fprintf (stderr,"*** m_IGpgme_QueryInterface(%p,%s)", + This, debugstr_guid(refiid));*/ + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IGpgme, refiid) ) { + *obj = This; + IGpgme_AddRef (iface); + fprintf (stderr," -> got %p\n", *obj); + return 0; + } + else if ( IsEqualGUID (&IID_IDispatch, refiid) ) { + HRESULT hr = IDispatch_QueryInterface (This->std_disp.disp, + refiid, obj); + /*fprintf (stderr," -> delegated, hr=%lx, got %p\n", + hr, hr? NULL: *obj);*/ + return hr; + } + /*fprintf (stderr," -> none\n");*/ + *obj = NULL; + return E_NOINTERFACE; +} + + +static ULONG WINAPI +m_IGpgme_AddRef (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + return ++This->ref; +} + + +static ULONG WINAPI +m_IGpgme_Release (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + if (--This->ref) + return This->ref; + + gpgme_release (This->mainctx); This->mainctx = NULL; + gpgme_data_release (This->plaintext); This->plaintext = NULL; + gpgme_data_release (This->ciphertext); This->ciphertext = NULL; + gpgme_recipients_release (This->rset); This->rset = NULL; + if (This->std_disp.disp) + IDispatch_Release (This->std_disp.disp); + if (This->std_disp.tinfo) + ITypeInfo_Release (This->std_disp.tinfo); + HeapFree(GetProcessHeap(),0,iface); + return 0; +} + + +static HRESULT WINAPI +m_stub_IDispatch_GetTypeInfoCount (IGpgme *iface, unsigned int *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_GetTypeInfo (IGpgme *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_GetIDsOfNames (IGpgme *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_Invoke (IGpgme *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + return E_NOTIMPL; +} + + + +static HRESULT WINAPI +m_IGpgme_GetVersion (IGpgme *iface, BSTR *retvat) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_GetEngineInfo (IGpgme *iface, BSTR *retval) +{ + return E_NOTIMPL; +} + + +static HRESULT WINAPI +m_IGpgme_Cancel (IGpgme *iface) +{ + return E_NOTIMPL; +} + + +static HRESULT WINAPI +m_IGpgme_SetArmor (IGpgme *iface, BOOL yes) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + gpgme_set_armor (This->mainctx, yes); + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetArmor (IGpgme *iface, BOOL *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + *retval = gpgme_get_armor (This->mainctx); + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetTextmode (IGpgme *iface, BOOL yes) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + gpgme_set_textmode (This->mainctx, yes); + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetTextmode (IGpgme *iface, BOOL *retval) +{ + return E_NOTIMPL; +} + + +/* + * Put the data from VAL into a a Gpgme data object, which is passed by + * reference. Valid types of the Variant are: BSTR, SAFEARRAY of BYTE and + * SAFEARRAY of VARIANTS of signed or unsigned integers. + */ +static HRESULT WINAPI +set_data_from_variant (GpgmeData *data, VARIANT val, int *given_as_bstr) +{ + GpgmeError err = 0; + HRESULT hr; + unsigned char *buf; + SAFEARRAY *array; + size_t len; + int i; + + if ( val.vt == VT_BSTR) { + len = bstrtoutf8 (val.u.bstrVal, NULL, 0); + buf = _gpgme_malloc (len); + if (!buf) + return E_OUTOFMEMORY; + + if (bstrtoutf8 (val.u.bstrVal, buf, len) < 0) { + fprintf (stderr,"problem with bstrtoutf8\n"); + _gpgme_free (buf); + return E_FAIL; + } + + fprintf (stderr,"Got a BSTR (utf8):"); + for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr); + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 0 /*no need to copy*/ ); + if (!err && given_as_bstr) + *given_as_bstr = 1; + } + else if ( val.vt == (VT_ARRAY|VT_UI1)) { + array = val.u.parray; + + fprintf (stderr,"Got an ARRAY of bytes:"); + hr = SafeArrayAccessData (array, (void**)&buf); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + return hr; + } + len = array->rgsabound[0].cElements; + for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr); + + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 1 ); + SafeArrayUnaccessData (array); + if (given_as_bstr) + *given_as_bstr = 0; + } + else if ( val.vt == (VT_ARRAY|VT_VARIANT)) { + VARIANT *vp; + array = val.u.parray; + + fprintf (stderr,"Got an ARRAY of VARIANTS:"); + hr = SafeArrayAccessData (array, (void**)&vp); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + return hr; + } + len = array->rgsabound[0].cElements; + /* allocate the array using the gpgme allocator so that we can + * later use a new without the copy set*/ + buf = _gpgme_malloc (len); + if (!buf) { + SafeArrayUnaccessData (array); + return E_OUTOFMEMORY; + } + /* coerce all array elements into rawtext */ + for (i=0; i < len; i++) { + switch (vp[i].vt) { + case VT_I1: buf[i] = (BYTE)vp[i].u.cVal; break; + case VT_I2: buf[i] = ((UINT)vp[i].u.iVal) & 0xff; break; + case VT_I4: buf[i] = ((ULONG)vp[i].u.lVal) & 0xff; break; + case VT_INT: buf[i] = ((UINT)vp[i].u.intVal) & 0xff; break; + case VT_UI1: buf[i] = vp[i].u.bVal; break; + case VT_UI2: buf[i] = vp[i].u.uiVal & 0xff; break; + case VT_UI4: buf[i] = vp[i].u.ulVal & 0xff; break; + case VT_UINT: buf[i] = vp[i].u.uintVal & 0xff; break; + default: + fprintf (stderr, "Invalid value in array as pos %d\n", i); + _gpgme_free (buf); + SafeArrayUnaccessData (array); + return E_INVALIDARG; + } + } + + for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr); + + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 0); + SafeArrayUnaccessData (array); + if (given_as_bstr) + *given_as_bstr = 0; + } + else { + fprintf (stderr, "Got a variant type = %d (0x%x)\n", + (int)val.vt, (int)val.vt ); + return E_INVALIDARG; /* not a safearray of bytes */ + } + return map_gpgme_error (err); +} + + +static HRESULT WINAPI +set_data_to_variant (GpgmeData data, VARIANT *retval, int use_bstr) +{ + GpgmeError err; + HRESULT hr; + SAFEARRAY *array; + char *p; + size_t nread, len; + int i; + + /* Get some info on the data */ + err = gpgme_data_rewind (data); + if (err ) { + fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err); + return map_gpgme_error (err); + } + err = gpgme_data_read (data, NULL, 0, &nread); + if (err && err != GPGME_EOF ) { + fprintf (stderr, "*** gpgme_data_read [length] failed: %d\n", err); + return map_gpgme_error (err); + } + len = nread; /*(eof returns a length of 0)*/ + fprintf (stderr,"*** %d bytes are availabe\n", (int)len); + + /* convert it to the target data type */ + if (use_bstr) { + BSTR bs; + unsigned char *helpbuf; + + fprintf (stderr," using BSTR\n"); + /* It is easier to allocate some helper storage */ + helpbuf = _gpgme_malloc (len); + if (!helpbuf) + return E_OUTOFMEMORY; + err = gpgme_data_read (data, helpbuf, len, &nread); + if (err ) { + _gpgme_free (helpbuf); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err); + return map_gpgme_error (err); + } + + bs = SysAllocStringLen (NULL, len+1); + if (!bs) { + _gpgme_free (helpbuf); + return E_OUTOFMEMORY; + } + + for (i=0, p=helpbuf; i < len; i++, p++) + bs[i] = *p; + bs[i] = 0; + _gpgme_free (helpbuf); + + /* Ready */ + VariantInit (retval); + retval->vt = VT_BSTR; + retval->u.bstrVal = bs; + } +#if 0 + else if (use_byte_array) { + array = SafeArrayCreateVector (VT_UI1, 0, len); + if (!array) + return E_OUTOFMEMORY; + + p = NULL; + hr = SafeArrayAccessData (array, (void**)&p); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + return hr; + } + if (len) { + err = gpgme_data_read (data, p, len, &nread); + if (err ) { + SafeArrayUnaccessData (array); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", + err); + return map_gpgme_error (err); + } + } + SafeArrayUnaccessData (array); + + /* pass the data to the caller */ + VariantInit (retval); + retval->vt = (VT_ARRAY|VT_UI1); + retval->u.parray = array; + } +#endif + else { /* Create an array of variants of bytes */ + VARIANT *v; + unsigned char *helpbuf; + + /* It is easier to allocate some helper storage */ + helpbuf = _gpgme_malloc (len); + if (!helpbuf) + return E_OUTOFMEMORY; + err = gpgme_data_read (data, helpbuf, len, &nread); + if (err ) { + _gpgme_free (helpbuf); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err); + return map_gpgme_error (err); + } + + /* The create the array */ + array = SafeArrayCreateVector (VT_VARIANT, 0, len); + if (!array) { + _gpgme_free (helpbuf); + return E_OUTOFMEMORY; + } + + v = NULL; + hr = SafeArrayAccessData (array, (void**)&v); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + _gpgme_free (helpbuf); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + return hr; + } + + for (p=helpbuf; len; len--, v++) { + VariantInit (v); + v->vt = VT_UI1; + v->u.bVal = *p; + } + SafeArrayUnaccessData (array); + _gpgme_free (helpbuf); + + /* pass the data to the caller */ + VariantInit (retval); + retval->vt = (VT_ARRAY|VT_VARIANT); + retval->u.parray = array; + } + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetPlaintext (IGpgme *iface, VARIANT val) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + return set_data_from_variant (&This->plaintext, val, + &This->plaintext_given_as_bstr); +} + + +static HRESULT WINAPI +m_IGpgme_GetPlaintext (IGpgme *iface, VARIANT *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + return set_data_to_variant (This->plaintext, retval, + This->plaintext_given_as_bstr); +} + +static HRESULT WINAPI +m_IGpgme_SetCiphertext (IGpgme *iface, VARIANT val) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + return set_data_from_variant (&This->ciphertext, val, NULL); +} + +static HRESULT WINAPI +m_IGpgme_GetCiphertext (IGpgme *iface, VARIANT *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + return set_data_to_variant (This->ciphertext, retval, + This->ciphertext_is_armored); +} + +static HRESULT WINAPI +m_IGpgme_ClearRecipients (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + gpgme_recipients_release (This->rset); This->rset = NULL; + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_AddRecipient (IGpgme *iface, BSTR name, signed short int trust) +{ + GpgmeError err; + int n; + char *p; + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p, %d)\n", This, (int)trust); + if (!This->rset) { + err = gpgme_recipients_new (&This->rset); + if (err) + return map_gpgme_error (err); + } + + n = bstrtoutf8 (name, NULL, 0); + p = HeapAlloc (GetProcessHeap(), 0, n ); + if (!p) { + fprintf (stderr,"HeapAlloc failed: ec=%d\n", (int)GetLastError () ); + return E_OUTOFMEMORY; + } + if (bstrtoutf8 (name, p, n) < 0) { + fprintf (stderr,"problem with bstrtoutf8\n"); + HeapFree (GetProcessHeap(), 0, p); + return E_FAIL; + } + fprintf (stderr,"*** adding name `%s'\n", p); + err = gpgme_recipients_add_name (This->rset, p); + HeapFree (GetProcessHeap(), 0, p); + return map_gpgme_error (err); +} + +static HRESULT WINAPI +m_IGpgme_ResetSignKeys (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_AddSignKey (IGpgme *iface, BSTR name) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_Encrypt (IGpgme *iface) +{ + GpgmeError err; + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + gpgme_data_release (This->ciphertext); + err = gpgme_data_new (&This->ciphertext); + if (err) + return map_gpgme_error (err); + + + This->ciphertext_is_armored = gpgme_get_armor (This->mainctx); + err = gpgme_op_encrypt (This->mainctx, This->rset, + This->plaintext, This->ciphertext); +#if 0 + if (!err ) { + char buf[100]; + size_t nread; + + err = gpgme_data_rewind ( This->ciphertext ); + if (err ) + fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err); + while ( !(err = gpgme_data_read ( This->ciphertext, + buf, 100, &nread )) ) { + fwrite ( buf, nread, 1, stderr ); + } + if (err != GPGME_EOF) + fprintf (stderr, "*** gpgme_data_read failed: %d\n", err); + err = 0; + } +#endif + + return map_gpgme_error (err); +} + +static HRESULT WINAPI +m_IGpgme_Sign (IGpgme *iface, short int signmode) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_SignEncrypt (IGpgme *iface, short int signmode) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +#if 0 +static HRESULT WINAPI +m_IGpgme_SetKeylistMode( GpgmeCtx c, BOOL mode ) +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetPassphraseCB (GpgmeCtx c, + GpgmePassphraseCb cb, void *cb_value) +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetProgressCB (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value) +{ + return E_NOTIMPL; +} + + +static HRESULT WINAPI +m_IGpgme_SignersClear (GpgmeCtx c) +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SignersAdd (GpgmeCtx c, const GpgmeKey key) +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SignersEnum (const GpgmeCtx c, int seq) +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_GetSigStatus(GpgmeCtx c, int idx, + GpgmeSigStat *r_stat, time_t *r_created ); +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_GetSigKey (GpgmeCtx c, int idx, GpgmeKey *r_key); +{ + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetNotation(IGpgme *c, BSTR *retval) +{ + return 0; +} +#endif + + +static ICOM_VTABLE(IGpgme) igpgme_vtbl = +{ + /* IUnknown methods */ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + m_IGpgme_QueryInterface, + m_IGpgme_AddRef, + m_IGpgme_Release, + /* IDispatch methods */ + m_stub_IDispatch_GetTypeInfoCount, + m_stub_IDispatch_GetTypeInfo, + m_stub_IDispatch_GetIDsOfNames, + m_stub_IDispatch_Invoke, + /* Our methods */ + m_IGpgme_GetVersion, + m_IGpgme_GetEngineInfo, + m_IGpgme_Cancel, + m_IGpgme_SetArmor, + m_IGpgme_GetArmor, + m_IGpgme_SetTextmode, + m_IGpgme_GetTextmode, + m_IGpgme_SetPlaintext, + m_IGpgme_GetPlaintext, + m_IGpgme_SetCiphertext, + m_IGpgme_GetCiphertext, + m_IGpgme_ClearRecipients, + m_IGpgme_AddRecipient, + m_IGpgme_ResetSignKeys, + m_IGpgme_AddSignKey, + m_IGpgme_Encrypt, + m_IGpgme_Sign, + m_IGpgme_SignEncrypt, +/* m_IGpgme_SetKeylistMode, + * m_IGpgme_SetPassphraseCB, + * m_IGpgme_SetProgressCB, + * m_IGpgme_SignersClear, + * m_IGpgme_SignersAdd, + * m_IGpgme_SignersEnum, + * m_IGpgme_GetSigStatus, + * m_IGpgme_GetSigKey, + * m_IGpgme_GetNotation + */ +}; + + + +/*************************************************************** + ****************** Gpgme Factory **************************** + ***************************************************************/ + +static HRESULT WINAPI +m_GpgmeFactory_QueryInterface (IClassFactory *iface, + REFIID refiid, LPVOID *obj) +{ + ICOM_THIS (IClassFactoryImpl,iface); + + /*fprintf (stderr,"*** m_GpgmeFactory_QueryInterface(%p,%s)", + This, debugstr_guid(refiid));*/ + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IClassFactory, refiid) ) { + *obj = This; + /*fprintf (stderr," -> got %p\n", obj);*/ + return 0; + } + *obj = NULL; + /*fprintf (stderr," -> none\n");*/ + return E_NOINTERFACE; +} + +static ULONG WINAPI +m_GpgmeFactory_AddRef (IClassFactory *iface) +{ + ICOM_THIS(IClassFactoryImpl,iface); + return ++(This->ref); +} + +static ULONG WINAPI +m_GpgmeFactory_Release (IClassFactory *iface) +{ + ICOM_THIS(IClassFactoryImpl,iface); + return --(This->ref); +} + +static HRESULT WINAPI +m_GpgmeFactory_CreateInstance (IClassFactory *iface, IUnknown *outer, + REFIID refiid, LPVOID *r_obj ) +{ + /*ICOM_THIS(IClassFactoryImpl,iface);*/ + + fprintf (stderr,"*** m_GpgmeFactory_CreateInstance(%s)", + debugstr_guid(refiid) ); + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IGpgme, refiid) ) { + IGpgmeImpl *obj; + GpgmeCtx ctx; + GpgmeError err; + + + err = gpgme_new (&ctx); + if (err) { + fprintf (stderr," -> gpgme_new failed: %s\n", gpgme_strerror (err)); + return E_OUTOFMEMORY; + } + + obj = HeapAlloc (GetProcessHeap(), 0, sizeof *obj ); + if ( !obj) { + fprintf (stderr," -> out of core\n"); + gpgme_release (ctx); + return E_OUTOFMEMORY; + } + memset (obj, 0, sizeof *obj); + + ICOM_VTBL(obj) = &igpgme_vtbl; + obj->ref = 1; + obj->mainctx = ctx; + { /* Fixme: need to release some stuff on error */ + HRESULT hr; + ITypeLib *pTypeLib; + + hr = LoadRegTypeLib (&TLBID_Gpgcom, 1, 0, LANG_NEUTRAL, &pTypeLib); + if (hr) { + fprintf (stderr," -> LoadRegTypeLib failed: %lx\n", hr); + return hr; + } + hr = ITypeLib_GetTypeInfoOfGuid (pTypeLib, &IID_IGpgme, + &obj->std_disp.tinfo); + ITypeLib_Release (pTypeLib); + if (hr) { + fprintf (stderr," -> GetTypeInfoOfGuid failed: %lx\n", hr); + return hr; + } + hr = CreateStdDispatch ((IUnknown*)obj, obj, obj->std_disp.tinfo, + &obj->std_disp.disp); + if (hr) { + fprintf (stderr," -> CreateStdDispatch failed: %lx\n", hr); + return hr; + } + } + + *r_obj = obj; + fprintf (stderr," -> created %p\n", obj ); + return 0; + } + fprintf (stderr," -> no interface\n" ); + *r_obj = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI +m_GpgmeFactory_LockServer (IClassFactory *iface, BOOL dolock ) +{ + /*ICOM_THIS(IClassFactoryImpl,iface);*/ + return 0; +} + +static ICOM_VTABLE(IClassFactory) igpgme_factory_vtbl = { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + m_GpgmeFactory_QueryInterface, + m_GpgmeFactory_AddRef, + m_GpgmeFactory_Release, + m_GpgmeFactory_CreateInstance, + m_GpgmeFactory_LockServer +}; +static IClassFactoryImpl igpgme_CF = {&igpgme_factory_vtbl, 1 }; + + +IClassFactory * +igpgme_factory_new ( CLSID *r_clsid ) +{ + *r_clsid = CLSID_Gpgme; + IClassFactory_AddRef((IClassFactory*)&igpgme_CF); + return (IClassFactory*)&igpgme_CF; +} + +void +igpgme_factory_release ( IClassFactory *factory ) +{ + /* it's static - nothing to do */ +} |