Add a passphrase callback and minor changes to the interface
authorWerner Koch <wk@gnupg.org>
Tue, 12 Dec 2000 13:31:25 +0000 (13:31 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 12 Dec 2000 13:31:25 +0000 (13:31 +0000)
34 files changed:
README
complus/Makefile.am
complus/WINE-AUTHORS [new file with mode: 0644]
complus/WINE-LICENSE [new file with mode: 0644]
complus/basetsd.h [new file with mode: 0644]
complus/example.c [new file with mode: 0644]
complus/guiddef.h [new file with mode: 0644]
complus/ignupg.c [new file with mode: 0644]
complus/ignupg.h [new file with mode: 0644]
complus/main.c
complus/main.h
complus/obj_base.h [new file with mode: 0644]
complus/wtypes.h [new file with mode: 0644]
configure.in
gpgme/Makefile.am
gpgme/context.h
gpgme/data.c
gpgme/decrypt.c
gpgme/gpgme.c
gpgme/gpgme.h
gpgme/io.h
gpgme/ops.h
gpgme/posix-io.c
gpgme/rungpg.c
gpgme/rungpg.h
gpgme/sign.c
gpgme/status-table.h
gpgme/verify.c
gpgme/w32-io.c
gpgme/wait.c
tests/Makefile.am
tests/t-decrypt.c
tests/t-sign.c
tests/t-verify.c

diff --git a/README b/README
index 03cb718..080d6bc 100644 (file)
--- a/README
+++ b/README
@@ -9,7 +9,8 @@ http://www.gnupg.org/cvs-access.html .  If you use passphrases for
 your keys, you should get the gpg-agent which comes with the GnuPG
 unstable version (either CVS HEAD or
 ftp.gnupg.org/pub/gcrypt/alpha/gnupg/gnupg-1.1.2.tar.gz) and install
-the agent from the agent subdirectory.
+the agent from the agent subdirectory or use the new 
+gpgme_set_passphrase_cb() 
 
 Please subscribe to the gnupg-devel@gnupg.org mailing list if you want
 to do serious work. 
index 8976cd8..bbae8d5 100644 (file)
@@ -1,12 +1,17 @@
 ## Process this file with automake to produce Makefile.in
 
+EXTRA_DIST = WINE-LICENSE WINE-AUTHORS
+
 # No need to install this becuase we are cross-compiling anyway.
-noinst_PROGRAMS = gpgme
+noinst_PROGRAMS = gpgcom
 
 INCLUDES = -I$(top_srcdir)/jnlib
 LDADD = -L ../jnlib -ljnlib 
 
-gpgme_SOURCES = main.c main.h
+comheaders = obj_base.h basetsd.h guiddef.h  wtypes.h
 
+gpgcom_SOURCES = main.c main.h \
+               $(comheaders) \
+               ignupg.c ignupg.h 
 
 
diff --git a/complus/WINE-AUTHORS b/complus/WINE-AUTHORS
new file mode 100644 (file)
index 0000000..be51ca5
--- /dev/null
@@ -0,0 +1,331 @@
+@c This file is processed by GNU's TeXinfo
+@c If you modify it or move it to another location, make sure that
+@c TeXinfo works (type `make' in directory documentation).
+
+@c This is a list of the Wine authors and copyright holders.
+
+Wine is available thanks to the work of:
+James Abbatiello,
+Michael Abd-El-Malek,
+Howard Abrams,
+Mark G. Adams,
+Bruno Afonso,
+Samir Al-Battran,
+Guy Albertelli,
+Gustavo Junior Alves,
+Bob Amstadt,
+Dag Asheim,
+Jim Aston,
+Martin Ayotte,
+Viktor Babrian,
+Karl Backström,
+Bradley Baetz,
+Peter Bajusz,
+Andre Malafaya Baptista,
+Aaron Barnes,
+Jean-Claude Batista,
+Marcel Baur,
+Francis Beaudet,
+Tom Bech,
+Matthew Becker,
+Georg Beyerle,
+Ross Biro,
+Dennis Björklund,
+Zygo Blaxell,
+Martin Boehme,
+Francois Boisvert,
+Pim Bollen,
+Uwe Bonnes,
+Peter Bortas,
+Noel Borthwick,
+Erik Bos,
+Fons Botman,
+Sylvain Bouchard,
+Frederic Boulanger,
+Justin Bradford,
+John Brezak,
+Andrew Bulhak,
+John Burton,
+Jonathan Buzzard,
+Jose Marcos López Caravaca,
+Eddie Carpenter,
+Niels de Carpentier,
+Mike Castle,
+Ron Cemer,
+Gordon Chaffee,
+Gael de Chalendar,
+Jimen Ching,
+Geoff Clare,
+Robert 'Admiral' Coeyman,
+Richard Cohen,
+Jean-Claude Cote,
+Stephen Crowley,
+Pascal Cuoq,
+David A. Cuthbert,
+Brian Joseph Czapiga,
+Ulrich Czekalla,
+Huw D. M. Davies,
+Moses DeJong,
+Petar Djukic,
+Roman Dolejsi,
+Frans van Dorsselaer,
+Rikhardur Egilsson,
+Morten Eriksen,
+Chris Faherty,
+Carsten Fallesen,
+Paul Falstad,
+David Faure,
+Wesley Filardo,
+Claus Fischer,
+Olaf Flebbe,
+Chad Fraleigh,
+Matthew Francis,
+Philippe Froidevaux,
+Peter Galbavy,
+Peter Ganten,
+Ramon Garcia,
+Jeff Garzik,
+Julio Cesar Gazquez,
+Klaas van Gend,
+Abey George,
+Brian Gerst,
+Matthew Ghio,
+Jody Goldberg,
+David Golding,
+François Gouget,
+Hans de Graaff,
+David Grant,
+Albert den Haan,
+Jess Haas,
+Robert W Hall,
+Noomen Hamza,
+Charles M. Hannum,
+Adrian Harvey,
+John Harvey,
+James Hatheway,
+Kalevi J Hautaniemi,
+Bill Hawes,
+Lars Heete,
+Cameron Heide,
+Bernd Herd,
+Theodore S. Hetke,
+Haithem Hmida,
+Jochen Hoenicke,
+Henning Hoffmann,
+Kevin Holbrook,
+Nick Holloway,
+Onno Hovers,
+Jeffrey Hsu,
+Peter Hunnisett,
+Miguel de Icaza,
+Jukka Iivonen,
+Kostya Ivanov,
+Serge Ivanov,
+Lee Jaekil,
+Gautam Jain,
+Niels Kristian Bech Jensen,
+Rajeev Jhangiani,
+Bill Jin,
+Jeff Johann,
+Alexandre Julliard,
+Bang Jun-Young,
+James Juran,
+Achim Kaiser,
+Alexander Kanavin,
+Jukka Kangas,
+Pavel Kankovsky,
+Michael Karcher,
+Niclas Karlsson,
+Jochen Karrer,
+Don Kelly,
+Andreas Kirschbaum,
+Rein Klazes,
+Albrecht Kleine,
+Dietmar Kling,
+Eric Kohl,
+Jon Konrath,
+Alex Korobka,
+Zoltan Kovacs,
+Greg Kreider,
+Anand Kumria,
+Ove Kåven,
+Scott A. Laird,
+David Lee Lambert,
+Stephen Langasek,
+Sean Langley,
+Dan Langlois,
+Alexander Larsson,
+David Lassonde,
+Stefan Leichter,
+Karl Lessard,
+Pascal Lessard,
+Andrew Lewycky,
+John Li,
+Weisheng Li,
+Xiang Li,
+Per Lindström,
+Brian Litzinger,
+Juergen Lock,
+Martin von Loewis,
+Michiel van Loon,
+Richard A Lough,
+Alexander V. Lukyanov,
+Jiuming Luo,
+Stephane Lussier,
+David Luyer,
+José Marcos López,
+Kenneth MacDonald,
+Peter MacDonald,
+Pierre Mageau,
+William Magro,
+Juergen Marquardt,
+Ricardo Massaro,
+Keith Matthews,
+Joerg Mayer,
+Michael McCormack,
+Jason McMullan,
+Caolan McNamara,
+Marcus Meissner,
+Graham Menhennitt,
+David Metcalfe,
+Toufic Milan,
+Paul Millar,
+Bruce Milner,
+Steffen Moeller,
+Andreas Mohr,
+Slava Monich,
+James Moody,
+Chris Morgan,
+Kai Morich,
+Richard Mortimer,
+Vasudev Mulchandani,
+Rick Mutzke,
+Philippe De Muyter,
+Itai Nahshon,
+Jonathan Naylor,
+Tim Newsome,
+Thuy Nguyen,
+Kristian Nielsen,
+Damien O'Neill,
+Henrik Olsen,
+Gerard Patel,
+Michael Patra,
+Murali Pattathe,
+Dimitrie O. Paun,
+Bernd Paysan,
+Brad Pepers,
+Jim Peterson,
+Gerald Pfeifer,
+Dave Pickles,
+Ian Pilcher,
+Brian Pirie,
+Michael Poole,
+Eric Pouech,
+Robert Pouliot,
+Vahid Pourlotfali,
+Chad Powell,
+Joseph Pranevich,
+Alex Priem,
+Paul Quinn,
+Pete Ratzlaff,
+Ron Record,
+Petter Reinholdtsen,
+Keith Reynolds,
+Slaven Rezic,
+John Richardson,
+Rick Richardson,
+Douglas Ridgway,
+Robert Riggs,
+Bernhard Rosenkraenzer,
+Matthew Robertson,
+Pavel Roskin,
+Herbert Rosmanith,
+Lilia Roumiantseva,
+Johannes Ruscheinski,
+Adam Sacarny,
+Ivan de Saedeleer,
+Thomas Sandford,
+Constantine Sapuntzakis,
+Pablo Saratxaga,
+Carl van Schaik,
+Daniel Schepler,
+Christian Schlaile,
+Peter Schlaile,
+Ulrich Schmid,
+Bernd Schmidt,
+Ian Schmidt,
+Juergen Schmied,
+Ingo Schneider,
+Victor Schneider,
+John Sheets,
+Yngvi Sigurjonsson,
+Stephen Simmons,
+Jesper Skov,
+Rick Sladkey,
+William Smith,
+Jaroslaw Piotr Sobieszek,
+Patrick Spinler,
+Sylvain St-Germain,
+Gavriel State,
+Sheri Steeves,
+Norman Stevens,
+Dominik Strasser,
+Patrik Stridvall,
+Vadim Strizhevsky,
+Bertho Stultiens,
+Abraham Sudhakar,
+Charles Suprin,
+James Sutherland,
+Erik Svendsen,
+Tristan Tarrant,
+Andrew Taylor,
+Joshua Thielen,
+Dirk Thierbach,
+Jean-Louis Thirot,
+Duncan C Thomson,
+Adrian Thurston,
+Goran Thyni,
+Steve Tibbett,
+Dmitry Timoshkov,
+Jimmy Tirtawangsa,
+Jon Tombs,
+Linus Torvalds,
+Luc Tourangeau,
+Jeff Tranter,
+Gregory Trubetskoy,
+Petri Tuomola,
+Sergey Turchanov,
+Lionel Ulmer,
+Moshe Vainer,
+Michael Veksler,
+Sven Verdoolaege,
+Todd Vierling,
+Erez Volk,
+Jerome Vouillon,
+Duc Vuong,
+Ronan Waide,
+Martin Walker,
+Owen Wang,
+Eric Warnke,
+Leigh Wedding,
+Randy Weems,
+Manfred Weichel,
+Ulrich Weigand,
+Morten Welinder,
+Jeremy White,
+Len White,
+Lawson Whitney,
+Jan Willamowius,
+Carl Williams,
+Eric Williams,
+Cliff Wright,
+Karl Guenter Wuensch,
+Eric Youngdale,
+James Youngman,
+Nikita V. Youshchenko,
+Mikolaj Zalewski,
+John Zero,
+Yuxi Zhang,
+Nathan Zorich,
+Luiz Otavio L. Zorzella,
+and Per Ångström.
diff --git a/complus/WINE-LICENSE b/complus/WINE-LICENSE
new file mode 100644 (file)
index 0000000..f3478fe
--- /dev/null
@@ -0,0 +1,26 @@
+This is the license file as it appeared in the CVS version of 
+Wine at cvs@rhlx01.fht-esslingen.de:/home/wine as of 2000-12-04 
+where only AUTHORS has been renamed to WINE-AUTHORS.  It applies
+to the header files establishing the COM+ framework
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
+for a complete list)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/complus/basetsd.h b/complus/basetsd.h
new file mode 100644 (file)
index 0000000..866c9b8
--- /dev/null
@@ -0,0 +1,160 @@
+/* basetsd.h -  Compilers that uses ILP32, LP64 or P64 type models
+                for both Win32 and Win64 are supported by this file.
+
+ Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
+ for a complete list)
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __WINE_BASETSD_H
+#define __WINE_BASETSD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+/*
+ * Win32 was easy to implement under Unix since most (all?) 32-bit
+ * Unices uses the same type model (ILP32) as Win32, where int, long
+ * and pointer are 32-bit.
+ *
+ * Win64, however, will cause some problems when implemented under Unix.
+ * Linux/{Alpha, Sparc64} and most (all?) other 64-bit Unices uses
+ * the LP64 type model where int is 32-bit and long and pointer are
+ * 64-bit. Win64 on the other hand uses the P64 (sometimes called LLP64)
+ * type model where int and long are 32 bit and pointer is 64-bit.
+ */
+
+/* Type model indepent typedefs */
+
+typedef char          __int8;
+typedef unsigned char __uint8;
+
+typedef short          __int16;
+typedef unsigned short __uint16;
+
+typedef int          __int32;
+typedef unsigned int __uint32;
+
+typedef long long          __int64;
+typedef unsigned long long __uint64;
+
+#if defined(_WIN64)
+
+typedef __uint32 __ptr32;
+typedef void    *__ptr64;
+
+#else /* FIXME: defined(_WIN32) */
+
+typedef void    *__ptr32;
+typedef __uint64 __ptr64;
+
+#endif
+
+/* Always signed and 32 bit wide */
+
+typedef __int32 LONG32;
+typedef __int32 INT32;
+
+typedef LONG32 *PLONG32;
+typedef INT32  *PINT32;
+
+/* Always unsigned and 32 bit wide */
+
+typedef __uint32 ULONG32;
+typedef __uint32 DWORD32;
+typedef __uint32 UINT32;
+
+typedef ULONG32 *PULONG32;
+typedef DWORD32 *PDWORD32;
+typedef UINT32  *PUINT32;
+
+/* Always signed and 64 bit wide */
+
+typedef __int64 LONG64;
+typedef __int64 INT64;
+
+typedef LONG64 *PLONG64;
+typedef INT64  *PINT64;
+
+/* Always unsigned and 64 bit wide */
+
+typedef __uint64 ULONG64;
+typedef __uint64 DWORD64;
+typedef __uint64 UINT64;
+
+typedef ULONG64 *PULONG64;
+typedef DWORD64 *PDWORD64;
+typedef UINT64  *PUINT64;
+
+/* Win32 or Win64 dependent typedef/defines. */
+
+#ifdef _WIN64
+
+typedef __int64 INT_PTR, *PINT_PTR;
+typedef __uint64 UINT_PTR, *PUINT_PTR;
+
+#define MAXINT_PTR 0x7fffffffffffffff
+#define MININT_PTR 0x8000000000000000
+#define MAXUINT_PTR 0xffffffffffffffff
+
+typedef __int32 HALF_PTR, *PHALF_PTR;
+typedef __int32 UHALF_PTR, *PUHALF_PTR;
+
+#define MAXHALF_PTR 0x7fffffff
+#define MINHALF_PTR 0x80000000
+#define MAXUHALF_PTR 0xffffffff
+
+typedef __int64 LONG_PTR, *PLONG_PTR;
+typedef __uint64 ULONG_PTR, *PULONG_PTR;
+typedef __uint64 DWORD_PTR, *PDWORD_PTR;
+
+#else /* FIXME: defined(_WIN32) */
+
+typedef __int32 INT_PTR, *PINT_PTR;
+typedef __uint32 UINT_PTR, *PUINT_PTR;
+
+#define MAXINT_PTR 0x7fffffff
+#define MININT_PTR 0x80000000
+#define MAXUINT_PTR 0xffffffff
+
+typedef __int16 HALF_PTR, *PHALF_PTR;
+typedef __uint16 UHALF_PTR, *PUHALF_PTR;
+
+#define MAXUHALF_PTR 0xffff
+#define MAXHALF_PTR 0x7fff
+#define MINHALF_PTR 0x8000
+
+typedef __int32 LONG_PTR, *PLONG_PTR;
+typedef __uint32 ULONG_PTR, *PULONG_PTR;
+typedef __uint32 DWORD_PTR, *PDWORD_PTR;
+
+#endif /* defined(_WIN64) || defined(_WIN32) */
+
+typedef INT_PTR SSIZE_T, *PSSIZE_T;
+typedef UINT_PTR SIZE_T, *PSIZE_T;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* !defined(__WINE_BASETSD_H) */
+
+
+
diff --git a/complus/example.c b/complus/example.c
new file mode 100644 (file)
index 0000000..a7d838d
--- /dev/null
@@ -0,0 +1,598 @@
+/*                                
+ * Copyright 1999 Marcus Meissner
+ */
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "winbase.h"
+#include "winnls.h"
+#include "mmsystem.h"
+#include "winerror.h"
+#include "debugtools.h"
+
+#include "initguid.h"
+#include "vfw.h"
+
+DEFAULT_DEBUG_CHANNEL(avifile);
+
+static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
+static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
+static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
+static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
+static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
+static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
+static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
+static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
+static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
+static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
+
+struct ICOM_VTABLE(IAVIFile) iavift = {
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IAVIFile_fnQueryInterface,
+    IAVIFile_fnAddRef,
+    IAVIFile_fnRelease,
+    IAVIFile_fnInfo,
+    IAVIFile_fnGetStream,
+    IAVIFile_fnCreateStream,
+    IAVIFile_fnWriteData,
+    IAVIFile_fnReadData,
+    IAVIFile_fnEndRecord,
+    IAVIFile_fnDeleteStream
+};
+
+static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
+static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface);
+static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface);
+static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
+static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
+static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
+static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
+static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
+static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
+static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
+static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
+static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
+static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
+static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
+
+struct ICOM_VTABLE(IAVIStream) iavist = {
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IAVIStream_fnQueryInterface,
+    IAVIStream_fnAddRef,
+    IAVIStream_fnRelease,
+    IAVIStream_fnCreate,
+    IAVIStream_fnInfo,
+    IAVIStream_fnFindSample,
+    IAVIStream_fnReadFormat,
+    IAVIStream_fnSetFormat,
+    IAVIStream_fnRead,
+    IAVIStream_fnWrite,
+    IAVIStream_fnDelete,
+    IAVIStream_fnReadData,
+    IAVIStream_fnWriteData,
+    IAVIStream_fnSetInfo
+};
+
+typedef struct IAVIStreamImpl {
+       /* IUnknown stuff */
+       ICOM_VFIELD(IAVIStream);
+       DWORD           ref;
+       /* IAVIStream stuff */
+       LPVOID          lpInputFormat;
+       DWORD           inputformatsize;
+       BOOL            iscompressing;
+       DWORD           curframe;
+
+           /* Compressor stuff */
+           HIC hic;
+           LPVOID      lpCompressFormat;
+           ICINFO      icinfo;
+           DWORD       compbufsize;
+           LPVOID      compbuffer;
+
+           DWORD       decompbufsize;
+           LPVOID      decompbuffer;
+           LPVOID      decompformat;
+           AVICOMPRESSOPTIONS  aco;
+
+           LPVOID      lpPrev; /* pointer to decompressed frame later */
+           LPVOID      lpPrevFormat; /* pointer to decompressed info later */
+} IAVIStreamImpl;
+
+/***********************************************************************
+ *             AVIFileInit
+ */
+void WINAPI
+AVIFileInit(void) {
+       FIXME("(),stub!\n");
+}
+
+typedef struct IAVIFileImpl {
+       /* IUnknown stuff */
+       ICOM_VFIELD(IAVIFile);
+       DWORD                           ref;
+       /* IAVIFile stuff... */
+} IAVIFileImpl;
+
+static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
+       ICOM_THIS(IAVIFileImpl,iface);
+
+       TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
+       if (    !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
+               !memcmp(&IID_IAVIFile,refiid,sizeof(IID_IAVIFile))
+       ) {
+               *obj = iface;
+               return S_OK;
+       }
+       return OLE_E_ENUM_NOMORE;
+}
+
+static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
+       ICOM_THIS(IAVIFileImpl,iface);
+       
+       FIXME("(%p)->AddRef()\n",iface);
+       return ++(This->ref);
+}
+
+static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
+       ICOM_THIS(IAVIFileImpl,iface);
+       
+       FIXME("(%p)->Release()\n",iface);
+       if (!--(This->ref)) {
+               HeapFree(GetProcessHeap(),0,iface);
+               return 0;
+       }
+       return This->ref;
+}
+
+static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size) {
+       FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
+
+       /* FIXME: fill out struct? */
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
+       FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
+       /* FIXME: create interface etc. */
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
+       ICOM_THIS(IAVIStreamImpl,iface);
+       char            fcc[5];
+       IAVIStreamImpl  *istream;
+
+       FIXME("(%p,%p,%p)\n",This,avis,asi);
+       istream = (IAVIStreamImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIStreamImpl));
+       istream->ref = 1;
+       ICOM_VTBL(istream) = &iavist;
+       fcc[4]='\0';
+       memcpy(fcc,(char*)&(asi->fccType),4);
+       FIXME("\tfccType '%s'\n",fcc);
+       memcpy(fcc,(char*)&(asi->fccHandler),4);
+       FIXME("\tfccHandler '%s'\n",fcc);
+       FIXME("\tdwFlags 0x%08lx\n",asi->dwFlags);
+       FIXME("\tdwCaps 0x%08lx\n",asi->dwCaps);
+       FIXME("\tname '%s'\n",debugstr_w(asi->szName));
+
+       istream->curframe = 0;
+       *avis = (PAVISTREAM)istream;
+       return S_OK;
+}
+
+static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size) {
+       FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,ckid,lpData,size);
+       /* FIXME: write data to file */
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size) {
+       FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,ckid,lpData,size);
+       /* FIXME: read at most size bytes from file */
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface) {
+       FIXME("(%p)->EndRecord()\n",iface);
+       /* FIXME: end record? */
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam) {
+       FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",iface,fccType,lParam);
+       /* FIXME: delete stream? */
+       return E_FAIL;
+}
+
+/***********************************************************************
+ *             AVIFileOpenA
+ */
+HRESULT WINAPI AVIFileOpenA(
+       PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
+) {
+       IAVIFileImpl    *iavi;
+
+       FIXME("(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,debugstr_guid(lpHandler));
+       iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
+       iavi->ref = 1;
+       ICOM_VTBL(iavi) = &iavift;
+       *ppfile = (LPVOID)iavi;
+       return S_OK;
+}
+
+static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
+       ICOM_THIS(IAVIStreamImpl,iface);
+
+       TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
+       if (    !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
+               !memcmp(&IID_IAVIStream,refiid,sizeof(IID_IAVIStream))
+       ) {
+               *obj = This;
+               return S_OK;
+       }
+       /* can return IGetFrame interface too */
+       return OLE_E_ENUM_NOMORE;
+}
+
+static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
+       ICOM_THIS(IAVIStreamImpl,iface);
+       
+       FIXME("(%p)->AddRef()\n",iface);
+       return ++(This->ref);
+}
+
+static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
+       ICOM_THIS(IAVIStreamImpl,iface);
+       
+       FIXME("(%p)->Release()\n",iface);
+       if (!--(This->ref)) {
+               HeapFree(GetProcessHeap(),0,This);
+               return 0;
+       }
+       return This->ref;
+}
+
+static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
+       FIXME("(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
+       FIXME("(%p)->Info(%p,%ld)\n",iface,psi,size);
+       return E_FAIL;
+}
+
+static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
+       FIXME("(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
+       FIXME("(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
+       return E_FAIL;
+}
+
+/***********************************************************************
+ *             IAVIStream::SetFormat
+ */
+static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
+       IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
+
+       FIXME("(%p)->SetFormat(%ld,%p,%ld)\n",iface,pos,format,formatsize);
+       if (as->lpInputFormat) HeapFree(GetProcessHeap(),0,as->lpInputFormat);
+       as->inputformatsize = formatsize;
+       as->lpInputFormat = HeapAlloc(GetProcessHeap(),0,formatsize);
+       memcpy(as->lpInputFormat,format,formatsize);
+       if (as->iscompressing) {
+               int     xsize; 
+               /* Set up the Compressor part */
+               xsize = ICCompressGetFormatSize(as->hic,as->lpInputFormat);
+               as->lpCompressFormat = HeapAlloc(GetProcessHeap(),0,xsize);
+               ICCompressGetFormat(as->hic,as->lpInputFormat,as->lpCompressFormat);
+               ICCompressBegin(as->hic,as->lpInputFormat,as->lpCompressFormat);
+               as->compbufsize = ICCompressGetSize(as->hic,as->lpInputFormat,as->lpCompressFormat);
+               as->compbuffer = HeapAlloc(GetProcessHeap(),0,as->compbufsize);
+
+               /* Set up the Decompressor part (for prev frames?) */
+               xsize=ICDecompressGetFormatSize(as->hic,as->lpCompressFormat);
+               as->decompformat = HeapAlloc(GetProcessHeap(),0,xsize);
+               ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
+               as->decompbufsize=((LPBITMAPINFOHEADER)as->decompbuffer)->biSizeImage;
+               as->decompbuffer = HeapReAlloc(GetProcessHeap(),0,as->decompbuffer,as->decompbufsize);
+               memset(as->decompbuffer,0xff,as->decompbufsize);
+               assert(HeapValidate(GetProcessHeap(),0,NULL));
+
+               ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
+               ICDecompressBegin(as->hic,as->lpCompressFormat,as->decompformat);
+               as->lpPrev = as->lpPrevFormat = NULL;
+       }
+       return S_OK;
+}
+
+static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
+       FIXME("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
+       IAVIStreamImpl  *as = (IAVIStreamImpl*)iface;
+       DWORD           ckid,xflags;
+
+       FIXME("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
+
+       ICCompress(
+               as->hic,flags,
+               as->lpCompressFormat,
+               as->compbuffer,
+               as->lpInputFormat,buffer,
+               &ckid,&xflags,
+               as->curframe,0xffffff/*framesize*/,as->aco.dwQuality,
+               as->lpPrevFormat,as->lpPrev
+       );
+       ICDecompress(
+               as->hic,
+               flags,  /* FIXME: check */
+               as->lpCompressFormat,
+               as->compbuffer,
+               as->decompformat,
+               as->decompbuffer
+       );
+       /* We now have a prev format for the next compress ... */
+       as->lpPrevFormat = as->decompformat;
+       as->lpPrev = as->decompbuffer;
+       return S_OK;
+}
+
+static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
+       FIXME("(%p)->Delete(%ld,%ld)\n",iface,start,samples);
+       return E_FAIL;
+}
+static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
+       FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
+       FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
+       return E_FAIL;
+}
+
+static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
+       FIXME("(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
+       return E_FAIL;
+}
+
+/***********************************************************************
+ *             AVIFileCreateStreamA
+ */
+HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE iface,PAVISTREAM *ppavi,AVISTREAMINFOA * psi) {
+       AVISTREAMINFOW  psiw;
+       
+       /* Only the szName at the end is different */
+       memcpy(&psiw,psi,sizeof(*psi)-sizeof(psi->szName));
+        MultiByteToWideChar( CP_ACP, 0, psi->szName, -1,
+                             psiw.szName, sizeof(psiw.szName) / sizeof(WCHAR) );
+       return IAVIFile_CreateStream(iface,ppavi,&psiw);
+}
+
+/***********************************************************************
+ *             AVIFileCreateStreamW
+ */
+HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
+       return IAVIFile_CreateStream(iface,avis,asi);
+}
+
+
+/***********************************************************************
+ *             AVIFileGetStream
+ */
+HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
+       return IAVIFile_GetStream(iface,avis,fccType,lParam);
+}
+
+/***********************************************************************
+ *             AVIFileInfoA
+ */
+HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
+       AVIFILEINFOW    afiw;
+       HRESULT         hres;
+
+       if (size < sizeof(AVIFILEINFOA))
+               return AVIERR_BADSIZE;
+       hres = IAVIFile_Info(iface,&afiw,sizeof(afiw));
+       memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
+        WideCharToMultiByte( CP_ACP, 0, afiw.szFileType, -1,
+                             afi->szFileType, sizeof(afi->szFileType), NULL, NULL );
+        afi->szFileType[sizeof(afi->szFileType)-1] = 0;
+       return hres;
+}
+
+/***********************************************************************
+ *             AVIStreamInfoW
+ */
+HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
+ size) {
+       return IAVIFile_Info(iface,asi,size);
+}
+
+/***********************************************************************
+ *             AVIStreamInfoA
+ */
+HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
+ size) {
+       AVISTREAMINFOW  asiw;
+       HRESULT                 hres;
+
+       if (size<sizeof(AVISTREAMINFOA))
+               return AVIERR_BADSIZE;
+       hres = IAVIFile_Info(iface,&asiw,sizeof(asiw));
+       memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
+        WideCharToMultiByte( CP_ACP, 0, asiw.szName, -1,
+                             asi->szName, sizeof(asi->szName), NULL, NULL );
+        asi->szName[sizeof(asi->szName)-1] = 0;
+       return hres;
+}
+
+/***********************************************************************
+ *             AVIFileInfoW
+ */
+HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
+       return IAVIFile_Info(iface,afi,size);
+}
+
+/***********************************************************************
+ *             AVIMakeCompressedStream
+ */
+HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
+       char                    fcc[5];
+       IAVIStreamImpl  *as;
+       FIXME("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
+       fcc[4]='\0';
+       memcpy(fcc,&(aco->fccType),4);
+       FIXME("\tfccType: '%s'\n",fcc);
+       memcpy(fcc,&(aco->fccHandler),4);
+       FIXME("\tfccHandler: '%s'\n",fcc);
+       FIXME("\tdwFlags: 0x%08lx\n",aco->dwFlags);
+
+       /* we just create a duplicate for now */
+       IAVIStream_AddRef(ppsSource);
+       *ppsCompressed = ppsSource;
+       as = (IAVIStreamImpl*)ppsSource;
+
+       /* this is where the fun begins. Open a compressor and prepare it. */
+       as->hic = ICOpen(aco->fccType,aco->fccHandler,ICMODE_COMPRESS);
+
+       /* May happen. for instance if the codec is not able to compress */
+       if (!as->hic) 
+               return AVIERR_UNSUPPORTED;
+
+       ICGetInfo(as->hic,&(as->icinfo),sizeof(ICINFO));
+       FIXME("Opened compressor: '%s' '%s'\n",debugstr_w(as->icinfo.szName),debugstr_w(as->icinfo.szDescription));
+       as->iscompressing = TRUE;
+       memcpy(&(as->aco),aco,sizeof(*aco));
+       if (as->icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
+               ICCOMPRESSFRAMES        icf;
+
+               /* now what to fill in there ... Hmm */
+               memset(&icf,0,sizeof(icf));
+               icf.lDataRate   = aco->dwBytesPerSecond;
+               icf.lQuality    = aco->dwQuality;
+               icf.lKeyRate    = aco->dwKeyFrameEvery;
+
+               icf.GetData = (void *)0xdead4242;
+               icf.PutData = (void *)0xdead4243;
+               ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
+       }
+       return S_OK;
+}
+
+/***********************************************************************
+ *             AVIStreamSetFormat
+ */
+HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
+       return IAVIStream_SetFormat(iface,pos,format,formatsize);
+}
+
+/***********************************************************************
+ *             AVIStreamReadFormat
+ */
+HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
+       return IAVIStream_ReadFormat(iface,pos,format,formatsize);
+}
+
+/***********************************************************************
+ *             AVIStreamWrite(
+ */
+HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
+       return IAVIStream_Write(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
+}
+
+/***********************************************************************
+ *             AVIStreamRead
+ */
+HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
+       return IAVIStream_Read(iface,start,samples,buffer,buffersize,bytesread,samplesread);
+}
+
+/***********************************************************************
+ *             AVIStreamWriteData
+ */
+HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
+       return IAVIStream_WriteData(iface,fcc,lp,size);
+}
+
+/***********************************************************************
+ *             AVIStreamReadData
+ */
+HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
+       return IAVIStream_ReadData(iface,fcc,lp,lpread);
+}
+
+/***********************************************************************
+ *             AVIStreamStart
+ */
+LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
+       AVISTREAMINFOW  si;
+
+       IAVIStream_Info(iface,&si,sizeof(si));
+       return si.dwStart;
+}
+
+/***********************************************************************
+ *             AVIStreamLength
+ */
+LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
+       AVISTREAMINFOW  si;
+       HRESULT                 ret;
+
+       ret = IAVIStream_Info(iface,&si,sizeof(si));
+       if (ret) /* error */
+               return 1;
+       return si.dwLength;
+}
+
+/***********************************************************************
+ *             AVIStreamRelease
+ */
+ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
+       return IAVIStream_Release(iface);
+}
+
+/***********************************************************************
+ *             AVIStreamGetFrameOpen
+ */
+PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
+       FIXME("(%p)->(%p),stub!\n",iface,bmi);
+       return NULL;
+}
+
+/***********************************************************************
+ *             AVIStreamGetFrame
+ */
+LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
+       return IGetFrame_GetFrame(pg,pos);
+}
+
+/***********************************************************************
+ *             AVIStreamGetFrameClose
+ */
+HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
+       if (pg) IGetFrame_Release(pg);
+       return 0;
+}
+
+/***********************************************************************
+ *             AVIFileRelease
+ */
+ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
+       return IAVIFile_Release(iface);
+}
+
+/***********************************************************************
+ *             AVIFileExit
+ */
+void WINAPI AVIFileExit(void) {
+       FIXME("(), stub.\n");
+}
diff --git a/complus/guiddef.h b/complus/guiddef.h
new file mode 100644 (file)
index 0000000..b329dad
--- /dev/null
@@ -0,0 +1,95 @@
+/* guiddef.h 
+
+ Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
+ for a complete list)
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* already defined bu Mingw32/cpd
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+    unsigned long  Data1;
+    unsigned short Data2;
+    unsigned short Data3;
+    unsigned char  Data4[ 8 ];
+} GUID;
+#endif
+*/
+
+#undef DEFINE_GUID
+
+#ifdef INITGUID
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+        const GUID name = \
+       { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
+#else
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+    extern const GUID name
+#endif
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+       DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+#ifndef _GUIDDEF_H_
+#define _GUIDDEF_H_
+
+/*   typedef GUID *LPGUID;
+     typedef GUID CLSID,*LPCLSID; */
+typedef GUID IID,*LPIID;
+typedef GUID FMTID,*LPFMTID;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+#define REFGUID             const GUID &
+#define REFCLSID            const CLSID &
+#define REFIID              const IID &
+#define REFFMTID            const FMTID &
+#else /* !defined(__cplusplus) && !defined(CINTERFACE) */
+#define REFGUID             const GUID* const
+#define REFCLSID            const CLSID* const
+#define REFIID              const IID* const
+#define REFFMTID            const FMTID* const
+#endif /* !defined(__cplusplus) && !defined(CINTERFACE) */
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+#define IsEqualGUID(rguid1, rguid2) (!memcmp(&(rguid1), &(rguid2), sizeof(GUID)))
+#else /* defined(__cplusplus) && !defined(CINTERFACE) */
+#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
+#endif /* defined(__cplusplus) && !defined(CINTERFACE) */
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+inline bool operator==(const GUID& guidOne, const GUID& guidOther)
+{
+    return !memcmp(&guidOne,&guidOther,sizeof(GUID));
+}
+inline bool operator!=(const GUID& guidOne, const GUID& guidOther)
+{
+    return !(guidOne == guidOther);
+}
+#endif 
+
+extern const IID GUID_NULL;
+#define IID_NULL            GUID_NULL
+#define CLSID_NULL GUID_NULL
+#define FMTID_NULL          GUID_NULL
+   
+#endif /* _GUIDDEF_H_ */
diff --git a/complus/ignupg.c b/complus/ignupg.c
new file mode 100644 (file)
index 0000000..009d5db
--- /dev/null
@@ -0,0 +1,202 @@
+/* ignupg.c - COM+ class IGnuPG
+ *     Copyright (C) 2000 Werner Koch (dd9jn)
+ *
+ * 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>
+
+#define INITGUID
+#include "ignupg.h"
+
+/*
+ * Declare the interface implementation structures
+ */
+typedef struct IGnuPGImpl IGnuPGImpl;
+typedef struct IClassFactoryImpl IClassFactoryImpl;
+
+
+struct IGnuPGImpl {
+    /* IUnknown required stuff */
+    ICOM_VFIELD (IGnuPG);
+    DWORD       ref;
+    /* Our stuff */
+    int foo;
+};
+
+
+struct IClassFactoryImpl {
+    /* IUnknown fields */
+    ICOM_VFIELD(IClassFactory);
+    DWORD       ref;
+};
+
+
+
+/**********************************************************
+ **************  IGnuPG Implementation  *******************
+ **********************************************************/
+
+static HRESULT WINAPI
+IGnuPGImpl_QueryInterface (IGnuPG *iface, REFIID refiid, LPVOID *obj)
+{
+    ICOM_THIS (IGnuPGImpl,iface);
+
+    fprintf (stderr,"(%p)->QueryInterface(%s,%p)\n",
+             This, "debugstr_guid(refiid)", obj);
+    if ( IsEqualGUID (&IID_IUnknown, refiid)
+         || !IsEqualGUID (&IID_IGnuPG, refiid) ) {
+        *obj = iface;
+        return 0;
+    }
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+
+static ULONG WINAPI
+IGnuPGImpl_AddRef (IGnuPG *iface)
+{
+    ICOM_THIS (IGnuPGImpl,iface);
+       
+    return ++This->ref;
+}
+
+
+static ULONG WINAPI
+IGnuPGImpl_Release (IGnuPG *iface)
+{
+    ICOM_THIS (IGnuPGImpl,iface);
+       
+    if (--This->ref)
+        return This->ref;
+
+    HeapFree(GetProcessHeap(),0,iface);
+    return 0;
+}
+
+
+
+
+static ICOM_VTABLE(IGnuPG) gnupg_vtbl = 
+{
+    /* IUnknow methods */
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    IGnuPGImpl_QueryInterface,
+    IGnuPGImpl_AddRef,
+    IGnuPGImpl_Release,
+    /* Our methods */
+
+};
+
+
+
+/***************************************************************
+ ******************  GnuPG Factory  ****************************
+ ***************************************************************/
+
+static HRESULT WINAPI 
+GnuPGFactory_QueryInterface (IClassFactory *iface, REFIID refiid, LPVOID *obj)
+{
+    /*ICOM_THIS(IClassFactoryImpl,iface);*/
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+GnuPGFactory_AddRef (IClassFactory *iface)
+{
+    ICOM_THIS(IClassFactoryImpl,iface);
+    return ++(This->ref);
+}
+
+static ULONG WINAPI
+GnuPGFactory_Release (IClassFactory *iface)
+{
+    ICOM_THIS(IClassFactoryImpl,iface);
+    return --(This->ref);
+}
+
+static HRESULT WINAPI
+GnuPGFactory_CreateInstance (IClassFactory *iface, IUnknown *outer,
+                             REFIID refiid, LPVOID *r_obj )
+{
+    /*ICOM_THIS(IClassFactoryImpl,iface);*/
+
+    if ( IsEqualGUID (&IID_IGnuPG, refiid) ) {
+       IGnuPGImpl *obj;
+
+       obj = HeapAlloc (GetProcessHeap(), 0, sizeof *obj );
+       if ( !obj)
+            return E_OUTOFMEMORY;
+
+       ICOM_VTBL(obj) = &gnupg_vtbl;
+       obj->ref = 1;
+        *r_obj = obj;
+       return 0;
+    }
+    *r_obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI
+GnuPGFactory_LockServer (IClassFactory *iface, BOOL dolock )
+{
+    /*ICOM_THIS(IClassFactoryImpl,iface);*/
+    return 0;
+}
+
+static ICOM_VTABLE(IClassFactory) gnupg_factory_vtbl = {
+    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+    GnuPGFactory_QueryInterface,
+    GnuPGFactory_AddRef,
+    GnuPGFactory_Release,
+    GnuPGFactory_CreateInstance,
+    GnuPGFactory_LockServer
+};
+static IClassFactoryImpl GnuPG_CF = {&gnupg_factory_vtbl, 1 };
+
+
+IClassFactory *
+gnupg_factory_new ( CLSID *r_clsid )
+{
+    *r_clsid = CLSID_GnuPG;
+    IClassFactory_AddRef((IClassFactory*)&GnuPG_CF);
+    return (IClassFactory*)&GnuPG_CF;
+}
+
+void
+gnupg_factory_release ( IClassFactory *factory )
+{
+    /* it's static - nothing to do */
+}
+
+
+
+
+
+
+
+
+
diff --git a/complus/ignupg.h b/complus/ignupg.h
new file mode 100644 (file)
index 0000000..e9cf9a6
--- /dev/null
@@ -0,0 +1,68 @@
+/* ignupg.h - COM+ class IGnuPG
+ *     Copyright (C) 2000 Werner Koch (dd9jn)
+ *
+ * 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
+ */
+
+#ifndef IGNUPG_H
+#define IGNUPG_H 1
+
+#include "obj_base.h"
+
+DEFINE_GUID(CLSID_GnuPG,      0x42424242, 0x62e8, 0x11cf,
+                              0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+DEFINE_GUID(IID_IGnuPG,       0x24242424, 0x4981, 0x11CE,
+                              0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
+typedef struct IGnuPG IGnuPG;
+
+
+
+#define ICOM_INTERFACE IGnuPG
+
+#define IGnuPG_METHODS \
+    ICOM_METHOD1(HRESULT,Initialize,    REFIID,) \
+    ICOM_METHOD1(HRESULT,EnumDevices,   LPVOID,) 
+
+#define IGnuPG_IMETHODS \
+    IUnknown_IMETHODS \
+    IGnuPG_METHODS
+
+ICOM_DEFINE(IGnuPG,IUnknown)
+#undef ICOM_INTERFACE
+
+
+/*** IUnknown methods ***/
+#define IGnuPG_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IGnuPG_AddRef(p)             ICOM_CALL (AddRef,p)
+#define IGnuPG_Release(p)            ICOM_CALL (Release,p)
+/*** IGnuPG methods ***/
+#define IGnuPG_Initialize(p,a)       ICOM_CALL1(Initialize,p,a)
+#define IGnuPG_EnumDevices(p,a,b)    ICOM_CALL2(EnumDevice,p,a,b)
+
+
+#endif /*IGNUPG_H*/
+
+
+
+
+
+
+
+
+
+
+
index 221a66b..519d2bc 100644 (file)
@@ -28,6 +28,8 @@
 #include <time.h>
 #include <windows.h>
 
+#include "obj_base.h"
+
 #include "argparse.h"
 
 #include "main.h"
@@ -71,6 +73,9 @@ static ARGPARSE_OPTS opts[] = {
     { oEmbedding, "Embedding" , 0, "@" },
 {0} };
 
+
+
+
 static const char *
 my_strusage( int level )
 {
@@ -258,30 +263,23 @@ enter_complus ()
 {
     HANDLE running;
     int reg;
-    void *factory;
+    IClassFactory *factory;
+    CLSID clsid;
 
-    /* CoInitializeEx (NULL, COINIT_MULTITHREADED); */
+    CoInitializeEx (NULL, COINIT_MULTITHREADED); 
     running = CreateEvent (NULL, FALSE, FALSE, NULL );
 
-  #if 0
-    factory = create_class_factory ();
-    CoRegisterClassObject (CLSID_gpgme, factory, 
+    factory = gnupg_factory_new ( &clsid ); 
+    CoRegisterClassObject (&clsid, (IUnknown*)factory, 
                            CLSCTX_LOCAL_SERVER,
-                           REGCLS_SUSPENDED|REGCLASS_MULTIPLEUSE, &reg );
+                           REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, &reg );
     CoResumeClassObjects ();
-  #endif
 
     WaitForSingleObject ( running, INFINITE );
     CloseHandle (running);
-  #if 0
     CoRevokeClassObject ( reg );
-    factory->release ();
-    CoUnitialize (); 
-  #endif
+    gnupg_factory_release (factory);
+    CoUninitialize (); 
 }
 
 
-
-
-
-
index 9c48c7b..472b8cd 100644 (file)
@@ -38,6 +38,10 @@ struct {
 } opt;
 
 
+/*-- ignupg.c --*/
+IClassFactory *gnupg_factory_new ( CLSID *r_clsid );
+void gnupg_factory_release ( IClassFactory *factory );
+
 
 
 #endif /* COMPLUS_MAIN_H */
diff --git a/complus/obj_base.h b/complus/obj_base.h
new file mode 100644 (file)
index 0000000..8707ae9
--- /dev/null
@@ -0,0 +1,800 @@
+/* obj_base.h - This file defines the macros and types necessary to
+                define COM interfaces, and the three most basic COM interfaces:
+                IUnknown, IMalloc and IClassFactory.
+
+ Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
+ for a complete list)
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __WINE_WINE_OBJ_BASE_H
+#define __WINE_WINE_OBJ_BASE_H
+
+/* check these values! */
+#define E_NOINTERFACE 0x80040002
+#define E_OUTOFMEMORY 0x8007000E
+
+/*****************************************************************************
+ * define ICOM_MSVTABLE_COMPAT
+ * to implement the microsoft com vtable compatibility workaround for g++.
+ *
+ * NOTE: Turning this option on will produce a winelib that is incompatible
+ * with the binary emulator.
+ *
+ * If the compiler supports the com_interface attribute, leave this off, and
+ * define the ICOM_USE_COM_INTERFACE_ATTRIBUTE macro below. This may also
+ * require the addition of the -vtable-thunks option for g++.
+ *
+ * If you aren't interested in Winelib C++ compatibility at all, leave both
+ * options off.
+ *
+ * The preferable method for using ICOM_USE_COM_INTERFACE_ATTRIBUTE macro
+ * would be to define it only for your Winelib application. This allows you
+ * to have both binary and Winelib compatibility for C and C++ at the same 
+ * time :)
+ */
+/* #define ICOM_MSVTABLE_COMPAT 1 */
+/* #define ICOM_USE_COM_INTERFACE_ATTRIBUTE 1 */
+
+/*****************************************************************************
+ * Defines the basic types
+ */
+#include "wtypes.h"
+#include "guiddef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef NONAMELESSSTRUCT
+#define LISet32(li, v)   ((li).HighPart = (v) < 0 ? -1 : 0, (li).LowPart = (v))
+#define ULISet32(li, v)  ((li).HighPart = 0, (li).LowPart = (v))
+#else
+#define LISet32(li, v)   ((li).s.HighPart = (v) < 0 ? -1 : 0, (li).s.LowPart = (v))
+#define ULISet32(li, v)  ((li).s.HighPart = 0, (li).s.LowPart = (v))
+#endif
+
+/*****************************************************************************
+ * GUID API
+ */
+HRESULT WINAPI StringFromCLSID16(REFCLSID id, LPOLESTR16*);
+HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR*);
+
+HRESULT WINAPI CLSIDFromString16(LPCOLESTR16, CLSID *);
+HRESULT WINAPI CLSIDFromString(LPCOLESTR, CLSID *);
+
+HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid);
+HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid);
+
+HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID);
+
+
+INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax);
+
+
+/*****************************************************************************
+ * Macros to define a COM interface
+ */
+/*
+ * The goal of the following set of definitions is to provide a way to use the same 
+ * header file definitions to provide both a C interface and a C++ object oriented 
+ * interface to COM interfaces. The type of interface is selected automatically 
+ * depending on the language but it is always possible to get the C interface in C++ 
+ * by defining CINTERFACE.
+ *
+ * It is based on the following assumptions:
+ *  - all COM interfaces derive from IUnknown, this should not be a problem.
+ *  - the header file only defines the interface, the actual fields are defined 
+ *    separately in the C file implementing the interface.
+ *
+ * The natural approach to this problem would be to make sure we get a C++ class and 
+ * virtual methods in C++ and a structure with a table of pointer to functions in C.
+ * Unfortunately the layout of the virtual table is compiler specific, the layout of 
+ * g++ virtual tables is not the same as that of an egcs virtual table which is not the 
+ * same as that generated by Visual C+. There are workarounds to make the virtual tables 
+ * compatible via padding but unfortunately the one which is imposed to the WINE emulator
+ * by the Windows binaries, i.e. the Visual C++ one, is the most compact of all.
+ *
+ * So the solution I finally adopted does not use virtual tables. Instead I use inline 
+ * non virtual methods that dereference the method pointer themselves and perform the call.
+ *
+ * Let's take Direct3D as an example:
+ *
+ *    #define ICOM_INTERFACE IDirect3D
+ *    #define IDirect3D_METHODS \
+ *        ICOM_METHOD1(HRESULT,Initialize,    REFIID,) \
+ *        ICOM_METHOD2(HRESULT,EnumDevices,   LPD3DENUMDEVICESCALLBACK,, LPVOID,) \
+ *        ICOM_METHOD2(HRESULT,CreateLight,   LPDIRECT3DLIGHT*,, IUnknown*,) \
+ *        ICOM_METHOD2(HRESULT,CreateMaterial,LPDIRECT3DMATERIAL*,, IUnknown*,) \
+ *        ICOM_METHOD2(HRESULT,CreateViewport,LPDIRECT3DVIEWPORT*,, IUnknown*,) \
+ *        ICOM_METHOD2(HRESULT,FindDevice,    LPD3DFINDDEVICESEARCH,, LPD3DFINDDEVICERESULT,)
+ *    #define IDirect3D_IMETHODS \
+ *        IUnknown_IMETHODS \
+ *        IDirect3D_METHODS
+ *    ICOM_DEFINE(IDirect3D,IUnknown)
+ *    #undef ICOM_INTERFACE
+ *
+ *    #ifdef ICOM_CINTERFACE
+ *    // *** IUnknown methods *** //
+ *    #define IDirect3D_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+ *    #define IDirect3D_AddRef(p)             ICOM_CALL (AddRef,p)
+ *    #define IDirect3D_Release(p)            ICOM_CALL (Release,p)
+ *    // *** IDirect3D methods *** //
+ *    #define IDirect3D_Initialize(p,a)       ICOM_CALL1(Initialize,p,a)
+ *    #define IDirect3D_EnumDevices(p,a,b)    ICOM_CALL2(EnumDevice,p,a,b)
+ *    #define IDirect3D_CreateLight(p,a,b)    ICOM_CALL2(CreateLight,p,a,b)
+ *    #define IDirect3D_CreateMaterial(p,a,b) ICOM_CALL2(CreateMaterial,p,a,b)
+ *    #define IDirect3D_CreateViewport(p,a,b) ICOM_CALL2(CreateViewport,p,a,b)
+ *    #define IDirect3D_FindDevice(p,a,b)     ICOM_CALL2(FindDevice,p,a,b)
+ *    #endif
+ *
+ * Comments:
+ *  - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' 
+ *    pointer. Defining this macro here saves us the trouble of having to repeat the interface 
+ *    name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 
+ *    cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not 
+ *    'IDirect3D_VTABLE'.
+ *  - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the 
+ *    inherited methods to form ICOM_IMETHODS.
+ *  - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must 
+ *    be written manually (rather than using a macro to generate the equivalent code) to avoid 
+ *    macro recursion (which compilers don't like).
+ *  - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to 
+ *    explicitly use the interface name for macro expansion reasons again.
+ *    Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's 
+ *    Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance 
+ *    is taken care of by the language.
+ *  - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer 
+ *    method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The 
+ *    only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and 
+ *    to have it take only the type information (with const if necessary) as parameters.
+ *    The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following 
+ *    macros will not work. This time it's because the ICOM_CALL macro expansion is done only once 
+ *    the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone 
+ *    anyway.
+ *  - You may have noticed the double commas after each parameter type. This allows you to put the 
+ *    name of that parameter which I think is good for documentation. It is not required and since 
+ *    I did not know what to put there for this example (I could only find doc about IDirect3D2), 
+ *    I left them blank.
+ *  - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access 
+ *    to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate 
+ *    the inherited method definitions there. This time I could have used a trick to use only one 
+ *    macro whatever the number of parameters but I prefered to have it work the same way as above.
+ *  - You probably have noticed that we don't define the fields we need to actually implement this 
+ *    interface: reference count, pointer to other resources and miscellaneous fields. That's 
+ *    because these interfaces are just that: interfaces. They may be implemented more than once, in 
+ *    different contexts and sometimes not even in Wine. Thus it would not make sense to impose 
+ *    that the interface contains some specific fields.
+ *
+ *
+ * In C this gives:
+ *    typedef struct IDirect3DVtbl IDirect3DVtbl;
+ *    struct IDirect3D {
+ *        IDirect3DVtbl* lpVtbl;
+ *    };
+ *    struct IDirect3DVtbl {
+ *        HRESULT (*fnQueryInterface)(IDirect3D* me, REFIID riid, LPVOID* ppvObj);
+ *        ULONG (*fnQueryInterface)(IDirect3D* me);
+ *        ULONG (*fnQueryInterface)(IDirect3D* me);
+ *        HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
+ *        HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
+ *        HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
+ *        HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
+ *        HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
+ *        HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
+ *    }; 
+ *
+ *    #ifdef ICOM_CINTERFACE
+ *    // *** IUnknown methods *** //
+ *    #define IDirect3D_QueryInterface(p,a,b) (p)->lpVtbl->fnQueryInterface(p,a,b)
+ *    #define IDirect3D_AddRef(p)             (p)->lpVtbl->fnAddRef(p)
+ *    #define IDirect3D_Release(p)            (p)->lpVtbl->fnRelease(p)
+ *    // *** IDirect3D methods *** //
+ *    #define IDirect3D_Initialize(p,a)       (p)->lpVtbl->fnInitialize(p,a)
+ *    #define IDirect3D_EnumDevices(p,a,b)    (p)->lpVtbl->fnEnumDevice(p,a,b)
+ *    #define IDirect3D_CreateLight(p,a,b)    (p)->lpVtbl->fnCreateLight(p,a,b)
+ *    #define IDirect3D_CreateMaterial(p,a,b) (p)->lpVtbl->fnCreateMaterial(p,a,b)
+ *    #define IDirect3D_CreateViewport(p,a,b) (p)->lpVtbl->fnCreateViewport(p,a,b)
+ *    #define IDirect3D_FindDevice(p,a,b)     (p)->lpVtbl->fnFindDevice(p,a,b)
+ *    #endif
+ *
+ * Comments:
+ *  - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing 
+ *    the user needs to know to use the interface. Of course the structure we will define to 
+ *    implement this interface will have more fields but the first one will match this pointer.
+ *  - The code generated by ICOM_DEFINE defines both the structure representing the interface and 
+ *    the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to 
+ *    automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS 
+ *    to define the IDirect3D methods.
+ *  - Each method is declared as a pointer to function field in the jump table. The implementation 
+ *    will fill this jump table with appropriate values, probably using a static variable, and 
+ *    initialize the lpVtbl field to point to this variable.
+ *  - The IDirect3D_Xxx macros then just derefence the lpVtbl pointer and use the function pointer 
+ *    corresponding to the macro name. This emulates the behavior of a virtual table and should be 
+ *    just as fast.
+ *  - This C code should be quite compatible with the Windows headers both for code that uses COM 
+ *    interfaces and for code implementing a COM interface.
+ *
+ *
+ * And in C++ (with gcc's g++):
+ *
+ *    typedef struct IDirect3D: public IUnknown {
+ *        private: HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
+ *        public: inline HRESULT Initialize(REFIID a) { return ((IDirect3D*)t.lpVtbl)->fnInitialize(this,a); };
+ *        private: HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
+ *        public: inline HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK a, LPVOID b)
+ *            { return ((IDirect3D*)t.lpVtbl)->fnEnumDevices(this,a,b); };
+ *        private: HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
+ *        public: inline HRESULT CreateLight(LPDIRECT3DLIGHT* a, IUnknown* b)
+ *            { return ((IDirect3D*)t.lpVtbl)->fnCreateLight(this,a,b); };
+ *        private: HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
+ *        public: inline HRESULT CreateMaterial(LPDIRECT3DMATERIAL* a, IUnknown* b)
+ *            { return ((IDirect3D*)t.lpVtbl)->fnCreateMaterial(this,a,b); };
+ *        private: HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
+ *        public: inline HRESULT CreateViewport(LPDIRECT3DVIEWPORT* a, IUnknown* b)
+ *            { return ((IDirect3D*)t.lpVtbl)->fnCreateViewport(this,a,b); };
+ *        private:  HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
+ *        public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b)
+ *            { return ((IDirect3D*)t.lpVtbl)->fnFindDevice(this,a,b); };
+ *    }; 
+ *
+ * Comments:
+ *  - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface 
+ *    definition. The reason for this is to avoid having to duplicate the mehod definitions: once 
+ *    to have the function pointers in the jump table and once to have the methods in the interface 
+ *    class. Here one macro can generate both. This means though that the first pointer, t.lpVtbl 
+ *    defined in IUnknown,  must be interpreted as the jump table pointer if we interpret the 
+ *    structure as the the interface class, and as the function pointer to the QueryInterface 
+ *    method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this 
+ *    gymnastic is entirely taken care of in the header of IUnknown.
+ *  - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. 
+ *  - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and 
+ *    a non-vritual inline method which dereferences it and calls it. This way this method behaves 
+ *    just like a virtual method but does not create a true C++ virtual table which would break the 
+ *    structure layout. If you look at the implementation of these methods you'll notice that they 
+ *    would not work for void functions. We have to return something and fortunately this seems to 
+ *    be what all the COM methods do (otherwise we would need another set of macros).
+ *  - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter 
+ *    names and the method invocation using only the formal parameter name. This is the reason why 
+ *    we need different macros to handle different numbers of parameters.
+ *  - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE 
+ *    macro is defined in which case we would not be here.
+ *  - This C++ code works well for code that just uses COM interfaces. But it will not work with 
+ *    C++ code implement a COM interface. That's because such code assumes the interface methods 
+ *    are declared as virtual C++ methods which is not the case here.
+ *
+ *
+ * Implementing a COM interface.
+ *
+ * This continues the above example. This example assumes that the implementation is in C.
+ *
+ *    typedef struct _IDirect3D {
+ *        void* lpVtbl;
+ *        // ...
+ *
+ *    } _IDirect3D;
+ *
+ *    static ICOM_VTABLE(IDirect3D) d3dvt;
+ *
+ *    // implement the IDirect3D methods here
+ *
+ *    int IDirect3D_fnQueryInterface(IDirect3D* me)
+ *    {
+ *        ICOM_THIS(IDirect3D,me);
+ *        // ...
+ *    }
+ *
+ *    // ...
+ *
+ *    static ICOM_VTABLE(IDirect3D) d3dvt = {
+ *        ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ *        IDirect3D_fnQueryInterface,
+ *        IDirect3D_fnAdd,
+ *        IDirect3D_fnAdd2,
+ *        IDirect3D_fnInitialize,
+ *        IDirect3D_fnSetWidth
+ *    };
+ *
+ * Comments:
+ *  - We first define what the interface really contains. This is th e_IDirect3D structure. The 
+ *    first field must of course be the virtual table pointer. Everything else is free.
+ *  - Then we predeclare our static virtual table variable, we will need its address in some 
+ *    methods to initialize the virtual table pointer of the returned interface objects.
+ *  - Then we implement the interface methods. To match what has been declared in the header file 
+ *    they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that 
+ *    we can manipulate the fields. This is performed by the ICOM_THIS macro.
+ *  - Finally we initialize the virtual table.
+ */
+
+
+#define ICOM_VTABLE(iface)       iface##Vtbl
+#define ICOM_VFIELD(iface)       ICOM_VTABLE(iface)* lpVtbl
+#define ICOM_VTBL(iface)         (iface)->lpVtbl
+
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define ICOM_CINTERFACE 1
+#endif
+
+#ifndef ICOM_CINTERFACE
+/* C++ interface */
+
+#define ICOM_METHOD(ret,xfn) \
+     public: virtual ret CALLBACK (xfn)(void) = 0;
+#define ICOM_METHOD1(ret,xfn,ta,na) \
+     public: virtual ret CALLBACK (xfn)(ta a) = 0;
+#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b) = 0;
+#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c) = 0;
+#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0;
+#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0;
+#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0;
+#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0;
+#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0;
+#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0;
+#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j) = 0;
+#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
+     public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k) = 0;
+
+
+#define ICOM_VMETHOD(xfn) \
+     public: virtual void CALLBACK (xfn)(void) = 0;
+#define ICOM_VMETHOD1(xfn,ta,na) \
+     public: virtual void CALLBACK (xfn)(ta a) = 0;
+#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b) = 0;
+#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c) = 0;
+#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0;
+#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0;
+#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0;
+#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0;
+#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0;
+#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0;
+#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j) = 0;
+#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
+     public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j, tk k) = 0;
+
+
+#ifdef ICOM_USE_COM_INTERFACE_ATTRIBUTE
+
+#define ICOM_DEFINE(iface,ibase) \
+    typedef struct iface: public ibase { \
+        iface##_METHODS \
+            } __attribute__ ((com_interface));
+
+#else
+
+#define ICOM_DEFINE(iface,ibase) \
+    typedef struct iface: public ibase { \
+        iface##_METHODS \
+    };
+
+#endif /* ICOM_USE_COM_INTERFACE_ATTRIBUTE */
+
+#define ICOM_CALL(xfn, p)                         (p)->xfn()
+#define ICOM_CALL1(xfn, p,a)                      (p)->xfn(a)
+#define ICOM_CALL2(xfn, p,a,b)                    (p)->xfn(a,b)
+#define ICOM_CALL3(xfn, p,a,b,c)                  (p)->xfn(a,b,c)
+#define ICOM_CALL4(xfn, p,a,b,c,d)                (p)->xfn(a,b,c,d)
+#define ICOM_CALL5(xfn, p,a,b,c,d,e)              (p)->xfn(a,b,c,d,e)
+#define ICOM_CALL6(xfn, p,a,b,c,d,e,f)            (p)->xfn(a,b,c,d,e,f)
+#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g)          (p)->xfn(a,b,c,d,e,f,g)
+#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h)        (p)->xfn(a,b,c,d,e,f,g,h)
+#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i)      (p)->xfn(a,b,c,d,e,f,g,h,i)
+#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j)   (p)->xfn(a,b,c,d,e,f,g,h,i,j)
+#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) (p)->xfn(a,b,c,d,e,f,g,h,i,j,k)
+
+
+#else
+/* C interface */
+
+
+#ifdef __WINE__
+
+#define ICOM_METHOD(ret,xfn) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me);
+#define ICOM_METHOD1(ret,xfn,ta,na) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a);
+#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b);
+#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
+#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
+#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
+#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
+#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
+#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
+#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
+#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
+#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
+    ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
+
+#define ICOM_VMETHOD(xfn) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me);
+#define ICOM_VMETHOD1(xfn,ta,na) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a);
+#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b);
+#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
+#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
+#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
+#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
+#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
+#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,nh) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
+#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ni) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
+#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,nj) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
+#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,nk) \
+    void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
+
+#define ICOM_CALL(xfn, p)                         ICOM_VTBL(p)->fn##xfn(p)
+#define ICOM_CALL1(xfn, p,a)                      ICOM_VTBL(p)->fn##xfn(p,a)
+#define ICOM_CALL2(xfn, p,a,b)                    ICOM_VTBL(p)->fn##xfn(p,a,b)
+#define ICOM_CALL3(xfn, p,a,b,c)                  ICOM_VTBL(p)->fn##xfn(p,a,b,c)
+#define ICOM_CALL4(xfn, p,a,b,c,d)                ICOM_VTBL(p)->fn##xfn(p,a,b,c,d)
+#define ICOM_CALL5(xfn, p,a,b,c,d,e)              ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e)
+#define ICOM_CALL6(xfn, p,a,b,c,d,e,f)            ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f)
+#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g)          ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g)
+#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h)        ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h)
+#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i)      ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i)
+#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j)   ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i,j)
+#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i,j,k)
+
+#else
+
+/* WINELIB case */
+
+#define ICOM_METHOD(ret,xfn) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me);
+#define ICOM_METHOD1(ret,xfn,ta,na) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a);
+#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b);
+#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
+#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
+#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
+#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
+#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
+#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
+#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
+#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
+#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
+    ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
+
+#define ICOM_VMETHOD(xfn) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me);
+#define ICOM_VMETHOD1(xfn,ta,na) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a);
+#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b);
+#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
+#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
+#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
+#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
+#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
+#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,nh) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
+#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ni) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
+#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,nj) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
+#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,nk) \
+    void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
+
+#define ICOM_CVMETHOD(xfn) \
+        void CALLBACK (*xfn)(const ICOM_INTERFACE* me);
+#define ICOM_CVMETHOD1(xfn,ta,na) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a);
+#define ICOM_CVMETHOD2(xfn,ta,na,tb,nb) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b);
+#define ICOM_CVMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c);
+#define ICOM_CVMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
+#define ICOM_CVMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
+#define ICOM_CVMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
+#define ICOM_CVMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
+#define ICOM_CVMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
+
+#define ICOM_CVMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
+#define ICOM_CVMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
+#define ICOM_CVMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
+    void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
+
+#define ICOM_CALL(xfn, p)                         ICOM_VTBL(p)->xfn(p)
+#define ICOM_CALL1(xfn, p,a)                      ICOM_VTBL(p)->xfn(p,a)
+#define ICOM_CALL2(xfn, p,a,b)                    ICOM_VTBL(p)->xfn(p,a,b)
+#define ICOM_CALL3(xfn, p,a,b,c)                  ICOM_VTBL(p)->xfn(p,a,b,c)
+#define ICOM_CALL4(xfn, p,a,b,c,d)                ICOM_VTBL(p)->xfn(p,a,b,c,d)
+#define ICOM_CALL5(xfn, p,a,b,c,d,e)              ICOM_VTBL(p)->xfn(p,a,b,c,d,e)
+#define ICOM_CALL6(xfn, p,a,b,c,d,e,f)            ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f)
+#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g)          ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g)
+#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h)        ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h)
+#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i)      ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i)
+#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j)   ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j)
+#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j,k)
+
+#endif /* __WINE__ */
+
+#ifdef ICOM_MSVTABLE_COMPAT
+#define ICOM_DEFINE(iface,ibase) \
+    typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \
+    struct iface { \
+        const ICOM_VFIELD(iface); \
+    }; \
+    struct ICOM_VTABLE(iface) { \
+        long dummyRTTI1; \
+        long dummyRTTI2; \
+        ibase##_IMETHODS \
+        iface##_METHODS \
+    };
+#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE 0,0,
+
+#else
+#define ICOM_DEFINE(iface,ibase) \
+    typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \
+    struct iface { \
+        const ICOM_VFIELD(iface); \
+    }; \
+    struct ICOM_VTABLE(iface) { \
+        ibase##_IMETHODS \
+        iface##_METHODS \
+    };
+#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+#endif /* ICOM_MSVTABLE_COMPAT */
+
+
+#define ICOM_THIS(impl,iface)          impl* const This=(impl*)iface
+#define ICOM_CTHIS(impl,iface)         const impl* const This=(const impl*)iface
+
+#endif
+
+
+/*****************************************************************************
+ * Predeclare the interfaces
+ */
+DEFINE_OLEGUID(IID_IClassFactory,      0x00000001L, 0, 0);
+typedef struct IClassFactory IClassFactory, *LPCLASSFACTORY;
+
+DEFINE_OLEGUID(IID_IMalloc,            0x00000002L, 0, 0);
+typedef struct IMalloc IMalloc,*LPMALLOC;
+
+DEFINE_OLEGUID(IID_IUnknown,           0x00000000L, 0, 0);
+typedef struct IUnknown IUnknown, *LPUNKNOWN;
+
+
+/*****************************************************************************
+ * IUnknown interface
+ */
+#define ICOM_INTERFACE IUnknown
+#define IUnknown_IMETHODS \
+    ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj) \
+    ICOM_METHOD (ULONG,AddRef) \
+    ICOM_METHOD (ULONG,Release)
+#ifdef ICOM_CINTERFACE
+typedef struct ICOM_VTABLE(IUnknown) ICOM_VTABLE(IUnknown);
+struct IUnknown {
+    ICOM_VFIELD(IUnknown);
+#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE)
+} __attribute__ ((com_interface)); 
+#else
+};
+#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */
+
+struct ICOM_VTABLE(IUnknown) {
+#ifdef ICOM_MSVTABLE_COMPAT
+    long dummyRTTI1;
+    long dummyRTTI2;
+#endif /* ICOM_MSVTABLE_COMPAT */
+
+#else /* ICOM_CINTERFACE */
+struct IUnknown {
+
+#endif /* ICOM_CINTERFACE */
+
+    ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj)
+    ICOM_METHOD (ULONG,AddRef)
+    ICOM_METHOD (ULONG,Release)
+#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE)
+} __attribute__ ((com_interface)); 
+#else
+};
+#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */
+
+#undef ICOM_INTERFACE
+
+/*** IUnknown methods ***/
+#define IUnknown_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IUnknown_AddRef(p)             ICOM_CALL (AddRef,p)
+#define IUnknown_Release(p)            ICOM_CALL (Release,p)
+
+/*****************************************************************************
+ * IClassFactory interface
+ */
+#define ICOM_INTERFACE IClassFactory
+#define IClassFactory_METHODS \
+    ICOM_METHOD3(HRESULT,CreateInstance, LPUNKNOWN,pUnkOuter, REFIID,riid, LPVOID*,ppvObject) \
+    ICOM_METHOD1(HRESULT,LockServer,     BOOL,fLock)
+#define IClassFactory_IMETHODS \
+    IUnknown_IMETHODS \
+    IClassFactory_METHODS
+ICOM_DEFINE(IClassFactory,IUnknown)
+#undef ICOM_INTERFACE
+
+/*** IUnknown methods ***/
+#define IClassFactory_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IClassFactory_AddRef(p)             ICOM_CALL (AddRef,p)
+#define IClassFactory_Release(p)            ICOM_CALL (Release,p)
+/*** IClassFactory methods ***/
+#define IClassFactory_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c)
+#define IClassFactory_LockServer(p,a)         ICOM_CALL1(LockServer,p,a)
+
+
+/*****************************************************************************
+ * IMalloc interface
+ */
+#define ICOM_INTERFACE IMalloc
+#define IMalloc_METHODS \
+    ICOM_METHOD1 (LPVOID,Alloc,       DWORD,cb) \
+    ICOM_METHOD2 (LPVOID,Realloc,     LPVOID,pv, DWORD,cb) \
+    ICOM_VMETHOD1(       Free,        LPVOID,pv) \
+    ICOM_METHOD1(DWORD, GetSize,     LPVOID,pv) \
+    ICOM_METHOD1(INT, DidAlloc,    LPVOID,pv) \
+    ICOM_METHOD  (VOID,  HeapMinimize)
+#define IMalloc_IMETHODS \
+    IUnknown_IMETHODS \
+    IMalloc_METHODS
+ICOM_DEFINE(IMalloc,IUnknown)
+#undef ICOM_INTERFACE
+
+/*** IUnknown methods ***/
+#define IMalloc_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
+#define IMalloc_AddRef(p)             ICOM_CALL (AddRef,p)
+#define IMalloc_Release(p)            ICOM_CALL (Release,p)
+/*** IMalloc32 methods ***/
+#define IMalloc_Alloc(p,a)      ICOM_CALL1(Alloc,p,a)
+#define IMalloc_Realloc(p,a,b)  ICOM_CALL2(Realloc,p,a,b)
+#define IMalloc_Free(p,a)       ICOM_CALL1(Free,p,a)
+#define IMalloc_GetSize(p,a)    ICOM_CALL1(GetSize,p,a)
+#define IMalloc_DidAlloc(p,a)   ICOM_CALL1(DidAlloc,p,a)
+#define IMalloc_HeapMinimize(p) ICOM_CALL (HeapMinimize,p)
+
+
+HRESULT WINAPI CoGetMalloc(DWORD dwMemContext,LPMALLOC* lpMalloc);
+
+LPVOID WINAPI CoTaskMemAlloc(ULONG size);
+
+void WINAPI CoTaskMemFree(LPVOID ptr);
+
+/* FIXME: unimplemented */
+LPVOID WINAPI CoTaskMemRealloc(LPVOID ptr, ULONG size);
+
+
+/*****************************************************************************
+ * Additional API
+ */
+
+HRESULT WINAPI CoCreateGuid(GUID* pguid);
+
+HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
+
+void WINAPI CoFreeAllLibraries(void);
+
+void WINAPI CoFreeLibrary(HINSTANCE hLibrary);
+
+void WINAPI CoFreeUnusedLibraries(void);
+
+HRESULT WINAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv);
+
+HRESULT WINAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved, REFIID iid, LPVOID *ppv);
+
+HRESULT WINAPI CoInitialize(LPVOID lpReserved);
+HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit);
+
+void WINAPI CoUninitialize(void);
+
+typedef enum tagCOINIT
+{
+    COINIT_APARTMENTTHREADED  = 0x2, /* Apartment model */
+    COINIT_MULTITHREADED      = 0x0, /* OLE calls objects on any thread */
+    COINIT_DISABLE_OLE1DDE    = 0x4, /* Don't use DDE for Ole1 support */
+    COINIT_SPEED_OVER_MEMORY  = 0x8  /* Trade memory for speed */
+} COINIT;
+
+
+/* FIXME: not implemented */
+BOOL WINAPI CoIsOle1Class(REFCLSID rclsid);
+
+HRESULT WINAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+
+/* class registration flags; passed to CoRegisterClassObject */
+typedef enum tagREGCLS
+{
+    REGCLS_SINGLEUSE = 0,
+    REGCLS_MULTIPLEUSE = 1,
+    REGCLS_MULTI_SEPARATE = 2,
+    REGCLS_SUSPENDED = 4
+} REGCLS;
+
+HRESULT WINAPI CoResumeClassObjects (void);
+HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid,LPUNKNOWN pUnk,DWORD dwClsContext,DWORD flags,LPDWORD lpdwRegister);
+
+HRESULT WINAPI CoRevokeClassObject(DWORD dwRegister);
+
+/*****************************************************************************
+ *     COM Server dll - exports
+ */
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv);
+HRESULT WINAPI DllCanUnloadNow(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __WINE_WINE_OBJ_BASE_H */
diff --git a/complus/wtypes.h b/complus/wtypes.h
new file mode 100644 (file)
index 0000000..bff3f30
--- /dev/null
@@ -0,0 +1,272 @@
+/* wtypes.h - Defines the basic types used by COM interfaces.  
+
+ Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
+ for a complete list)
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __WINE_WTYPES_H
+#define __WINE_WTYPES_H
+
+#include "basetsd.h"
+#include "guiddef.h"
+/*#include "rpc.h"*/
+/*#include "rpcndr.h"*/
+
+typedef WORD CLIPFORMAT, *LPCLIPFORMAT;
+
+/* FIXME: does not belong here */
+typedef CHAR           OLECHAR16;
+typedef LPSTR          LPOLESTR16;
+typedef LPCSTR         LPCOLESTR16;
+typedef OLECHAR16      *BSTR16;
+typedef BSTR16         *LPBSTR16;
+#define OLESTR16(x) x
+
+typedef WCHAR          OLECHAR;
+typedef LPWSTR         LPOLESTR;
+typedef LPCWSTR                LPCOLESTR;
+typedef OLECHAR        *BSTR;
+typedef BSTR           *LPBSTR;
+
+/*
+#ifndef _DWORDLONG_
+#define _DWORDLONG_
+typedef __uint64 DWORDLONG, *PDWORDLONG;
+#endif
+
+#ifndef _ULONGLONG_
+#define _ULONGLONG_
+typedef __int64 LONGLONG, *PLONGLONG;
+typedef __uint64 ULONGLONG, *PULONGLONG;
+#endif
+*/
+
+#define OLESTR(x) L##x
+
+typedef enum tagDVASPECT
+{ 
+       DVASPECT_CONTENT   = 1,
+       DVASPECT_THUMBNAIL = 2,
+       DVASPECT_ICON      = 4,   
+       DVASPECT_DOCPRINT  = 8
+} DVASPECT;
+
+typedef enum tagSTGC
+{
+       STGC_DEFAULT = 0,
+       STGC_OVERWRITE = 1,
+       STGC_ONLYIFCURRENT = 2,
+       STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
+       STGC_CONSOLIDATE = 8
+} STGC;
+
+typedef enum tagSTGMOVE
+{   
+       STGMOVE_MOVE = 0,
+       STGMOVE_COPY = 1,
+       STGMOVE_SHALLOWCOPY = 2
+} STGMOVE;
+
+
+typedef struct _COAUTHIDENTITY
+{
+    USHORT* User;
+    ULONG UserLength;
+    USHORT* Domain;
+    ULONG DomainLength;
+    USHORT* Password;
+    ULONG PasswordLength;
+    ULONG Flags;
+} COAUTHIDENTITY;
+
+typedef struct _COAUTHINFO
+{
+    DWORD dwAuthnSvc;
+    DWORD dwAuthzSvc;
+    LPWSTR pwszServerPrincName;
+    DWORD dwAuthnLevel;
+    DWORD dwImpersonationLevel;
+    COAUTHIDENTITY* pAuthIdentityData;
+    DWORD dwCapabilities;
+} COAUTHINFO;
+
+typedef struct _COSERVERINFO
+{
+    DWORD dwReserved1;
+    LPWSTR pwszName;
+    COAUTHINFO* pAuthInfo;
+    DWORD dwReserved2;
+} COSERVERINFO;
+
+typedef enum tagCLSCTX
+{
+    CLSCTX_INPROC_SERVER     = 0x1,
+    CLSCTX_INPROC_HANDLER    = 0x2,
+    CLSCTX_LOCAL_SERVER      = 0x4,
+    CLSCTX_INPROC_SERVER16   = 0x8,
+    CLSCTX_REMOTE_SERVER     = 0x10,
+    CLSCTX_INPROC_HANDLER16  = 0x20,
+    CLSCTX_INPROC_SERVERX86  = 0x40,
+    CLSCTX_INPROC_HANDLERX86 = 0x80,
+    CLSCTX_ESERVER_HANDLER   = 0x100
+} CLSCTX;
+
+#define CLSCTX_INPROC           (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER)
+#define CLSCTX_ALL              (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
+#define CLSCTX_SERVER           (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
+
+typedef enum tagMSHLFLAGS
+{
+    MSHLFLAGS_NORMAL        = 0,
+    MSHLFLAGS_TABLESTRONG   = 1,
+    MSHLFLAGS_TABLEWEAK     = 2,
+    MSHLFLAGS_NOPING        = 4
+} MSHLFLAGS;
+
+typedef enum tagMSHCTX
+{
+    MSHCTX_LOCAL            = 0,
+    MSHCTX_NOSHAREDMEM      = 1,
+    MSHCTX_DIFFERENTMACHINE = 2,
+    MSHCTX_INPROC           = 3
+} MSHCTX;
+
+typedef unsigned short VARTYPE;
+
+typedef ULONG PROPID;
+
+/*
+#ifndef _tagBLOB_DEFINED
+#define _tagBLOB_DEFINED
+#define _BLOB_DEFINED
+#define _LPBLOB_DEFINED
+typedef struct tagBLOB
+{
+    ULONG cbSize;
+    BYTE *pBlobData;
+} BLOB, *LPBLOB;
+#endif
+*/
+
+#ifndef _tagCY_DEFINED
+#define _tagCY_DEFINED
+
+typedef union tagCY {
+    struct {
+#ifdef BIG_ENDIAN
+        LONG  Hi;
+        LONG  Lo;
+#else /* defined(BIG_ENDIAN) */
+        ULONG Lo;
+        LONG  Hi;
+#endif /* defined(BIG_ENDIAN) */
+    } DUMMYSTRUCTNAME;
+    LONGLONG int64;
+} CY;
+
+#endif /* _tagCY_DEFINED */
+
+/*
+ * 0 == FALSE and -1 == TRUE
+ */
+#define VARIANT_TRUE     ((VARIANT_BOOL)0xFFFF)
+#define VARIANT_FALSE    ((VARIANT_BOOL)0x0000)
+typedef short VARIANT_BOOL,_VARIANT_BOOL;
+
+typedef struct tagCLIPDATA
+{
+    ULONG cbSize;
+    long ulClipFmt;
+    BYTE *pClipData;
+} CLIPDATA;
+
+/* Macro to calculate the size of the above pClipData */
+#define CBPCLIPDATA(clipdata)    ( (clipdata).cbSize - sizeof((clipdata).ulClipFmt) )
+
+typedef LONG SCODE;
+
+/*
+#ifndef _FILETIME_
+#define _FILETIME_
+*/
+/* 64 bit number of 100 nanoseconds intervals since January 1, 1601 */
+/*
+typedef struct
+{
+  DWORD  dwLowDateTime;
+  DWORD  dwHighDateTime;
+} FILETIME, *LPFILETIME;
+#endif 
+*/
+
+#ifndef _SECURITY_DEFINED
+#define _SECURITY_DEFINED
+
+/*
+typedef struct {
+    BYTE Value[6];
+} SID_IDENTIFIER_AUTHORITY,*PSID_IDENTIFIER_AUTHORITY;
+
+typedef struct _SID {
+    BYTE Revision;
+    BYTE SubAuthorityCount;
+    SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+    DWORD SubAuthority[1];
+} SID,*PSID;
+*/
+/*
+ * ACL 
+ */
+/*
+typedef struct _ACL {
+    BYTE AclRevision;
+    BYTE Sbz1;
+    WORD AclSize;
+    WORD AceCount;
+    WORD Sbz2;
+} ACL, *PACL;
+
+typedef DWORD SECURITY_INFORMATION;
+typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
+typedef DWORD ACCESS_MASK, *PACCESS_MASK;
+
+typedef PVOID PGENERIC_MAPPING;
+*/
+/* The security descriptor structure */
+/*
+typedef struct {
+    BYTE Revision;
+    BYTE Sbz1;
+    SECURITY_DESCRIPTOR_CONTROL Control;
+    PSID Owner;
+    PSID Group;
+    PACL Sacl;
+    PACL Dacl;
+} SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR;
+*/
+#endif /* _SECURITY_DEFINED */
+
+#ifndef _ROTFLAGS_DEFINED
+#define _ROTFLAGS_DEFINED
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 0x1
+#define ROTFLAGS_ALLOWANYCLIENT 0x2
+#endif /* !defined(_ROTFLAGS_DEFINED) */
+
+#endif /* __WINE_WTYPES_H */
index ec98903..41a8b18 100644 (file)
@@ -13,7 +13,7 @@ AM_MAINTAINER_MODE
 #    AGE, set REVISION to 0.
 # 3. Interfaces removed (BAD, breaks upward compatibility): Increment
 #    CURRENT, set AGE and REVISION to 0.
-AM_INIT_AUTOMAKE(gpgme,0.1.1)
+AM_INIT_AUTOMAKE(gpgme,0.1.2)
 LIBGPGME_LT_CURRENT=0
 LIBGPGME_LT_AGE=0
 LIBGPGME_LT_REVISION=3
@@ -24,6 +24,8 @@ AC_SUBST(LIBGPGME_LT_AGE)
 AC_SUBST(LIBGPGME_LT_REVISION)
 
 
+AM_MAINTAINER_MODE
+
 dnl
 dnl Checks for programs
 dnl
@@ -47,7 +49,7 @@ case "${target}" in
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         AC_DEFINE(HAVE_DOSISH_SYSTEM)
         GPG='c:\\gnupg\\gpg.exe'
-        component_system='COM+'
+        #component_system='COM+'
         ;;
     *)
        ;;
index 6fe3bb1..ec08ae6 100644 (file)
@@ -24,7 +24,7 @@ libgpgme_la_SOURCES = \
         key.c key.h \
        keylist.c \
         rungpg.c rungpg.h status-table.h \
-       io.h posix-io.c w32-io.c \
+       syshdr.h io.h posix-io.c w32-io.c \
        gpgme.c version.c errors.c
 
 
index 324245a..ba5a1b4 100644 (file)
@@ -69,7 +69,8 @@ struct gpgme_context_s {
     volatile int key_cond;  /* something new is available */
     struct key_queue_item_s *key_queue;
 
-    char *prompt_1;
+    GpgmePassphraseCb passphrase_cb;
+    void *passphrase_cb_value;
 };
 
 
index 94438f6..6581db4 100644 (file)
@@ -25,8 +25,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
-
+#include "syshdr.h"
 
 #include "util.h"
 #include "context.h"
index 0a2545f..465101b 100644 (file)
@@ -33,7 +33,7 @@ struct decrypt_result_s {
     int no_passphrase;
     int okay;
     int failed;
-
+    void *last_pw_handle;
 };
 
 
@@ -76,8 +76,6 @@ decrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
       case STATUS_NEED_PASSPHRASE:
       case STATUS_NEED_PASSPHRASE_SYM:
         fprintf (stderr, "need a passphrase ...\n" );
-        _gpgme_set_prompt (ctx, 1, "Hey! We need your passphrase!");
-        /* next thing gpg has to do is to read it from the passphrase-fd */
         break;
 
       case STATUS_MISSING_PASSPHRASE:
@@ -101,9 +99,44 @@ decrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
     }
 }
 
+static const char *
+command_handler ( void *opaque, GpgStatusCode code, const char *key )
+{
+    GpgmeCtx c = opaque;
+
+    if ( c->result_type == RESULT_TYPE_NONE ) {
+        if ( create_result_struct ( c ) ) {
+            c->out_of_core = 1;
+            return NULL;
+        }
+    }
+
+    if ( !code ) {
+        /* We have been called for cleanup */
+        if ( c->passphrase_cb ) { 
+            /* Fixme: take the key in account */
+            c->passphrase_cb (c->passphrase_cb_value, 0, 
+                              &c->result.decrypt->last_pw_handle );
+        }
+        
+        return NULL;
+    }
+
+    if ( !key || !c->passphrase_cb )
+        return NULL;
+    
+    if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
+        return c->passphrase_cb (c->passphrase_cb_value,
+                                 "Hey, Mr. Hoover wants your passphrase!",
+                                 &c->result.decrypt->last_pw_handle );
+   }
+    
+    return NULL;
+}
+
 
 GpgmeError
-gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData passphrase,
+gpgme_op_decrypt_start ( GpgmeCtx c, 
                          GpgmeData ciph, GpgmeData plain   )
 {
     int rc = 0;
@@ -124,16 +157,16 @@ gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData passphrase,
         goto leave;
 
     _gpgme_gpg_set_status_handler ( c->gpg, decrypt_status_handler, c );
+    if (c->passphrase_cb) {
+        rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c );
+        if (rc)
+            goto leave;
+    }
 
     /* build the commandline */
     _gpgme_gpg_add_arg ( c->gpg, "--decrypt" );
     for ( i=0; i < c->verbosity; i++ )
         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
-    if (passphrase) {
-        _gpgme_gpg_add_arg (c->gpg, "--passphrase-fd" );
-        _gpgme_gpg_add_data (c->gpg, passphrase, -2 );
-    }
-
 
     /* Check the supplied data */
     if ( !ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE ) {
@@ -169,7 +202,6 @@ gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData passphrase,
 /**
  * gpgme_op_decrypt:
  * @c: The context
- * @passphrase: A data object with the passphrase or NULL.
  * @in: ciphertext input
  * @out: plaintext output
  * 
@@ -180,10 +212,10 @@ gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData passphrase,
  * Return value:  0 on success or an errorcode. 
  **/
 GpgmeError
-gpgme_op_decrypt ( GpgmeCtx c, GpgmeData passphrase,
+gpgme_op_decrypt ( GpgmeCtx c,
                    GpgmeData in, GpgmeData out )
 {
-    GpgmeError err = gpgme_op_decrypt_start ( c, passphrase, in, out );
+    GpgmeError err = gpgme_op_decrypt_start ( c, in, out );
     if ( !err ) {
         gpgme_wait (c, 1);
         if ( c->result_type != RESULT_TYPE_DECRYPT )
index d6b189c..ad74e10 100644 (file)
@@ -52,6 +52,7 @@ gpgme_new (GpgmeCtx *r_ctx)
     c->verbosity = 1;
     c->use_armor = 1; /* fixme: reset this to 0 */
     *r_ctx = c;
+
     return 0;
 }
 
@@ -70,7 +71,6 @@ gpgme_release ( GpgmeCtx c )
     _gpgme_key_release ( c->tmp_key );
     gpgme_data_release ( c->notation );
     /* fixme: release the key_queue */
-    xfree (c->prompt_1);
     xfree (c);
 }
 
@@ -147,35 +147,40 @@ gpgme_set_textmode ( GpgmeCtx c, int yes )
     c->use_textmode = yes;
 }
 
-/* 
- * The only which currently allowed is 1
- */
+/**
+ * gpgme_set_passphrase_cb:
+ * @c: the context 
+ * @cb: A callback function
+ * @cb_value: The value passed to the callback function
+ * 
+ * This function sets a callback function to be used to pass a passphrase
+ * to gpg. The preferred way to handle this is by using the gpg-agent, but
+ * because that beast is not ready for real use, you can use this passphrase
+ * thing.
+ *
+ * The callback function is defined as:
+ * <literal>
+ * typedef const char *(*GpgmePassphraseCb)(void*cb_value,
+ *                                          const char *desc,
+ *                                          void *r_hd);
+ * </literal>
+ * and called whenever gpgme needs a passphrase. DESC will have a nice
+ * text, to be used to prompt for the passphrase and R_HD is just a parameter
+ * to be used by the callback it self.  Becuase the callback returns a const
+ * string, the callback might want to know when it can releae resources
+ * assocated with that returned string; gpgme helps here by calling this
+ * passphrase callback with an DESC of %NULL as soon as it does not need
+ * the returned string anymore.  The callback function might then choose
+ * to release resources depending on R_HD.
+ *
+ **/
 void
-_gpgme_set_prompt ( GpgmeCtx c, int which, const char *text )
+gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value )
 {
-    assert ( which == 1 );
-
-    xfree (c->prompt_1); c->prompt_1 = NULL;
-    if (text) {
-        c->prompt_1 = xtrystrdup (text);
-        if ( !c->prompt_1 )
-            c->out_of_core = 1;
-    }
+    c->passphrase_cb = cb;
+    c->passphrase_cb_value = cb_value;
 }
 
-const char *
-gpgme_get_prompt ( GpgmeCtx c, int which )
-{
-    if ( which != 1 )
-        return NULL;
-    return c->prompt_1;
-}
-
-
-
-
-
-
 
 
 
index b9509cc..57066e5 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
  * let autoconf (using the AM_PATH_GPGME macro) check that this
  * header matches the installed library.
  * Warning: Do not edit the next line.  configure will do that for you! */
-#define GPGME_VERSION "0.1.1"
+#define GPGME_VERSION "0.1.2"
 
 
 
@@ -92,6 +92,15 @@ typedef enum {
     GPGME_SIG_STAT_ERROR = 5
 } GpgmeSigStat;
 
+typedef enum {
+    GPGME_SIG_MODE_NORMAL = 0,
+    GPGME_SIG_MODE_DETACH = 1,
+    GPGME_SIG_MODE_CLEAR = 2
+} GpgmeSigMode;
+
+
+typedef const char *(*GpgmePassphraseCb)(void*, const char *desc, void *r_hd);
+
 
 /* Context management */
 GpgmeError gpgme_new (GpgmeCtx *r_ctx);
@@ -101,6 +110,8 @@ GpgmeCtx   gpgme_wait ( GpgmeCtx c, int hang );
 char *gpgme_get_notation ( GpgmeCtx c );
 void gpgme_set_armor ( GpgmeCtx c, int yes );
 void gpgme_set_textmode ( GpgmeCtx c, int yes );
+void gpgme_set_passphrase_cb ( GpgmeCtx c,
+                               GpgmePassphraseCb cb, void *cb_value );
 
 
 
@@ -138,9 +149,11 @@ char *gpgme_key_get_as_xml ( GpgmeKey key );
 GpgmeError gpgme_op_encrypt_start ( GpgmeCtx c,
                                     GpgmeRecipients recp,
                                     GpgmeData in, GpgmeData out );
-GpgmeError gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData passphrase,
+GpgmeError gpgme_op_decrypt_start ( GpgmeCtx c, 
                                     GpgmeData ciph, GpgmeData plain );
-GpgmeError gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out );
+GpgmeError gpgme_op_sign_start ( GpgmeCtx c,
+                                 GpgmeData in, GpgmeData out,
+                                 GpgmeSigMode mode );
 GpgmeError gpgme_op_verify_start ( GpgmeCtx c,
                                    GpgmeData sig, GpgmeData text );
 
@@ -154,9 +167,10 @@ GpgmeError gpgme_op_keylist_next ( GpgmeCtx c, GpgmeKey *r_key );
 /* Convenience functions for normal usage */
 GpgmeError gpgme_op_encrypt ( GpgmeCtx c, GpgmeRecipients recp,
                               GpgmeData in, GpgmeData out );
-GpgmeError gpgme_op_decrypt ( GpgmeCtx c, GpgmeData passphrase,
+GpgmeError gpgme_op_decrypt ( GpgmeCtx c, 
                               GpgmeData in, GpgmeData out );
-GpgmeError gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out );
+GpgmeError gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out,
+                           GpgmeSigMode mode);
 GpgmeError gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text,
                              GpgmeSigStat *r_status );
 
index 0ae58a2..14c0947 100644 (file)
@@ -35,6 +35,7 @@ struct io_select_fd_s {
     int for_read;
     int for_write;
     int signaled;
+    int frozen;
     void *opaque;
 };
 
index ba382a9..0019b82 100644 (file)
 
 /*-- gpgme.c --*/
 void _gpgme_release_result ( GpgmeCtx c );
-void _gpgme_set_prompt ( GpgmeCtx c, int which, const char *text );
 
 /*-- wait.c --*/
 GpgmeCtx _gpgme_wait_on_condition ( GpgmeCtx c,
                                     int hang, volatile int *cond );
+void _gpgme_freeze_fd ( int fd );
+void _gpgme_thaw_fd ( int fd );
 
 
 /*-- recipient.c --*/
index dede3f9..740e98f 100644 (file)
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <unistd.h>
 #include <sys/wait.h>
 #include <signal.h>
 #include <fcntl.h>
+#include "syshdr.h"
 
 #include "io.h"
 
@@ -100,8 +100,24 @@ _gpgme_io_spawn ( const char *path, char **argv,
                   struct spawn_fd_item_s *fd_child_list,
                   struct spawn_fd_item_s *fd_parent_list )
 {
+    static volatile int fixed_signals;
     pid_t pid;
     int i;
+
+    if ( !fixed_signals ) { 
+        struct sigaction act;
+        
+        sigaction( SIGPIPE, NULL, &act );
+        if( act.sa_handler == SIG_DFL ) {
+            act.sa_handler = SIG_IGN;
+            sigemptyset( &act.sa_mask );
+            act.sa_flags = 0;
+            sigaction( SIGPIPE, &act, NULL);
+        }
+        fixed_signals = 1;
+        /* fixme: This is not really MT safe */
+    }
+
     
     pid = fork ();
     if (pid == -1) 
@@ -134,7 +150,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
         }
 
         if( !duped_stdin || !duped_stderr ) {
-            int fd = open ( "/dev/null", O_RDONLY );
+            int fd = open ( "/dev/null", O_RDWR );
             if ( fd == -1 ) {
                 fprintf (stderr,"can't open `/dev/null': %s\n",
                          strerror (errno) );
index 1a8f6ae..dde29a3 100644 (file)
@@ -26,9 +26,9 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
+#include "unistd.h"
 
 #include "gpgme.h"
 #include "util.h"
@@ -94,6 +94,26 @@ struct gpg_object_s {
     int running;
     int exit_status;
     int exit_signal;
+    
+    /* stuff needed for pipemode */
+    struct {
+        int used;
+        int active;
+        GpgmeData sig;
+        GpgmeData text;
+        int stream_started;
+    } pm;
+
+    /* stuff needed for interactive (command) mode */
+    struct {
+        int used;
+        int fd;
+        GpgmeData cb_data;   /* hack to get init the above fd later */
+        GpgStatusCode code;  /* last code */
+        char *keyword;       /* what has been requested (malloced) */
+        GpgCommandHandler fnc; 
+        void *fnc_value;
+    } cmd;
 };
 
 static void kill_gpg ( GpgObject gpg );
@@ -109,6 +129,11 @@ static GpgmeError read_status ( GpgObject gpg );
 static int gpg_colon_line_handler ( void *opaque, int pid, int fd );
 static GpgmeError read_colon_line ( GpgObject gpg );
 
+static int pipemode_cb ( void *opaque,
+                         char *buffer, size_t length, size_t *nread );
+static int command_cb ( void *opaque,
+                        char *buffer, size_t length, size_t *nread );
+
 
 
 GpgmeError
@@ -128,6 +153,7 @@ _gpgme_gpg_new ( GpgObject *r_gpg )
     gpg->status.fd[1] = -1;
     gpg->colon.fd[0] = -1;
     gpg->colon.fd[1] = -1;
+    gpg->cmd.fd = -1;
 
     /* allocate the read buffer for the status pipe */
     gpg->status.bufsize = 1024;
@@ -150,7 +176,6 @@ _gpgme_gpg_new ( GpgObject *r_gpg )
         sprintf ( buf, "%d", gpg->status.fd[1]);
         _gpgme_gpg_add_arg ( gpg, buf );
     }
