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