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.
## 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
--- /dev/null
+@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.
--- /dev/null
+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.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
--- /dev/null
+/* 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) */
+
+
+
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/* 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_ */
--- /dev/null
+/* 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 */
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+/* 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*/
+
+
+
+
+
+
+
+
+
+
+
#include <time.h>
#include <windows.h>
+#include "obj_base.h"
+
#include "argparse.h"
#include "main.h"
{ oEmbedding, "Embedding" , 0, "@" },
{0} };
+
+
+
static const char *
my_strusage( int level )
{
{
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, ® );
+ REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, ® );
CoResumeClassObjects ();
- #endif
WaitForSingleObject ( running, INFINITE );
CloseHandle (running);
- #if 0
CoRevokeClassObject ( reg );
- factory->release ();
- CoUnitialize ();
- #endif
+ gnupg_factory_release (factory);
+ CoUninitialize ();
}
-
-
-
-
} opt;
+/*-- ignupg.c --*/
+IClassFactory *gnupg_factory_new ( CLSID *r_clsid );
+void gnupg_factory_release ( IClassFactory *factory );
+
#endif /* COMPLUS_MAIN_H */
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */
# 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
AC_SUBST(LIBGPGME_LT_REVISION)
+AM_MAINTAINER_MODE
+
dnl
dnl Checks for programs
dnl
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
GPG='c:\\gnupg\\gpg.exe'
- component_system='COM+'
+ #component_system='COM+'
;;
*)
;;
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
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;
};
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
-
+#include "syshdr.h"
#include "util.h"
#include "context.h"
int no_passphrase;
int okay;
int failed;
-
+ void *last_pw_handle;
};
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:
}
}
+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;
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 ) {
/**
* gpgme_op_decrypt:
* @c: The context
- * @passphrase: A data object with the passphrase or NULL.
* @in: ciphertext input
* @out: plaintext output
*
* 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 )
c->verbosity = 1;
c->use_armor = 1; /* fixme: reset this to 0 */
*r_ctx = c;
+
return 0;
}
_gpgme_key_release ( c->tmp_key );
gpgme_data_release ( c->notation );
/* fixme: release the key_queue */
- xfree (c->prompt_1);
xfree (c);
}
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;
-}
-
-
-
-
-
-
* 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"
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);
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 );
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 );
/* 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 );
int for_read;
int for_write;
int signaled;
+ int frozen;
void *opaque;
};
/*-- 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 --*/
#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"
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)
}
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) );
#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"
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 );
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
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;
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" );
return rc;
}
+
void
_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
#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 )
assert (gpg);
assert (arg);
+
+ if (gpg->pm.active)
+ return 0;
+
a = xtrymalloc ( sizeof *a + strlen (arg) );
if ( !a ) {
gpg->arg_error = 1;
assert (gpg);
assert (data);
+ if (gpg->pm.active)
+ return 0;
+
a = xtrymalloc ( sizeof *a - 1 );
if ( !a ) {
gpg->arg_error = 1;
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
*/
GpgStatusHandler fnc, void *fnc_value )
{
assert (gpg);
+ if (gpg->pm.active)
+ return;
+
gpg->status.fnc = fnc;
gpg->status.fnc_value = fnc_value;
}
GpgColonLineHandler fnc, void *fnc_value )
{
assert (gpg);
+ if (gpg->pm.active)
+ return 0;
gpg->colon.bufsize = 1024;
gpg->colon.readpos = 0;
}
+/*
+ * 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 )
{
argc++;
if (use_agent)
argc++;
+ if (!gpg->cmd.used)
+ argc++;
argv = xtrycalloc ( argc+1, sizeof *argv );
if (!argv)
}
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) ) {
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 ) {
if ( gpg->arg_error )
return mk_error (Out_Of_Core);
+ if (gpg->pm.active)
+ return 0;
+
rc = build_argv ( gpg );
if ( rc )
return rc;
}
gpg->pid = pid;
+ if (gpg->pm.used)
+ gpg->pm.active = 1;
/*_gpgme_register_term_handler ( closure, closure_value, pid );*/
}
}
- /* 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;
}
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 ) {
}
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 );
*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;
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
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;
+}
+
+
+
+
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 );
struct sign_result_s {
int no_passphrase;
int okay;
+ void *last_pw_handle;
};
}
}
+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;
_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" );
* @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 )
{ "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 },
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 );
{
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" );
_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 */
* 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.
#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"
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;
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);
}
/* 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 ));
}
*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",
}
}
if ( !once_more && !count ) {
+ /* once more but after relinquishing our timeslot */
once_more = 1;
- Sleep (300);
+ Sleep (0);
goto restart;
}
#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"
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--;
* 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 )
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;
}
+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 ();
+}
+
-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
}
-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;
}
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 );
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);
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
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" ) );
"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"
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 );