-    _gpgme_gpg_add_arg ( gpg, "--batch" );
     _gpgme_gpg_add_arg ( gpg, "--no-tty" );
 
 
@@ -164,6 +189,7 @@ _gpgme_gpg_new ( GpgObject *r_gpg )
     return rc;
 }
 
+
 void
 _gpgme_gpg_release ( GpgObject gpg )
 {
@@ -173,6 +199,8 @@ _gpgme_gpg_release ( GpgObject gpg )
     xfree (gpg->colon.buffer);
     if ( gpg->argv )
         free_argv (gpg->argv);
+    xfree (gpg->cmd.keyword);
+
   #if 0
     /* fixme: We need a way to communicate back closed fds, so that we
      * don't do it a second time.  One way to do it is by using a global
@@ -209,7 +237,13 @@ kill_gpg ( GpgObject gpg )
   #endif
 }
 
-
+void
+_gpgme_gpg_enable_pipemode ( GpgObject gpg )
+{
+    gpg->pm.used = 1;
+    assert ( !gpg->pm.sig );
+    assert ( !gpg->pm.text );
+}
     
 GpgmeError
 _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg )
@@ -218,6 +252,10 @@ _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg )
 
     assert (gpg);
     assert (arg);
+
+    if (gpg->pm.active)
+        return 0;
+
     a = xtrymalloc ( sizeof *a + strlen (arg) );
     if ( !a ) {
         gpg->arg_error = 1;
@@ -239,6 +277,9 @@ _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to )
 
     assert (gpg);
     assert (data);
+    if (gpg->pm.active)
+        return 0;
+
     a = xtrymalloc ( sizeof *a - 1 );
     if ( !a ) {
         gpg->arg_error = 1;
@@ -259,6 +300,45 @@ _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to )
     return 0;
 }
 
+GpgmeError
+_gpgme_gpg_add_pm_data ( GpgObject gpg, GpgmeData data, int what )
+{
+    GpgmeError rc=0;
+
+    assert ( gpg->pm.used );
+    
+    if ( !what ) {
+        /* the signature */
+        assert ( !gpg->pm.sig );
+        gpg->pm.sig = data;
+    }
+    else if (what == 1) {
+        /* the signed data */
+        assert ( !gpg->pm.text );
+        gpg->pm.text = data;
+    }
+    else {
+        assert (0);
+    }
+
+    if ( gpg->pm.sig && gpg->pm.text ) {
+        if ( !gpg->pm.active ) {
+            /* create the callback handler and connect it to stdin */
+            GpgmeData tmp;
+            
+            rc = gpgme_data_new_with_read_cb ( &tmp, pipemode_cb, gpg );
+            if (!rc )
+                rc = _gpgme_gpg_add_data (gpg, tmp, 0);
+        }
+        if ( !rc ) {
+            /* here we can reset the handler stuff */
+            gpg->pm.stream_started = 0;
+        }
+    }
+
+    return rc;
+}
+
 /*
  * Note, that the status_handler is allowed to modifiy the args value
  */
@@ -267,6 +347,9 @@ _gpgme_gpg_set_status_handler ( GpgObject gpg,
                                 GpgStatusHandler fnc, void *fnc_value ) 
 {
     assert (gpg);
+    if (gpg->pm.active)
+        return;
+
     gpg->status.fnc = fnc;
     gpg->status.fnc_value = fnc_value;
 }
@@ -277,6 +360,8 @@ _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
                                     GpgColonLineHandler fnc, void *fnc_value ) 
 {
     assert (gpg);
+    if (gpg->pm.active)
+        return 0;
 
     gpg->colon.bufsize = 1024;
     gpg->colon.readpos = 0;
@@ -295,6 +380,39 @@ _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
 }
 
 
+/* 
+ * The Fnc will be called to get a value for one of the commands with
+ * a key KEY.  If the Code pssed to FNC is 0, the function may release
+ * resources associated with the returned value from another call.  To
+ * match such a second call to a first call, the returned value from
+ * the first call is passed as keyword.
+ */
+
+GpgmeError
+_gpgme_gpg_set_command_handler ( GpgObject gpg,
+                                 GpgCommandHandler fnc, void *fnc_value ) 
+{
+    GpgmeData tmp;
+    GpgmeError err;
+
+    assert (gpg);
+    if (gpg->pm.active)
+        return 0;
+
+    err = gpgme_data_new_with_read_cb ( &tmp, command_cb, gpg );
+    if (err)
+        return err;
+        
+    _gpgme_gpg_add_arg ( gpg, "--command-fd" );
+    _gpgme_gpg_add_data (gpg, tmp, -2);
+    gpg->cmd.cb_data = tmp;
+    gpg->cmd.fnc = fnc;
+    gpg->cmd.fnc_value = fnc_value;
+    gpg->cmd.used = 1;
+    return 0;
+}
+
+
 static void
 free_argv ( char **argv )
 {
@@ -362,6 +480,8 @@ build_argv ( GpgObject gpg )
         argc++;
     if (use_agent)
         argc++;
+    if (!gpg->cmd.used)
+        argc++;
 
     argv = xtrycalloc ( argc+1, sizeof *argv );
     if (!argv)
@@ -398,6 +518,15 @@ build_argv ( GpgObject gpg )
         }
         argc++;
     }
+    if ( !gpg->cmd.used ) {
+        argv[argc] = xtrystrdup ( "--batch" );
+        if (!argv[argc]) {
+            xfree (fd_data_map);
+            free_argv (argv);
+            return mk_error (Out_Of_Core);
+        }
+        argc++;
+    }
     for ( a=gpg->arglist; a; a = a->next ) {
         if ( a->data ) {
             switch ( _gpgme_data_get_mode (a->data) ) {
@@ -453,6 +582,13 @@ build_argv ( GpgObject gpg )
                     fd_data_map[datac].peer_fd  = fds[0];
                 }
             }
+
+            /* Hack to get hands on the fd later */
+            if ( gpg->cmd.used && gpg->cmd.cb_data == a->data ) {
+                assert (gpg->cmd.fd == -1);
+                gpg->cmd.fd = fd_data_map[datac].fd;
+            }
+
             fd_data_map[datac].data = a->data;
             fd_data_map[datac].dup_to = a->dup_to;
             if ( a->dup_to == -1 ) {
@@ -501,6 +637,9 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
     if ( gpg->arg_error )
         return mk_error (Out_Of_Core);
 
+    if (gpg->pm.active)
+        return 0;
+
     rc = build_argv ( gpg );
     if ( rc )
         return rc;
@@ -570,6 +709,8 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
     }
 
     gpg->pid = pid;
+    if (gpg->pm.used)
+        gpg->pm.active = 1;
 
     /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
 
@@ -610,8 +751,11 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
         }
     }
 
-    /* fixme: check what data we can release here */
+    if ( gpg->cmd.used )
+        _gpgme_freeze_fd ( gpg->cmd.fd );
 
+    /* fixme: check what data we can release here */
+    
     gpg->running = 1;
     return 0;
 }
@@ -699,7 +843,7 @@ write_cb_data ( GpgmeData dh, int fd )
         return 1;
     }
     
-    nwritten = _gpgme_io_write ( fd, dh->data+dh->readpos, nbytes );
+    nwritten = _gpgme_io_write ( fd, buffer, nbytes );
     if (nwritten == -1 && errno == EAGAIN )
         return 0;
     if ( nwritten < 1 ) {
@@ -710,6 +854,7 @@ write_cb_data ( GpgmeData dh, int fd )
     }
 
     if ( nwritten < nbytes ) {
+        /* ugly, ugly: It does currently only for for MEM type data */
         if ( _gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten ) )
             fprintf (stderr, "wite_cb_data: unread of %d bytes failed\n",
                      nbytes - nwritten );
@@ -819,8 +964,7 @@ read_status ( GpgObject gpg )
                 *p = 0;
                 fprintf (stderr, "read_status: `%s'\n", buffer);
                 if (!strncmp (buffer, "[GNUPG:] ", 9 )
-                    && buffer[9] >= 'A' && buffer[9] <= 'Z'
-                    && gpg->status.fnc ) {
+                    && buffer[9] >= 'A' && buffer[9] <= 'Z' ) {
                     struct status_table_s t, *r;
                     char *rest;
 
@@ -835,8 +979,30 @@ read_status ( GpgObject gpg )
                     r = bsearch ( &t, status_table, DIM(status_table)-1,
                                   sizeof t, status_cmp );
                     if ( r ) {
-                        gpg->status.fnc ( gpg->status.fnc_value, 
-                                          r->code, rest);
+                        if ( gpg->cmd.used
+                             && ( r->code == STATUS_GET_BOOL
+                                  || r->code == STATUS_GET_LINE
+                                  || r->code == STATUS_GET_HIDDEN )) {
+                            gpg->cmd.code = r->code;
+                            xfree (gpg->cmd.keyword);
+                            gpg->cmd.keyword = xtrystrdup (rest);
+                            if ( !gpg->cmd.keyword )
+                                return mk_error (Out_Of_Core);
+                            /* this should be the last thing we have received
+                             * and the next thing will be that the command
+                             * handler does it action */
+                            if ( nread > 1 )
+                                fprintf (stderr, "** ERROR, unxpected data in"
+                                         " read_status\n" );
+                            _gpgme_thaw_fd (gpg->cmd.fd);
+                        }
+                        else if ( gpg->status.fnc ) {
+                            gpg->status.fnc ( gpg->status.fnc_value, 
+                                              r->code, rest);
+                        }
+                    }
+                    if ( r->code == STATUS_END_STREAM ) {
+                        /* _gpgme_freeze_fd ( ? );*/
                     }
                 }
                 /* To reuse the buffer for the next line we have to
@@ -957,3 +1123,140 @@ read_colon_line ( GpgObject gpg )
     return 0;
 }
 
+static GpgmeError
+pipemode_copy (char *buffer, size_t length, size_t *nread, GpgmeData data )
+{
+    GpgmeError err;
+    int nbytes;
+    char tmp[1000], *s, *d;
+
+    /* we can optimize this whole thing but for now we just
+     * return after each escape character */
+    if (length > 990)
+        length = 990;
+
+    err = gpgme_data_read ( data, tmp, length, &nbytes );
+    if (err)
+        return err;
+    for (s=tmp, d=buffer; nbytes; s++, nbytes--) {
+        *d++ = *s;
+        if (*s == '@' ) {
+            *d++ = '@';
+            break;
+        }
+    }
+    *nread = d - buffer;
+    return 0;
+}
+
+
+static int
+pipemode_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
+{
+    GpgObject gpg = opaque;
+    GpgmeError err;
+
+    if ( !buffer || !length || !nread )
+        return 0; /* those values are reserved for extensions */
+    *nread =0;
+    if ( !gpg->pm.stream_started ) {
+        assert (length > 4 );
+        strcpy (buffer, "@<@B" );
+        *nread = 4;
+        gpg->pm.stream_started = 1;
+    }
+    else if ( gpg->pm.sig ) {
+        err = pipemode_copy ( buffer, length, nread, gpg->pm.sig );
+        if ( err == GPGME_EOF ) {
+            gpg->pm.sig = NULL;
+            assert (length > 4 );
+            strcpy (buffer, "@t" );
+            *nread = 2;
+        }
+        else if (err) {
+            fprintf (stderr, "** pipemode_cb: copy sig failed: %s\n",
+                     gpgme_strerror (err) );
+            return -1;
+        }
+    }
+    else if ( gpg->pm.text ) {
+        err = pipemode_copy ( buffer, length, nread, gpg->pm.text );
+        if ( err == GPGME_EOF ) {
+            gpg->pm.text = NULL;
+            assert (length > 4 );
+            strcpy (buffer, "@.@>" );
+            *nread = 4;
+        }
+        else if (err) {
+            fprintf (stderr, "** pipemode_cb: copy data failed: %s\n",
+                     gpgme_strerror (err) );
+            return -1;
+        }
+    }
+    else {
+        return 0; /* eof */
+    }
+
+    return 0;
+}
+
+
+/* 
+ * Here we handle --command-fd.  This works closely together with
+ * the status handler.  
+ */
+
+static int
+command_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
+{
+    GpgObject gpg = opaque;
+    const char *value;
+    int value_len;
+
+    fprintf (stderr, "** command_cb: enter\n");
+    assert (gpg->cmd.used);
+    if ( !buffer || !length || !nread )
+        return 0; /* those values are reserved for extensions */
+    *nread =0;
+    if ( !gpg->cmd.code ) {
+        fprintf (stderr, "** command_cb: no code\n");
+        return -1;
+    }
+    
+    if ( !gpg->cmd.fnc ) {
+        fprintf (stderr, "** command_cb: no user cb\n");
+        return -1;
+    }
+
+    value = gpg->cmd.fnc ( gpg->cmd.fnc_value, 
+                           gpg->cmd.code, gpg->cmd.keyword );
+    if ( !value ) {
+        fprintf (stderr, "** command_cb: no data from user cb\n");
+        gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
+        return -1;
+    }
+
+    value_len = strlen (value);
+    if ( value_len+1 > length ) {
+        fprintf (stderr, "** command_cb: too much data from user cb\n");
+        gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
+        return -1;
+    }
+
+    memcpy ( buffer, value, value_len );
+    if ( !value_len || (value_len && value[value_len-1] != '\n') ) 
+        buffer[value_len++] = '\n';
+    *nread = value_len;
+    
+    fprintf (stderr, "** command_cb: leave (wrote `%.*s')\n",
+             (int)*nread-1, buffer);
+    gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
+    gpg->cmd.code = 0;
+    /* and sleep again until read_status will wake us up again */
+    _gpgme_freeze_fd ( gpg->cmd.fd );
+    return 0;
+}
+
+
+
+
index 3ab0904..0d7be62 100644 (file)
@@ -81,22 +81,32 @@ typedef enum  {
     STATUS_SESSION_KEY        ,
     STATUS_NOTATION_NAME      ,
     STATUS_NOTATION_DATA      ,
-    STATUS_POLICY_URL
+    STATUS_POLICY_URL         ,
+    STATUS_BEGIN_STREAM       ,
+    STATUS_END_STREAM
 } GpgStatusCode;
 
 typedef void (*GpgStatusHandler)( GpgmeCtx, GpgStatusCode code, char *args ); 
 typedef void (*GpgColonLineHandler)( GpgmeCtx, char *line ); 
+typedef const char *(*GpgCommandHandler)(void*, GpgStatusCode code,
+                                         const char *keyword);
+
 
 GpgmeError _gpgme_gpg_new ( GpgObject *r_gpg );
 void       _gpgme_gpg_release ( GpgObject gpg );
+void       _gpgme_gpg_enable_pipemode ( GpgObject gpg );
 GpgmeError _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg );
 GpgmeError _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to );
+GpgmeError _gpgme_gpg_add_pm_data ( GpgObject gpg, GpgmeData data, int what );
 void       _gpgme_gpg_set_status_handler ( GpgObject gpg,
                                            GpgStatusHandler fnc,
                                            void *fnc_value );
 GpgmeError _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
                                                GpgColonLineHandler fnc,
                                                void *fnc_value );
+GpgmeError _gpgme_gpg_set_command_handler ( GpgObject gpg,
+                                            GpgCommandHandler fnc,
+                                            void *fnc_value );
 
 GpgmeError _gpgme_gpg_spawn ( GpgObject gpg, void *opaque );
 
index 3274f11..11480e0 100644 (file)
@@ -32,6 +32,7 @@
 struct  sign_result_s {
     int no_passphrase;
     int okay;
+    void *last_pw_handle;
 };
 
 
@@ -84,10 +85,48 @@ sign_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
     }
 }
 
+static const char *
+command_handler ( void *opaque, GpgStatusCode code, const char *key )
+{
+    GpgmeCtx c = opaque;
+
+    if ( c->result_type == RESULT_TYPE_NONE ) {
+        assert ( !c->result.sign );
+        c->result.sign = xtrycalloc ( 1, sizeof *c->result.sign );
+        if ( !c->result.sign ) {
+            c->out_of_core = 1;
+            return NULL;
+        }
+        c->result_type = RESULT_TYPE_SIGN;
+    }
+
+    if ( !code ) {
+        /* We have been called for cleanup */
+        if ( c->passphrase_cb ) { 
+            /* Fixme: take the key in account */
+            c->passphrase_cb (c->passphrase_cb_value, 0, 
+                              &c->result.sign->last_pw_handle );
+        }
+        
+        return NULL;
+    }
+
+    if ( !key || !c->passphrase_cb )
+        return NULL;
+    
+    if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
+        return c->passphrase_cb (c->passphrase_cb_value,
+                                 "Please enter your Friedrich Willem!",
+                                 &c->result.sign->last_pw_handle );
+   }
+    
+    return NULL;
+}
 
 
 GpgmeError
-gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out )
+gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out,
+                      GpgmeSigMode mode )
 {
     int rc = 0;
     int i;
@@ -98,23 +137,39 @@ gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out )
     _gpgme_release_result (c);
     c->out_of_core = 0;
 
-    /* do some checks */
-    assert ( !c->gpg );
+
+    if ( mode != GPGME_SIG_MODE_NORMAL
+         && mode != GPGME_SIG_MODE_DETACH
+         && mode != GPGME_SIG_MODE_CLEAR )
+        return mk_error (Invalid_Value);
         
     /* create a process object */
+    _gpgme_gpg_release (c->gpg);
+    c->gpg = NULL;
     rc = _gpgme_gpg_new ( &c->gpg );
     if (rc)
         goto leave;
 
     _gpgme_gpg_set_status_handler ( c->gpg, sign_status_handler, c );
+    if (c->passphrase_cb) {
+        rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c );
+        if (rc)
+            goto leave;
+    }
 
     /* build the commandline */
-    _gpgme_gpg_add_arg ( c->gpg, "--sign" );
-    _gpgme_gpg_add_arg ( c->gpg, "--detach" );
-    if ( c->use_armor )
-        _gpgme_gpg_add_arg ( c->gpg, "--armor" );
-    if ( c->use_textmode )
-        _gpgme_gpg_add_arg ( c->gpg, "--textmode" );
+    if ( mode == GPGME_SIG_MODE_CLEAR ) {
+        _gpgme_gpg_add_arg ( c->gpg, "--clearsign" );
+    }
+    else {
+        _gpgme_gpg_add_arg ( c->gpg, "--sign" );
+        if ( mode == GPGME_SIG_MODE_DETACH )
+            _gpgme_gpg_add_arg ( c->gpg, "--detach" );
+        if ( c->use_armor )
+            _gpgme_gpg_add_arg ( c->gpg, "--armor" );
+        if ( c->use_textmode )
+            _gpgme_gpg_add_arg ( c->gpg, "--textmode" );
+    }
     for ( i=0; i < c->verbosity; i++ )
         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
     
@@ -151,17 +206,26 @@ gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out )
  * @c: The context
  * @in: Data to be signed
  * @out: Detached signature
+ * @mode: Signature creation mode
  * 
  * Create a detached signature for @in and write it to @out.
  * The data will be signed using either the default key or the ones
  * defined through @c.
+ * The defined modes for signature create are:
+ * <literal>
+ * GPGME_SIG_MODE_NORMAL (or 0) 
+ * GPGME_SIG_MODE_DETACH
+ * GPGME_SIG_MODE_CLEAR
+ * </literal>
+ * Note that the settings done by gpgme_set_armor() and gpgme_set_textmode()
+ * are ignore for @mode GPGME_SIG_MODE_CLEAR.
  * 
  * Return value: 0 on success or an error code.
  **/
 GpgmeError
-gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out )
+gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out, GpgmeSigMode mode )
 {
-    GpgmeError err = gpgme_op_sign_start ( c, in, out );
+    GpgmeError err = gpgme_op_sign_start ( c, in, out, mode );
     if ( !err ) {
         gpgme_wait (c, 1);
         if ( c->result_type != RESULT_TYPE_SIGN )
index ce42710..4922d4e 100644 (file)
@@ -15,12 +15,14 @@ static struct status_table_s status_table[] =
   { "BAD_PASSPHRASE", STATUS_BAD_PASSPHRASE },
   { "BEGIN_DECRYPTION", STATUS_BEGIN_DECRYPTION },
   { "BEGIN_ENCRYPTION", STATUS_BEGIN_ENCRYPTION },
+  { "BEGIN_STREAM", STATUS_BEGIN_STREAM },
   { "DECRYPTION_FAILED", STATUS_DECRYPTION_FAILED },
   { "DECRYPTION_OKAY", STATUS_DECRYPTION_OKAY },
   { "DELETE_PROBLEM", STATUS_DELETE_PROBLEM },
   { "ENC_TO", STATUS_ENC_TO },
   { "END_DECRYPTION", STATUS_END_DECRYPTION },
   { "END_ENCRYPTION", STATUS_END_ENCRYPTION },
+  { "END_STREAM", STATUS_END_STREAM },
   { "ENTER", STATUS_ENTER },
   { "ERRMDC", STATUS_ERRMDC },
   { "ERRSIG", STATUS_ERRSIG },
index 4c3e61b..fad5cd9 100644 (file)
@@ -124,6 +124,9 @@ verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
         add_notation ( ctx, code, args );
         break;
 
+      case STATUS_END_STREAM:
+        break;
+
       default:
         /* ignore all other codes */
         fprintf (stderr, "verify_status: code=%d not handled\n", code );
@@ -138,29 +141,30 @@ gpgme_op_verify_start ( GpgmeCtx c,  GpgmeData sig, GpgmeData text )
 {
     int rc = 0;
     int i;
+    int pipemode = 0 /*!!text*/; /* use pipemode for detached sigs */
 
     fail_on_pending_request( c );
     c->pending = 1;
 
     _gpgme_release_result (c);
     c->out_of_core = 0;
-
-    /* create a process object.
-     * To optimize this, we should reuse an existing one and
-     * run gpg in the new --pipemode (I started with this but it is
-     * not yet finished) */
-    if ( c->gpg ) {
-        _gpgme_gpg_release ( c->gpg ); 
+    
+    if ( !pipemode ) {
+        _gpgme_gpg_release ( c->gpg );
         c->gpg = NULL;
     }
-    rc = _gpgme_gpg_new ( &c->gpg );
+
+    if ( !c->gpg ) 
+        rc = _gpgme_gpg_new ( &c->gpg );
     if (rc)
         goto leave;
 
+    if (pipemode)
+        _gpgme_gpg_enable_pipemode ( c->gpg ); 
     _gpgme_gpg_set_status_handler ( c->gpg, verify_status_handler, c );
 
     /* build the commandline */
-    _gpgme_gpg_add_arg ( c->gpg, "--verify" );
+    _gpgme_gpg_add_arg ( c->gpg, pipemode?"--pipemode" : "--verify" );
     for ( i=0; i < c->verbosity; i++ )
         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
 
@@ -178,10 +182,16 @@ gpgme_op_verify_start ( GpgmeCtx c,  GpgmeData sig, GpgmeData text )
         _gpgme_data_set_mode (text, GPGME_DATA_MODE_OUT );
     /* Tell the gpg object about the data */
     _gpgme_gpg_add_arg ( c->gpg, "--" );
-    _gpgme_gpg_add_data ( c->gpg, sig, -1 );
-    if (text) {
-        _gpgme_gpg_add_arg ( c->gpg, "-" );
-        _gpgme_gpg_add_data ( c->gpg, text, 0 );
+    if (pipemode) {
+        _gpgme_gpg_add_pm_data ( c->gpg, sig, 0 );
+        _gpgme_gpg_add_pm_data ( c->gpg, text, 1 );
+    }
+    else {
+        _gpgme_gpg_add_data ( c->gpg, sig, -1 );
+        if (text) {
+            _gpgme_gpg_add_arg ( c->gpg, "-" );
+            _gpgme_gpg_add_data ( c->gpg, text, 0 );
+        }
     }
 
     /* and kick off the process */
@@ -214,6 +224,7 @@ gpgme_op_verify_start ( GpgmeCtx c,  GpgmeData sig, GpgmeData text )
  *                        missing key
  *  GPGME_SIG_STAT_NOSIG: This is not a signature
  *  GPGME_SIG_STAT_ERROR: Due to some other error the check could not be done.
+ *  FIXME: What do we return if only some o the signatures ae valid?
  *
  * Return value: 0 on success or an errorcode if something not related to
  *               the signature itself did go wrong.
index 21d4b1f..fe5e52d 100644 (file)
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <windows.h>
+#include "syshdr.h"
 
 #include "util.h"
 #include "io.h"
@@ -209,6 +209,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
     int duped_stdin = 0;
     int duped_stderr = 0;
     HANDLE hnul = INVALID_HANDLE_VALUE;
+    int debug_me = !!getenv ("GPGME_DEBUG");
 
     memset (&sec_attr, 0, sizeof sec_attr );
     sec_attr.nLength = sizeof sec_attr;
@@ -220,7 +221,8 @@ _gpgme_io_spawn ( const char *path, char **argv,
 
     memset (&si, 0, sizeof si);
     si.cb = sizeof (si);
-    si.dwFlags = STARTF_USESTDHANDLES;
+    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    si.wShowWindow = debug_me? SW_SHOW : SW_HIDE;
     si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
     si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
     si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
@@ -268,7 +270,7 @@ _gpgme_io_spawn ( const char *path, char **argv,
         }
         /* We normally don't want all the normal output */
         if ( !duped_stderr ) {
-            if (!getenv ("GPGME_DEBUG") ) {
+            if (!debug_me) {
                 si.hStdError = hnul;
                 DEBUG_SELECT ((stderr,"** using %d for stderr\n", (int)hnul ));
             }
@@ -340,7 +342,7 @@ _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
 
     *r_status = 0;
     *r_signal = 0;
-    code = WaitForSingleObject ( proc, hang? INFINITE : NULL );
+    code = WaitForSingleObject ( proc, hang? INFINITE : 0 );
     switch (code) {
       case WAIT_FAILED:
         fprintf (stderr, "** WFSO pid=%d failed: %d\n",
@@ -565,8 +567,9 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
         }
     }
     if ( !once_more && !count ) {
+        /* once more but after relinquishing our timeslot */
         once_more = 1;
-        Sleep (300);
+        Sleep (0);
         goto restart;
     }
 
index a337ad0..b024b09 100644 (file)
@@ -24,9 +24,8 @@
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
-#include <sys/time.h>
 #include <sys/types.h>
-#include <unistd.h>
+#include "syshdr.h"
 
 #include "util.h"
 #include "context.h"
@@ -236,7 +235,8 @@ do_select ( void )
         return 0; /* error or timeout */
 
     for (i=0; i < fd_table_size /*&& n*/; i++ ) {
-        if ( fd_table[i].fd != -1 && fd_table[i].signaled ) {
+        if ( fd_table[i].fd != -1 && fd_table[i].signaled 
+             && !fd_table[i].frozen ) {
             q = fd_table[i].opaque;
             assert (n);
             n--;
@@ -261,7 +261,7 @@ do_select ( void )
  * called by rungpg.c to register something for select()
  */
 GpgmeError
-_gpgme_register_pipe_handler( void *opaque, 
+_gpgme_register_pipe_handler ( void *opaque, 
                               int (*handler)(void*,int,int),
                               void *handler_value,
                               int pid, int fd, int inbound )
@@ -292,6 +292,7 @@ _gpgme_register_pipe_handler( void *opaque,
             fd_table[i].for_read = inbound;    
             fd_table[i].for_write = !inbound;    
             fd_table[i].signaled = 0;
+            fd_table[i].frozen = 0;
             fd_table[i].opaque = q;
             unlock_table ();
             return 0;
@@ -318,6 +319,38 @@ _gpgme_register_pipe_handler( void *opaque,
 }
 
 
+void
+_gpgme_freeze_fd ( int fd )
+{
+    int i;
+
+    lock_table ();
+    for (i=0; i < fd_table_size; i++ ) {
+        if ( fd_table[i].fd == fd ) {
+            fd_table[i].frozen = 1;
+            fprintf (stderr, "** FD %d frozen\n", fd );
+            break;
+        }
+    }
+    unlock_table ();
+}
+
+void
+_gpgme_thaw_fd ( int fd )
+{
+    int i;
+
+    lock_table ();
+    for (i=0; i < fd_table_size; i++ ) {
+        if ( fd_table[i].fd == fd ) {
+            fd_table[i].frozen = 0;
+            fprintf (stderr, "** FD %d thawed\n", fd );
+            break;
+        }
+    }
+    unlock_table ();
+}
+
 
 
 
index 5e03d45..51d1195 100644 (file)
@@ -22,7 +22,7 @@ all-local: ./pubring.gpg ./secring.gpg
        -gpg --homedir . --import $(srcdir)/pubdemo.asc
 
 ./secring.gpg: ./Alpha/Secret.gpg 
-       -gpg --homedir . --import Alpha/Secret.gpg Zulu/Secret.gpg
+       -gpg --homedir . --allow-secret-key-import --import Alpha/Secret.gpg Zulu/Secret.gpg
 
 ./Alpha/Secret.gpg: secdemo.asc 
        srcdir=$(srcdir) $(srcdir)/mkdemodirs 
index dd64689..677d382 100644 (file)
@@ -57,28 +57,23 @@ print_data ( GpgmeData dh )
 }
 
 
-static int
-passphrase_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
+static const char *
+passphrase_cb ( void *opaque, const char *desc, void *r_hd )
 {
-    struct passphrase_cb_info_s *info = opaque;
-    const char *desc;
-
-    assert (info);
-    assert (info->c);
-    if ( !buffer || !length || !nread )
-        return 0; /* those values are reserved for extensions */
-    if ( info->did_it )
-        return -1; /* eof */
-
-    desc = gpgme_get_prompt (info->c, 1);
-    if (desc)
-        fprintf (stderr, "Request passphrase for '%s'\n", desc );
-    if ( length < 3 )
-        return -1; /* FIXME - sending an EOF here is wrong */
-    memcpy (buffer, "abc", 3 );
-    *nread = 3;
-    info->did_it = 1;
-    return 0;
+    const char *pass;
+
+    if ( !desc ) {
+        /* cleanup by looking at *r_hd */
+
+        
+        return NULL;
+    }
+
+    pass = "abc";
+    fprintf (stderr, "%% requesting passphrase for `%s': ", desc );
+    fprintf (stderr, "sending `%s'\n", pass );
+
+    return pass;
 }
 
 
@@ -111,10 +106,10 @@ main (int argc, char **argv )
   do {
     err = gpgme_new (&ctx);
     fail_if_err (err);
-    if ( 0 && !getenv("GPG_AGENT_INFO") ) {
+    if ( !getenv("GPG_AGENT_INFO") ) {
         memset ( &info, 0, sizeof info );
         info.c = ctx;
-        gpgme_data_new_with_read_cb ( &pwdata, passphrase_cb, &info );
+        gpgme_set_passphrase_cb ( ctx, passphrase_cb, &info );
     } 
 
     err = gpgme_data_new_from_file ( &in, cipher_1_asc, 1 );
@@ -123,7 +118,7 @@ main (int argc, char **argv )
     err = gpgme_data_new ( &out );
     fail_if_err (err);
 
-    err = gpgme_op_decrypt (ctx, pwdata, in, out );
+    err = gpgme_op_decrypt (ctx, in, out );
     fail_if_err (err);
 
     fflush (NULL);
index c09b2c9..79f6b5c 100644 (file)
@@ -47,6 +47,24 @@ print_data ( GpgmeData dh )
         fail_if_err (err);
 }
 
+static const char *
+passphrase_cb ( void *opaque, const char *desc, void *r_hd )
+{
+    const char *pass;
+
+    if ( !desc ) {
+        /* cleanup by looking at *r_hd */
+
+        
+        return NULL;
+    }
+
+    pass = "abc";
+    fprintf (stderr, "%% requesting passphrase for `%s': ", desc );
+    fprintf (stderr, "sending `%s'\n", pass );
+
+    return pass;
+}
 
 
 int 
@@ -59,25 +77,55 @@ main (int argc, char **argv )
   do {
     err = gpgme_new (&ctx);
     fail_if_err (err);
+    if ( !getenv("GPG_AGENT_INFO") ) {
+        gpgme_set_passphrase_cb ( ctx, passphrase_cb, NULL );
+    } 
+
+    gpgme_set_textmode (ctx, 1);
+    gpgme_set_armor (ctx, 1);
 
     err = gpgme_data_new_from_mem ( &in, "Hallo Leute\n", 12, 0 );
     fail_if_err (err);
 
+    /* first a normal signature */
     err = gpgme_data_new ( &out );
     fail_if_err (err);
-
-    gpgme_set_textmode (ctx, 1);
-    gpgme_set_armor (ctx, 1);
-    err = gpgme_op_sign (ctx, in, out );
+    err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL );
+    fail_if_err (err);
+    fflush (NULL);
+    fputs ("Begin Result:\n", stdout );
+    print_data (out);
+    fputs ("End Result.\n", stdout );
+    gpgme_data_release (out);
+    gpgme_data_rewind (in);
+    
+    /* now a detached signature */
+    err = gpgme_data_new ( &out );
     fail_if_err (err);
+    err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH );
+    fail_if_err (err);
+    fflush (NULL);
+    fputs ("Begin Result:\n", stdout );
+    print_data (out);
+    fputs ("End Result.\n", stdout );
+    gpgme_data_release (out);
+    gpgme_data_rewind (in);
+    
 
+    /* And finally a cleartext signature */
+    err = gpgme_data_new ( &out );
+    fail_if_err (err);
+    err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_CLEAR );
+    fail_if_err (err);
     fflush (NULL);
     fputs ("Begin Result:\n", stdout );
     print_data (out);
     fputs ("End Result.\n", stdout );
-   
-    gpgme_data_release (in);
     gpgme_data_release (out);
+    gpgme_data_rewind (in);
+    
+    /* ready */
+    gpgme_data_release (in);
     gpgme_release (ctx);
   } while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
    
index ac9e337..2b91a99 100644 (file)
@@ -35,7 +35,7 @@ static const char test_sig1[] =
 "ZgIAn0204PBR7yxSdQx6CFxugstNqmRv\n"
 "=yku6\n"
 "-----END PGP SIGNATURE-----\n"
-#elif 0 
+#elif 0
 "-----BEGIN PGP SIGNATURE-----\n"
 "Version: GnuPG v1.0.4-2 (GNU/Linux)\n"
 "Comment: For info see http://www.gnupg.org\n"
@@ -108,14 +108,19 @@ main (int argc, char **argv )
     err = gpgme_data_new_from_mem ( &text,
                                     test_text1, strlen (test_text1), 0 );
     fail_if_err (err);
+  #if 1
     err = gpgme_data_new_from_mem ( &sig,
                                     test_sig1, strlen (test_sig1), 0 );
+  #else
+    err = gpgme_data_new_from_file ( &sig, "xx1", 1 );
+  #endif
     fail_if_err (err);
 
     puts ("checking a valid message:\n");
     err = gpgme_op_verify (ctx, sig, text, &status );
     print_sig_stat ( status );
     fail_if_err (err);
+
     if ( (nota=gpgme_get_notation (ctx)) )
         printf ("---Begin Notation---\n%s---End Notation---\n", nota );