Lösungsvorschläge zum Übungsblatt 12: … · Fortgeschrittene Aspekte objektorientierter...

32
Prof. Dr. A. Poetzsch-Heffter Dipl.-Inform. N. Rauch Technische Universität Kaiserslautern Fachbereich Informatik AG Softwaretechnik http://softech.informatik.uni-kl.de/fasoop Lösungsvorschläge zum Übungsblatt 12: Fortgeschrittene Aspekte objektorientierter Programmierung (WS 2005/06) Aufgabe 1 Virtual Types Eine mögliche Lösung siehe Main.java. Aufgabe 2 COM Proxy/Stub basic.idl enthält die Schnittstellendefinition der Komponente: Die Interfaces mit den bereitgestellten Methoden sowie die Komponente mit den darin befindlichen Klassen und den Interfaces, über die mit den Klassen kommuniziert werden kann. Die Datei wird übersetzt mit midl $(MIDL_FLAGS) $(MIDL_DEFINES) $(MIDL_INCLUDES) -out ./obj -tlb basic.tlb \ basic.idl und erzeugt die Dateien basic.h, basic_i.c, basic_p.c, dlldata.c und basic.tlb. /*============================================================================= * *+++ * * Copyright (c) Software AG 1996 - 99. All rights reserved. * *--- * * File: basic.idl * * History: * =============================================================================*/ [ uuid(9BD1C111-12C9-11D0-8E35-0020AFC81B8A), object, pointer_default(unique), helpstring("An interface for sending text") ] interface ISender : IUnknown { import "unknwn.idl"; HRESULT SendText([in, string] const OLECHAR *pwsz); } [ uuid(9BD1C112-12C9-11D0-8E35-0020AFC81B8A),

Transcript of Lösungsvorschläge zum Übungsblatt 12: … · Fortgeschrittene Aspekte objektorientierter...

Prof. Dr. A. Poetzsch-HeffterDipl.-Inform. N. Rauch

Technische Universität KaiserslauternFachbereich Informatik

AG Softwaretechnikhttp://softech.informatik.uni-kl.de/fasoop

Lösungsvorschläge zum Übungsblatt 12:Fortgeschrittene Aspekte objektorientierter Programmierung

(WS 2005/06)

Aufgabe 1 Virtual Types

Eine mögliche Lösung siehe Main.java.

Aufgabe 2 COM

Proxy/Stub

basic.idl enthält die Schnittstellendefinition der Komponente: Die Interfaces mit den bereitgestellten Methoden sowiedie Komponente mit den darin befindlichen Klassen und den Interfaces, über die mit den Klassen kommuniziertwerden kann.

Die Datei wird übersetzt mit

midl $(MIDL_FLAGS) $(MIDL_DEFINES) $(MIDL_INCLUDES) -out ./obj -tlb basic.tlb \basic.idl

und erzeugt die Dateien basic.h, basic_i.c, basic_p.c, dlldata.c und basic.tlb.

/*=============================================================================**+++** Copyright (c) Software AG 1996 - 99. All rights reserved.**---** File: basic.idl** History:*=============================================================================*/

[uuid(9BD1C111-12C9-11D0-8E35-0020AFC81B8A),object,pointer_default(unique),helpstring("An interface for sending text")

]interface ISender : IUnknown{

import "unknwn.idl";

HRESULT SendText([in, string] const OLECHAR *pwsz);}

[uuid(9BD1C112-12C9-11D0-8E35-0020AFC81B8A),

object,pointer_default(unique),helpstring("An interface for receiving text")

]interface IReceiver : IUnknown{

HRESULT ReceiveText([out, string] OLECHAR **ppwsz);}

[uuid(9BD1C110-12C9-11D0-8E35-0020AFC81B8A),version(1.0),lcid(9),helpstring("Basic DCOM sample")

]library BasicLib{

importlib("stdole32.tlb");[

uuid(9BD1C113-12C9-11D0-8E35-0020AFC81B8A),helpstring("An implementation that only supports queries")

]coclass CReadOnly{

interface IReceiver;}

[uuid(9BD1C114-12C9-11D0-8E35-0020AFC81B8A),helpstring("An implementation that only supports everything")

]coclass CReadWrite{

interface IReceiver;interface ISender;

}}

basicps.def enthält die beschreibt die Schnittstelle der Shared Library, aus der der Proxy / Stub besteht. Sie wirdübersetzt durch

makedef -EDllMain $(C_DEFINES) $(C_INCLUDES) $(MAKEDEF_FLAGS) basicps.def \obj/basicps_def.cxx

LIBRARY basicpsEXPORTS

DllGetClassObject @1 PRIVATEDllCanUnloadNow @2 PRIVATEDllRegisterServer @3 PRIVATEDllUnregisterServer @4 PRIVATEGetProxyDllInfo @5 PRIVATE

basicsvc_def.cxx enthält DLL-Code, der die generische Schnittstelle der Komponente deklariert. Die Datei wird über-setzt durch

g++ -c -o basicps_def.o basicps_def.cxx $(CC_FLAGS) $(C_DEFINES) $(C_INCLUDES)

und erzeugt basicps_def.o.

/** this is a generated file, do not edit

2

** build by rauch on tux3 from basicps.def** if you edit this file, its checksum will no longer match and* then the procedure generating this file will reject to overwrite* such a changed file. if this happens, the only thing you can do* is deleting such a changed file by hand.*/

#include <mutantsl.h>

#define MutantDllWithoutLoadLibraryAndDllMain

#define VerboseEnabled 0

#if VerboseEnabled#include <stdio.h>#define IfVerbose(X) do { X; } while (0);#else#define IfVerbose(X) /* empty */#endif

extern "C" {typedef void (* EXPORT_FUNC) ();

}extern "C" void DllCanUnloadNow (void);extern "C" void DllGetClassObject (void);extern "C" void DllRegisterServer (void);extern "C" void DllUnregisterServer (void);extern "C" void GetProxyDllInfo (void);

/** definition of the library name and description*/

static const char *g_LibraryName = "basicps";static const char *g_LibraryDesc = "";

/** list of all exported names*/

static MutantDllHeaderExportEntry g_MutantDllExports[] = {/* BEGIN */{"DllCanUnloadNow", (EXPORT_FUNC)DllCanUnloadNow},{"DllGetClassObject", (EXPORT_FUNC)DllGetClassObject},{"DllRegisterServer", (EXPORT_FUNC)DllRegisterServer},{"DllUnregisterServer", (EXPORT_FUNC)DllUnregisterServer},{"GetProxyDllInfo", (EXPORT_FUNC)GetProxyDllInfo},/* END */{0, 0}

};

/** the header of the dll*/

extern "C" void DllMain (void);

#include <memory.h>

3

static MutantDllHeader *g_pMutantDllHeader;

MutantDllHeader::MutantDllHeader(){

Version = MutantDllHeaderVersion;pEntryPoint = DllMain;numEntries = sizeof (g_MutantDllExports) / sizeof(g_MutantDllExports[0]) - 1;ExportList = g_MutantDllExports;DllName = g_LibraryName;DllDescription = g_LibraryDesc;memset(ReservedAndMustBeZero, 0, sizeof(ReservedAndMustBeZero));

}

/** support of linux compilers egcs and gnu*/

#include <stdio.h>#include <errno.h>static int numCalls = 0;

/** for Linux this is run before all static constructors. this is the* time to start memory owner logging.*/

void MutantDllFinalizerFetchHeader (MutantDllHeader **ppMutantDllHeader){

g_pMutantDllHeader = new MutantDllHeader();*ppMutantDllHeader = g_pMutantDllHeader;

}

static void MutantAtInit(void){

if ( numCalls++ == 0 ) {

MutantDllFinalizerProvider(g_pMutantDllHeader); /* used to load final.o from{mutant,windu}stubs */

MutantDllInitializerPostCons(g_pMutantDllHeader);

}}

void (* MutantStartup2Init)(void) __attribute__ ((section (".ctors"))) = MutantAtInit;

/** for Linux this is run before all static destructors. this is the* time to run the DLL main function with DLL_PROCESS_DETACH as reason.*/

static void MutantAtExit(){

if ( --numCalls == 0 ) {MutantDllFinalizerPreDest(g_pMutantDllHeader);

}}

4

void (* MutantStartup2Exit)(void) __attribute__ ((section (".dtors"))) = MutantAtExit;

/* Checksum = 1542545067 2975 ./obj/basicps_def.cxx */

basic_i.c enthält die Interface-IDs und Klassen-IDs, die zur eindeutigen Identifizierung einer Komponente verwendetwerden.

#pragma warning( disable: 4049 ) /* more than 64k source lines */

/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */

/* link this file in with the server and any clients */

/* File created by MIDL compiler version 5.03.0279 *//* at Sun Feb 12 14:41:39 2006

*//* Compiler settings for basic.idl:

Os (OptLev=s), W1, Zp4, env=Unix (32b run) wchar=4bytes, ms_ext, c_exterror checks: allocation ref bounds_check enum stub_dataVC __declspec() decoration level:

__declspec(uuid()), __declspec(selectany), __declspec(novtable)DECLSPEC_UUID(), MIDL_INTERFACE()

*///@@MIDL_FILE_HEADING( )

#if !defined(_M_IA64) && !defined(_M_AXP64)#include <sagenv.h>

#include <cooldef.h>

#ifdef __cplusplusextern "C"{#endif

#ifdef _MIDL_USE_GUIDDEF_

#ifndef INITGUID#define INITGUID#include <guiddef.h>#undef INITGUID#else#include <guiddef.h>#endif

#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)

#else // !_MIDL_USE_GUIDDEF_

#ifndef __IID_DEFINED__#define __IID_DEFINED__

typedef struct _IID{

5

ULONG x;unsigned short s1;unsigned short s2;unsigned char c[8];

} IID;

#endif // __IID_DEFINED__

#ifndef CLSID_DEFINED#define CLSID_DEFINEDtypedef IID CLSID;#endif // CLSID_DEFINED

#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}

#endif // !_MIDL_USE_GUIDDEF_

MIDL_DEFINE_GUID(IID, IID_ISender,0x9BD1C111,0x12C9,0x11D0,0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A);

MIDL_DEFINE_GUID(IID, IID_IReceiver,0x9BD1C112,0x12C9,0x11D0,0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A);

MIDL_DEFINE_GUID(IID, LIBID_BasicLib,0x9BD1C110,0x12C9,0x11D0,0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A);

MIDL_DEFINE_GUID(CLSID, CLSID_CReadOnly,0x9BD1C113,0x12C9,0x11D0,0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A);

MIDL_DEFINE_GUID(CLSID, CLSID_CReadWrite,0x9BD1C114,0x12C9,0x11D0,0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A);

#undef MIDL_DEFINE_GUID

#ifdef __cplusplus}#endif

#endif /* !defined(_M_IA64) && !defined(_M_AXP64)*/

basic_p.c enthält den Proxy Stub code, d.h. Funktionen, die Proxies für die in den Interfaces deklarierten Funktionendarstellen.

#pragma warning( disable: 4049 ) /* more than 64k source lines */

/* this ALWAYS GENERATED file contains the proxy stub code */

/* File created by MIDL compiler version 5.03.0279 *//* at Sun Feb 12 14:41:39 2006

*//* Compiler settings for basic.idl:

Os (OptLev=s), W1, Zp4, env=Unix (32b run) wchar=4bytes, ms_ext, c_exterror checks: allocation ref bounds_check enum stub_dataVC __declspec() decoration level:

__declspec(uuid()), __declspec(selectany), __declspec(novtable)DECLSPEC_UUID(), MIDL_INTERFACE()

6

*///@@MIDL_FILE_HEADING( )

#if !defined(_M_IA64) && !defined(_M_AXP64)

/* verify that the <rpcproxy.h> version is high enough to compile this file*/#ifndef __REDQ_RPCPROXY_H_VERSION__#define __REQUIRED_RPCPROXY_H_VERSION__ 440#endif

#include <sagenv.h>

#include "rpcproxy.h"#include <coolvtable.h>

#include "basic.h"

#define TYPE_FORMAT_STRING_SIZE 15#define PROC_FORMAT_STRING_SIZE 13#define TRANSMIT_AS_TABLE_SIZE 0#define WIRE_MARSHAL_TABLE_SIZE 0

typedef struct _MIDL_TYPE_FORMAT_STRING{short Pad;unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];} MIDL_TYPE_FORMAT_STRING;

typedef struct _MIDL_PROC_FORMAT_STRING{short Pad;unsigned char Format[ PROC_FORMAT_STRING_SIZE ];} MIDL_PROC_FORMAT_STRING;

extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;

/* Object interface: IUnknown, ver. 0.0,GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */

/* Object interface: ISender, ver. 0.0,GUID={0x9BD1C111,0x12C9,0x11D0,{0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A}} */

extern const MIDL_STUB_DESC Object_StubDesc;

/* #pragma code_seg(".orpc") */

HRESULT STDMETHODCALLTYPE ISender_SendText_Proxy(ISender __RPC_FAR * This,/* [string][in] */ const OLECHAR __RPC_FAR *pwsz)

{

HRESULT _RetVal;

7

RPC_MESSAGE _RpcMessage;

MIDL_STUB_MESSAGE _StubMsg;

RpcTryExcept{NdrProxyInitialize(

( void __RPC_FAR * )This,( PRPC_MESSAGE )&_RpcMessage,( PMIDL_STUB_MESSAGE )&_StubMsg,( PMIDL_STUB_DESC )&Object_StubDesc,3);

if(!pwsz){RpcRaiseException(RPC_X_NULL_REF_POINTER);}

RpcTryFinally{

_StubMsg.BufferLength = 12U;_StubMsg.BufferLength += 7; /* fix potential alignment problem */

NdrConformantStringBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,(unsigned char __RPC_FAR *)pwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[4] );

NdrProxyGetBuffer(This, &_StubMsg);NdrConformantStringMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,

(unsigned char __RPC_FAR *)pwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[4] );

NdrProxySendReceive(This, &_StubMsg);

if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[0] );

_RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer);_StubMsg.Buffer += sizeof( HRESULT );

}RpcFinally

{NdrProxyFreeBuffer(This, &_StubMsg);

}RpcEndFinally

}RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)

{_RetVal = NdrProxyErrorHandler(RpcExceptionCode());}

RpcEndExceptreturn _RetVal;

}

void __RPC_STUB ISender_SendText_Stub(

8

IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase)

{HRESULT _RetVal;MIDL_STUB_MESSAGE _StubMsg;const OLECHAR __RPC_FAR *pwsz;

NdrStubInitialize(_pRpcMessage,&_StubMsg,&Object_StubDesc,_pRpcChannelBuffer);

pwsz = 0;RpcTryFinally

{if ( (_pRpcMessage->DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )

NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[0] );

NdrConformantStringUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,(unsigned char __RPC_FAR * __RPC_FAR *)&pwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[4],(unsigned char)0 );

*_pdwStubPhase = STUB_CALL_SERVER;_RetVal = ISender_SendText((ISender *) ((CStdStubBuffer *)This)->pvServerObject,pwsz);

*_pdwStubPhase = STUB_MARSHAL;

_StubMsg.BufferLength = 4U;_StubMsg.BufferLength += 16;

NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);*(( HRESULT __RPC_FAR * )_StubMsg.Buffer) = _RetVal;_StubMsg.Buffer += sizeof( HRESULT );

}RpcFinally

{if ( pwsz )

_StubMsg.pfnFree( (void *) pwsz );

}RpcEndFinally_pRpcMessage->BufferLength =

(unsigned int)(_StubMsg.Buffer - (unsigned char __RPC_FAR *)_pRpcMessage->Buffer);

}

const CINTERFACE_PROXY_VTABLE(VTABLE_SIZE2( 4 ) ) _ISenderProxyVtbl ={

{ &IID_ISender },BEGIN_VTABLE2VTABLE_ENTRY2( IUnknown_QueryInterface_Proxy ),VTABLE_ENTRY2( IUnknown_AddRef_Proxy ),VTABLE_ENTRY2( IUnknown_Release_Proxy ), VTABLE_ENTRY2( ISender_SendText_Proxy )END_VTABLE2

9

};

static const PRPC_STUB_FUNCTION ISender_table[] ={

(PRPC_STUB_FUNCTION) ISender_SendText_Stub};

const CInterfaceStubVtbl _ISenderStubVtbl ={

{ &IID_ISender,0,4,&ISender_table[-3] },CStdStubBuffer_METHODS

};

/* Object interface: IReceiver, ver. 0.0,GUID={0x9BD1C112,0x12C9,0x11D0,{0x8E,0x35,0x00,0x20,0xAF,0xC8,0x1B,0x8A}} */

extern const MIDL_STUB_DESC Object_StubDesc;

/* #pragma code_seg(".orpc") */

HRESULT STDMETHODCALLTYPE IReceiver_ReceiveText_Proxy(IReceiver __RPC_FAR * This,/* [string][out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppwsz)

{

HRESULT _RetVal;

RPC_MESSAGE _RpcMessage;

MIDL_STUB_MESSAGE _StubMsg;

if(ppwsz){*ppwsz = 0;}

RpcTryExcept{NdrProxyInitialize(

( void __RPC_FAR * )This,( PRPC_MESSAGE )&_RpcMessage,( PMIDL_STUB_MESSAGE )&_StubMsg,( PMIDL_STUB_DESC )&Object_StubDesc,3);

if(!ppwsz){RpcRaiseException(RPC_X_NULL_REF_POINTER);}

RpcTryFinally{

10

_StubMsg.BufferLength = 0U;NdrProxyGetBuffer(This, &_StubMsg);NdrProxySendReceive(This, &_StubMsg);

if ( (_RpcMessage.DataRepresentation & 0X0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION )NdrConvert( (PMIDL_STUB_MESSAGE) &_StubMsg, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[6] );

NdrPointerUnmarshall( (PMIDL_STUB_MESSAGE) &_StubMsg,(unsigned char __RPC_FAR * __RPC_FAR *)&ppwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[6],(unsigned char)0 );

_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((LONG_PTR)_StubMsg.Buffer + 3) & ~ 0x3);_RetVal = *(( HRESULT __RPC_FAR * )_StubMsg.Buffer);_StubMsg.Buffer += sizeof( HRESULT );

}RpcFinally

{NdrProxyFreeBuffer(This, &_StubMsg);

}RpcEndFinally

}RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)

{NdrClearOutParameters(

( PMIDL_STUB_MESSAGE )&_StubMsg,( PFORMAT_STRING )&__MIDL_TypeFormatString.Format[6],( void __RPC_FAR * )ppwsz);

_RetVal = NdrProxyErrorHandler(RpcExceptionCode());}

RpcEndExceptreturn _RetVal;

}

void __RPC_STUB IReceiver_ReceiveText_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase)

{OLECHAR __RPC_FAR *_M4;HRESULT _RetVal;MIDL_STUB_MESSAGE _StubMsg;OLECHAR __RPC_FAR *__RPC_FAR *ppwsz;

NdrStubInitialize(_pRpcMessage,&_StubMsg,&Object_StubDesc,_pRpcChannelBuffer);

ppwsz = 0;RpcTryFinally

{ppwsz = &_M4;_M4 = 0;

*_pdwStubPhase = STUB_CALL_SERVER;

11

_RetVal = IReceiver_ReceiveText((IReceiver *) ((CStdStubBuffer *)This)->pvServerObject,ppwsz);

*_pdwStubPhase = STUB_MARSHAL;

_StubMsg.BufferLength = 16U + 10U;_StubMsg.BufferLength += 7; /* fix potential alignment problem */

NdrPointerBufferSize( (PMIDL_STUB_MESSAGE) &_StubMsg,(unsigned char __RPC_FAR *)ppwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[6] );

_StubMsg.BufferLength += 16;

NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);NdrPointerMarshall( (PMIDL_STUB_MESSAGE)& _StubMsg,

(unsigned char __RPC_FAR *)ppwsz,(PFORMAT_STRING) &__MIDL_TypeFormatString.Format[6] );

_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((LONG_PTR)_StubMsg.Buffer + 3) & ~ 0x3);*(( HRESULT __RPC_FAR * )_StubMsg.Buffer) = _RetVal;_StubMsg.Buffer += sizeof( HRESULT );

}RpcFinally

{NdrPointerFree( &_StubMsg,

(unsigned char __RPC_FAR *)ppwsz,&__MIDL_TypeFormatString.Format[6] );

}RpcEndFinally_pRpcMessage->BufferLength =

(unsigned int)(_StubMsg.Buffer - (unsigned char __RPC_FAR *)_pRpcMessage->Buffer);

}

const CINTERFACE_PROXY_VTABLE(VTABLE_SIZE2( 4 ) ) _IReceiverProxyVtbl ={

{ &IID_IReceiver },BEGIN_VTABLE2VTABLE_ENTRY2( IUnknown_QueryInterface_Proxy ),VTABLE_ENTRY2( IUnknown_AddRef_Proxy ),VTABLE_ENTRY2( IUnknown_Release_Proxy ), VTABLE_ENTRY2( IReceiver_ReceiveText_Proxy )END_VTABLE2

};

static const PRPC_STUB_FUNCTION IReceiver_table[] ={

(PRPC_STUB_FUNCTION) IReceiver_ReceiveText_Stub};

const CInterfaceStubVtbl _IReceiverStubVtbl ={

{ &IID_IReceiver,0,4,&IReceiver_table[-3] },CStdStubBuffer_METHODS

12

};

/*static*/ const MIDL_STUB_DESC Object_StubDesc =

{0,NdrOleAllocate,NdrOleFree,{ 0 },0,0,0,0,__MIDL_TypeFormatString.Format,1, /* -error bounds_check flag */0x10001, /* Ndr library version */0,0x5030117, /* MIDL Version 5.3.279 */0,0,0, /* notify & notify_flag routine table */0x1, /* MIDL flag */0, /* Reserved3 */0, /* Reserved4 */0 /* Reserved5 */};

/* #pragma data_seg(".rdata") */

#if !defined(__RPC_WIN32__)#error Invalid build platform for this stub.#endif

#if !(defined(SAG_COM) && CE_OLINUX86 && CE_HI386)#error Invalid build platform for this stub.#endif

#if (defined(SAG_COM) && (CE_CSZPTR != 4))#error Invalid build platform for this stub.#endif/*

static*/ const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString ={

0,{

0x4D, /* FC_IN_PARAM */0x1, /* Stack size =1 */

/* 2 */ NdrFcShort( 0x2 ), /* Type Offset=2 *//* 4 */ 0x53, /* FC_RETURN_PARAM_BASETYPE */

0x8, /* FC_LONG *//* 6 */

0x51, /* FC_OUT_PARAM */0x1, /* Stack size =1 */

/* 8 */ NdrFcShort( 0x6 ), /* Type Offset=6 *//* 10 */ 0x53, /* FC_RETURN_PARAM_BASETYPE */

0x8, /* FC_LONG */

0x0}

13

};/*

static*/ const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString ={

0,{

NdrFcShort( 0x0 ), /* 0 *//* 2 */

0x11, 0x8, /* FC_RP [simple_pointer] *//* 4 */

0x25, /* FC_C_WSTRING */0x5C, /* FC_PAD */

/* 6 */0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */

/* 8 */ NdrFcShort( 0x2 ), /* Offset= 2 (10) *//* 10 */

0x13, 0x8, /* FC_OP [simple_pointer] *//* 12 */

0x25, /* FC_C_WSTRING */0x5C, /* FC_PAD */

0x0}

};

const CInterfaceProxyVtbl * _basic_ProxyVtblList[] ={

( CInterfaceProxyVtbl *) &_ISenderProxyVtbl,( CInterfaceProxyVtbl *) &_IReceiverProxyVtbl,0

};

const CInterfaceStubVtbl * _basic_StubVtblList[] ={

( CInterfaceStubVtbl *) &_ISenderStubVtbl,( CInterfaceStubVtbl *) &_IReceiverStubVtbl,0

};

PCInterfaceName const _basic_InterfaceNamesList[] ={

"ISender","IReceiver",0

};

#define _basic_CHECK_IID(n) IID_GENERIC_CHECK_IID( _basic, pIID, n)

int __stdcall _basic_IID_Lookup( const IID * pIID, int * pIndex ){

IID_BS_LOOKUP_SETUP

IID_BS_LOOKUP_INITIAL_TEST( _basic, 2, 1 )IID_BS_LOOKUP_RETURN_RESULT( _basic, 2, *pIndex )

}

const ExtendedProxyFileInfo basic_ProxyFileInfo ={

14

(PCInterfaceProxyVtblList *) & _basic_ProxyVtblList,(PCInterfaceStubVtblList *) & _basic_StubVtblList,(const PCInterfaceName * ) & _basic_InterfaceNamesList,0, // no delegation& _basic_IID_Lookup,2,1,0, /* table of [async_uuid] interfaces */0, /* Filler1 */0, /* Filler2 */0 /* Filler3 */

};

#endif /* !defined(_M_IA64) && !defined(_M_AXP64)*/

dlldata.c stellt generischen Code für die DLL bereit.

/*********************************************************DllData file -- generated by MIDL compiler

DO NOT ALTER THIS FILE

This file is regenerated by MIDL on every IDL file compile.

To completely reconstruct this file, delete it and rerun MIDLon all the IDL files in this DLL, specifying this file for the/dlldata command line option

*********************************************************/

#ifdef SAG_COM /* Pull in COOL header */# include <sagenv.h>#endif /* SAG_COM */

#include <rpcproxy.h>

#ifdef __cplusplusextern "C" {#endif

EXTERN_PROXY_FILE( basic )

PROXYFILE_LIST_START/* Start of list */

REFERENCE_PROXY_FILE( basic ),/* End of list */PROXYFILE_LIST_END

DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )

#ifdef __cplusplus} /*extern "C" */#endif

/* end of generated dlldata file */

basic.c enthält die Deklarationen der Interfaces.

15

#pragma warning( disable: 4049 ) /* more than 64k source lines */

/* this ALWAYS GENERATED file contains the definitions for the interfaces */

/* File created by MIDL compiler version 5.03.0279 *//* at Sun Feb 12 14:41:39 2006

*//* Compiler settings for basic.idl:

Os (OptLev=s), W1, Zp4, env=Unix (32b run) wchar=4bytes, ms_ext, c_exterror checks: allocation ref bounds_check enum stub_dataVC __declspec() decoration level:

__declspec(uuid()), __declspec(selectany), __declspec(novtable)DECLSPEC_UUID(), MIDL_INTERFACE()

*///@@MIDL_FILE_HEADING( )

/* verify that the <rpcndr.h> version is high enough to compile this file*/#ifndef __REQUIRED_RPCNDR_H_VERSION__#define __REQUIRED_RPCNDR_H_VERSION__ 440#endif

#include "rpc.h"#include "rpcndr.h"

#ifndef __RPCNDR_H_VERSION__#error this stub requires an updated version of <rpcndr.h>#endif // __RPCNDR_H_VERSION__

#ifndef COM_NO_WINDOWS_H#include "windows.h"#include "ole2.h"#endif /*COM_NO_WINDOWS_H*/

#ifndef __basic_h__#define __basic_h__

/* Forward Declarations */

#ifndef __ISender_FWD_DEFINED__#define __ISender_FWD_DEFINED__typedef interface ISender ISender;#endif /* __ISender_FWD_DEFINED__ */

#ifndef __IReceiver_FWD_DEFINED__#define __IReceiver_FWD_DEFINED__typedef interface IReceiver IReceiver;#endif /* __IReceiver_FWD_DEFINED__ */

#ifndef __CReadOnly_FWD_DEFINED__#define __CReadOnly_FWD_DEFINED__

#ifdef __cplusplustypedef class CReadOnly CReadOnly;#elsetypedef struct CReadOnly CReadOnly;

16

#endif /* __cplusplus */

#endif /* __CReadOnly_FWD_DEFINED__ */

#ifndef __CReadWrite_FWD_DEFINED__#define __CReadWrite_FWD_DEFINED__

#ifdef __cplusplustypedef class CReadWrite CReadWrite;#elsetypedef struct CReadWrite CReadWrite;#endif /* __cplusplus */

#endif /* __CReadWrite_FWD_DEFINED__ */

/* header files for imported files */#include "unknwn.h"

#ifdef __cplusplusextern "C"{#endif

void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);void __RPC_USER MIDL_user_free( void __RPC_FAR * );

#ifndef __ISender_INTERFACE_DEFINED__#define __ISender_INTERFACE_DEFINED__

/* interface ISender *//* [helpstring][unique][object][uuid] */

EXTERN_C const IID IID_ISender;

# undef INTERFACE# define INTERFACE ISender

/* INTERFACE is required in the DECLARE_INTERFACE_ macro */DECLARE_INTERFACE_( ISender , IUnknown ){INTERFACE_PROLOGUE_( ISender , IUnknown )

STDMETHODEX_ ( HRESULT , QueryInterface, ( THIS_/* [in] */ REFIID riid,/* [iid_is][out] */ void **ppvObject) )

STDMETHODEX_ ( ULONG , AddRef, ( THIS) )

STDMETHODEX_ ( ULONG , Release, ( THIS) )

STDMETHODEX_ ( HRESULT , SendText, ( THIS_/* [string][in] */ const OLECHAR *pwsz) )

INTERFACE_EPILOGUE_( ISender , IUnknown ) };

# if (!defined(__cplusplus)) || (defined(CINTERFACE) || defined(COOL_C_INTERFACE))

17

/* C style interface */

#ifdef COBJMACROS

#define ISender_QueryInterface(This,riid,ppvObject) \(This)->lpVtbl -> QueryInterface(C_ADJUST_THIS(ISender, This, QueryInterface),riid,ppvObject)

#define ISender_AddRef(This) \(This)->lpVtbl -> AddRef(C_ADJUST_THIS(ISender, This, AddRef))

#define ISender_Release(This) \(This)->lpVtbl -> Release(C_ADJUST_THIS(ISender, This, Release))

#define ISender_SendText(This,pwsz) \(This)->lpVtbl -> SendText(C_ADJUST_THIS(ISender, This, SendText),pwsz)

#endif /* COBJMACROS */

# endif /* C style interface */

HRESULT STDMETHODCALLTYPE ISender_SendText_Proxy(ISender __RPC_FAR * This,/* [string][in] */ const OLECHAR __RPC_FAR *pwsz);

void __RPC_STUB ISender_SendText_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);

#endif /* __ISender_INTERFACE_DEFINED__ */

#ifndef __IReceiver_INTERFACE_DEFINED__#define __IReceiver_INTERFACE_DEFINED__

/* interface IReceiver *//* [helpstring][unique][object][uuid] */

EXTERN_C const IID IID_IReceiver;

# undef INTERFACE# define INTERFACE IReceiver

/* INTERFACE is required in the DECLARE_INTERFACE_ macro */DECLARE_INTERFACE_( IReceiver , IUnknown ){INTERFACE_PROLOGUE_( IReceiver , IUnknown )

18

STDMETHODEX_ ( HRESULT , QueryInterface, ( THIS_/* [in] */ REFIID riid,/* [iid_is][out] */ void **ppvObject) )

STDMETHODEX_ ( ULONG , AddRef, ( THIS) )

STDMETHODEX_ ( ULONG , Release, ( THIS) )

STDMETHODEX_ ( HRESULT , ReceiveText, ( THIS_/* [string][out] */ OLECHAR **ppwsz) )

INTERFACE_EPILOGUE_( IReceiver , IUnknown ) };

# if (!defined(__cplusplus)) || (defined(CINTERFACE) || defined(COOL_C_INTERFACE))/* C style interface */

#ifdef COBJMACROS

#define IReceiver_QueryInterface(This,riid,ppvObject) \(This)->lpVtbl -> QueryInterface(C_ADJUST_THIS(IReceiver, This, QueryInterface),riid,ppvObject)

#define IReceiver_AddRef(This) \(This)->lpVtbl -> AddRef(C_ADJUST_THIS(IReceiver, This, AddRef))

#define IReceiver_Release(This) \(This)->lpVtbl -> Release(C_ADJUST_THIS(IReceiver, This, Release))

#define IReceiver_ReceiveText(This,ppwsz) \(This)->lpVtbl -> ReceiveText(C_ADJUST_THIS(IReceiver, This, ReceiveText),ppwsz)

#endif /* COBJMACROS */

# endif /* C style interface */

HRESULT STDMETHODCALLTYPE IReceiver_ReceiveText_Proxy(IReceiver __RPC_FAR * This,/* [string][out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppwsz);

void __RPC_STUB IReceiver_ReceiveText_Stub(IRpcStubBuffer *This,IRpcChannelBuffer *_pRpcChannelBuffer,PRPC_MESSAGE _pRpcMessage,DWORD *_pdwStubPhase);

#endif /* __IReceiver_INTERFACE_DEFINED__ */

#ifndef __BasicLib_LIBRARY_DEFINED__#define __BasicLib_LIBRARY_DEFINED__

/* library BasicLib */

19

/* [helpstring][lcid][version][uuid] */

EXTERN_C const IID LIBID_BasicLib;

EXTERN_C const CLSID CLSID_CReadOnly;

#ifdef __cplusplus

class DECLSPEC_UUID("9BD1C113-12C9-11D0-8E35-0020AFC81B8A")CReadOnly;#endif

EXTERN_C const CLSID CLSID_CReadWrite;

#ifdef __cplusplus

class DECLSPEC_UUID("9BD1C114-12C9-11D0-8E35-0020AFC81B8A")CReadWrite;#endif#endif /* __BasicLib_LIBRARY_DEFINED__ */

/* Additional Prototypes for ALL interfaces */

/* end of Additional Prototypes */

#ifdef __cplusplus}#endif

#endif

Sie werden übersetzt mit

gcc -c -o file.o file.c $(C_FLAGS) $(C_DEFINES) $(C_DEFINES_PROXY) $(C_INCLUDES)

Die Proxy Stub Library wird zusammengebaut mit

g++ -o libbasicps.so \$(LIBRARY_LD_FLAGS) \obj/basic_p.o obj/basic_i.o obj/dlldata.o \obj/basicps_def.o \$(LIBRARY_LINKLIBS)

und registriert mit

regsvr libbasicps.so

In-Process Komponente

basic.def beschreibt die Schnittstelle der Shared Library, aus der die In-Process-Komponente besteht. Die Datei wirdübersetzt durch

makedef -EDllMain $(C_DEFINES) $(C_INCLUDES) $(MAKEDEF_FLAGS) basic.def \obj/basicsvc_def.cxx

und erzeugt basicsvc_def.cxx.

20

LIBRARY basicsvcEXPORTS

DllGetClassObject PRIVATEDllCanUnloadNow PRIVATEDllRegisterServer PRIVATEDllUnregisterServer PRIVATE

basicsvc_def.cxx enthält DLL-Code, der die generische Schnittstelle der Komponente deklariert. Die Datei wird über-setzt durch

g++ -c -o basicsvc_def.o basicsvc_def.cxx $(CC_FLAGS) $(C_DEFINES) $(C_INCLUDES)

und erzeugt basicsvc_def.o.

/** this is a generated file, do not edit** build by rauch on tux3 from basic.def** if you edit this file, its checksum will no longer match and* then the procedure generating this file will reject to overwrite* such a changed file. if this happens, the only thing you can do* is deleting such a changed file by hand.*/

#include <mutantsl.h>

#define MutantDllWithoutLoadLibraryAndDllMain

#define VerboseEnabled 0

#if VerboseEnabled#include <stdio.h>#define IfVerbose(X) do { X; } while (0);#else#define IfVerbose(X) /* empty */#endif

extern "C" {typedef void (* EXPORT_FUNC) ();

}extern "C" void DllCanUnloadNow (void);extern "C" void DllGetClassObject (void);extern "C" void DllRegisterServer (void);extern "C" void DllUnregisterServer (void);

/** definition of the library name and description*/

static const char *g_LibraryName = "basicsvc";static const char *g_LibraryDesc = "";

/** list of all exported names*/

static MutantDllHeaderExportEntry g_MutantDllExports[] = {/* BEGIN */{"DllCanUnloadNow", (EXPORT_FUNC)DllCanUnloadNow},{"DllGetClassObject", (EXPORT_FUNC)DllGetClassObject},

21

{"DllRegisterServer", (EXPORT_FUNC)DllRegisterServer},{"DllUnregisterServer", (EXPORT_FUNC)DllUnregisterServer},/* END */{0, 0}

};

/** the header of the dll*/

extern "C" void DllMain (void);

#include <memory.h>

static MutantDllHeader *g_pMutantDllHeader;

MutantDllHeader::MutantDllHeader(){

Version = MutantDllHeaderVersion;pEntryPoint = DllMain;numEntries = sizeof (g_MutantDllExports) / sizeof(g_MutantDllExports[0]) - 1;ExportList = g_MutantDllExports;DllName = g_LibraryName;DllDescription = g_LibraryDesc;memset(ReservedAndMustBeZero, 0, sizeof(ReservedAndMustBeZero));

}

/** support of linux compilers egcs and gnu*/

#include <stdio.h>#include <errno.h>static int numCalls = 0;

/** for Linux this is run before all static constructors. this is the* time to start memory owner logging.*/

void MutantDllFinalizerFetchHeader (MutantDllHeader **ppMutantDllHeader){

g_pMutantDllHeader = new MutantDllHeader();*ppMutantDllHeader = g_pMutantDllHeader;

}

static void MutantAtInit(void){

if ( numCalls++ == 0 ) {

MutantDllFinalizerProvider(g_pMutantDllHeader); /* used to load final.o from{mutant,windu}stubs */

MutantDllInitializerPostCons(g_pMutantDllHeader);

}}

void (* MutantStartup2Init)(void) __attribute__ ((section (".ctors"))) = MutantAtInit;

22

/** for Linux this is run before all static destructors. this is the* time to run the DLL main function with DLL_PROCESS_DETACH as reason.*/

static void MutantAtExit(){

if ( --numCalls == 0 ) {MutantDllFinalizerPreDest(g_pMutantDllHeader);

}}

void (* MutantStartup2Exit)(void) __attribute__ ((section (".dtors"))) = MutantAtExit;

/* Checksum = 1069741532 2881 ./obj/basicsvc_def.cxx */

baseobjs.cxx und baseobjs.h enthalten die Klassen CReadOnly und CReadWrite, die die Funktionalität der Kompo-nente implementieren.

//=============================================================================////+++//// Copyright (c) Software AG 1996. All rights reserved.////---//// File: baseobjs.cxx - basic DCOM sample object//// Created: 19-sep-96//// History:////=============================================================================

#include <windows.h>#include "baseobjs.h"#include "basic_i.c" /* include IID definitions */

extern void LockModule(void);extern void UnlockModule(void);

HRESULTCReadOnly::CreateInstance(IUnknown **ppunkObject){

if (*ppunkObject = (IReceiver*)new CReadOnly)return S_OK;

elsereturn E_OUTOFMEMORY;

}

CReadOnly::CReadOnly(void): m_cRef(0){

LockModule();wcscpy(m_wszText, OLESTR("COM Rocks"));InitializeCriticalSection(&m_cs);

}

23

CReadOnly::~CReadOnly(void){

UnlockModule();DeleteCriticalSection(&m_cs);

}

STDMETHODIMPCReadOnly::QueryInterface(REFIID riid, void **ppv){

if (riid == IID_IReceiver)*ppv = (IReceiver*)this;

else if (riid == IID_IUnknown)*ppv = (IReceiver*)this;

else{

*ppv = 0; // out params must be set to zeroreturn E_NOINTERFACE;

}((IUnknown*)*ppv)->AddRef();return S_OK;

}

STDMETHODIMP_(ULONG)CReadOnly::AddRef(void){

return InterlockedIncrement(&m_cRef);}

STDMETHODIMP_(ULONG)CReadOnly::Release(void){

if (InterlockedDecrement(&m_cRef) != 0)return m_cRef;

delete this;return 0;

}

STDMETHODIMPCReadOnly::ReceiveText(OLECHAR **ppwsz){

HRESULT hr = S_OK;EnterCriticalSection(&m_cs);if (*ppwsz = (OLECHAR*)CoTaskMemAlloc(sizeof(**ppwsz)*(wcslen(m_wszText) + 1)))

wcscpy(*ppwsz, m_wszText);else

hr = E_OUTOFMEMORY;LeaveCriticalSection(&m_cs);return hr;

}

HRESULTCReadWrite::CreateInstance(IUnknown **ppunkObject){

if (*ppunkObject = (IReceiver*)new CReadWrite)return S_OK;

elsereturn E_OUTOFMEMORY;

}

24

STDMETHODIMPCReadWrite::QueryInterface(REFIID riid, void **ppv){

if (riid == IID_ISender)*ppv = (ISender*)this;

elsereturn CReadOnly::QueryInterface(riid, ppv);

((IUnknown*)*ppv)->AddRef();return S_OK;

}

STDMETHODIMP_(ULONG)CReadWrite::AddRef(void){

return CReadOnly::AddRef();}

STDMETHODIMP_(ULONG)CReadWrite::Release(void){

return CReadOnly::Release();}

STDMETHODIMPCReadWrite::SendText(const OLECHAR *pwsz){

if (wcslen(pwsz) + 1 > sizeof(m_wszText)/sizeof(*m_wszText))return E_INVALIDARG;

EnterCriticalSection(&m_cs);wcscpy(m_wszText, pwsz);LeaveCriticalSection(&m_cs);return S_OK;

}

/*=============================================================================**+++** Copyright (c) Software AG 1996 - 99. All rights reserved.**---** File: baseobjs.h** History:*=============================================================================*/

#ifndef _BASEOBJS_H#define _BASEOBJS_H

// bring in interface definitions#include "basic.h"

class CReadOnly : public IReceiver{

LONG m_cRef;protected:

25

OLECHAR m_wszText[1024];CRITICAL_SECTION m_cs;

public:CReadOnly(void);virtual ~CReadOnly(void);

static HRESULT CreateInstance(IUnknown **ppunkObject);

STDMETHODIMP QueryInterface(REFIID riid, void **ppv);STDMETHODIMP_(ULONG) AddRef(void);STDMETHODIMP_(ULONG) Release(void);

STDMETHODIMP ReceiveText(OLECHAR **ppwsz);};

class CReadWrite : public ISender, public CReadOnly{public:

static HRESULT CreateInstance(IUnknown **ppunkObject);

STDMETHODIMP QueryInterface(REFIID riid, void **ppv);STDMETHODIMP_(ULONG) AddRef(void);STDMETHODIMP_(ULONG) Release(void);STDMETHODIMP SendText(const OLECHAR *pwsz);

};

#endif

cf.cxx und cf.h enthalten eine class factory, die es erlaubt, Instanzen von Komponenten zu verwalten.

//=============================================================================////+++//// Copyright (c) Software AG 1996. All rights reserved.////---//// File: cf.cxx - basic DCOM sample class factory//// Created: 19-sep-96//// History:////=============================================================================

#include <windows.h>#include "cf.h"

extern void LockModule(void);extern void UnlockModule(void);

CClassFactoryImplementation::CClassFactoryImplementation(PFNINSTANCECREATOR pfnCreateInstance,PFNAGGREGATECREATOR pfnCreateAggregate)

: m_pfnCreateInstance(pfnCreateInstance),m_pfnCreateAggregate(m_pfnCreateAggregate)

{}

26

STDMETHODIMPCClassFactoryImplementation::QueryInterface(REFIID riid, void **ppv){

if (riid == IID_IUnknown || riid == IID_IClassFactory)*ppv = (IClassFactory*)this;

else{

*ppv = 0;return E_NOINTERFACE;

}((IUnknown*)*ppv)->AddRef();return S_OK;

}

STDMETHODIMP_(ULONG)CClassFactoryImplementation::AddRef(void){

LockModule();return 2;

}

STDMETHODIMP_(ULONG)CClassFactoryImplementation::Release(void){

UnlockModule();return 1;

}

STDMETHODIMPCClassFactoryImplementation::LockServer(BOOL bLock){

if (bLock)LockModule();

elseUnlockModule();

return S_OK;}

STDMETHODIMPCClassFactoryImplementation::CreateInstance(IUnknown *pUnkOuter,

REFIID riid, void **ppv){

LockModule(); // ensure that we do not shutdownHRESULT hr = E_FAIL;*ppv = 0;if (pUnkOuter){

if (riid != IID_IUnknown)hr = E_INVALIDARG;

else if (m_pfnCreateAggregate){

hr = m_pfnCreateAggregate(pUnkOuter, (IUnknown**)ppv);if (SUCCEEDED(hr))

((IUnknown*)*ppv)->AddRef();}else

hr = CLASS_E_NOAGGREGATION;}else if (m_pfnCreateInstance)

27

{IUnknown *pUnk = 0;hr = m_pfnCreateInstance(&pUnk);if (SUCCEEDED(hr)){

pUnk->AddRef();hr = pUnk->QueryInterface(riid, ppv);pUnk->Release();

}}UnlockModule(); // allow shutdownreturn hr;

}

/*=============================================================================**+++** Copyright (c) Software AG 1996 - 99. All rights reserved.**---** File: cf.h** History:*=============================================================================*/

#ifndef _CF_H#define _CF_H

#include <unknwn.h>

// while template-driven implementations of IClassFactory// abound, this technique requires only one vtable for// the entire module at the expense of eating an extra// 3 * sizeof(pfn) for each coclass. Either way, all of// these bytes can be in COW pages, so it may be// more tweak than is needed

class CClassFactoryImplementation : public IClassFactory{public:

// note: this pointer returned from this internal function// will be addref’ed prior to returning from CreateInstance

typedef HRESULT (*PFNINSTANCECREATOR)(IUnknown **ppunkObj);

// aggregates need the controlling outer but must return IUnknown// note: this pointer returned from this internal function// will be addref’ed prior to returning from CreateInstance

typedef HRESULT (*PFNAGGREGATECREATOR)(IUnknown *pUnkOuter, IUnknown **ppunkObj);

CClassFactoryImplementation(PFNINSTANCECREATOR m_pfnCreateInstance,PFNAGGREGATECREATOR m_pfnCreateAggregate);

// IUnknown methodsSTDMETHODIMP QueryInterface(REFIID riid, void **ppv);STDMETHODIMP_(ULONG) AddRef(void);STDMETHODIMP_(ULONG) Release(void);

28

// IClassFactory methodsSTDMETHODIMP LockServer(BOOL bLock);STDMETHODIMP CreateInstance(IUnknown *pUnkOuter,

REFIID riid, void **ppv);private:

const PFNINSTANCECREATOR m_pfnCreateInstance;const PFNAGGREGATECREATOR m_pfnCreateAggregate;

};

#endif

basicsvc.cxx enthält den Code der in basic.def deklarierten Schnittstellenfunktionen.

//=============================================================================////+++//// Copyright (c) Software AG 1996. All rights reserved.////---//// File: basicsvc.cxx - basic DCOM sample server//// Created: 19-sep-96//// History:////=============================================================================

#include <windows.h>#include <stdio.h>#include "baseobjs.h"#include "cf.h"

//// define _STA_ for Apartment Threading Model////#define _STA_ 1//

extern void LockModule(void);extern void UnlockModule(void);

// class object definitions

CClassFactoryImplementation g_readOnlyCF(CReadOnly::CreateInstance, 0);CClassFactoryImplementation g_readWriteCF(CReadWrite::CreateInstance, 0);

// registry info

const char * const MODULE_FILE_NAME = (const char*)-1;const char * const DEFAULT_VALUE = 0;

#define SERVER_TYPE "InprocServer32"#define THREADING_MODEL "Both"

#ifdef _STA_DWORD dwThreadId = 0;#endif

29

struct REGISTRY_ENTRIES{

const char * pszSubKey;const char * pszValueName;const char * pszValue;BOOL bDelete;

};

const REGISTRY_ENTRIES g_registryEntries[] ={// CReadOnly entries

{ "BasicLib.CReadOnly", DEFAULT_VALUE, "Basic Read-Only Object", TRUE },{ "BasicLib.CReadOnly\\CLSID", DEFAULT_VALUE, "{9BD1C113-12C9-11D0-8E35-0020AFC81B8A}", TRUE},{ "BasicLib.CReadOnly.1", DEFAULT_VALUE, "Basic Read-Only Object", TRUE },{ "BasicLib.CReadOnly.1\\CLSID", DEFAULT_VALUE, "{9BD1C113-12C9-11D0-8E35-0020AFC81B8A}", TRUE },{ "CLSID\\{9BD1C113-12C9-11D0-8E35-0020AFC81B8A}", DEFAULT_VALUE, "Basic Read-Only Object", TRUE },{ "CLSID\\{9BD1C113-12C9-11D0-8E35-0020AFC81B8A}\\" SERVER_TYPE, DEFAULT_VALUE, MODULE_FILE_NAME, TRUE },

#if defined(THREADING_MODEL){ "CLSID\\{9BD1C113-12C9-11D0-8E35-0020AFC81B8A}\\" SERVER_TYPE, "ThreadingModel", THREADING_MODEL, FALSE },

#endif// CReadWrite entries

{ "BasicLib.CReadWrite", DEFAULT_VALUE, "Basic Read-Write Object", TRUE },{ "BasicLib.CReadWrite\\CLSID", DEFAULT_VALUE, "{9BD1C114-12C9-11D0-8E35-0020AFC81B8A}", TRUE },{ "BasicLib.CReadWrite.1", DEFAULT_VALUE, "Basic Read-Write Object", TRUE },{ "BasicLib.CReadWrite.1\\CLSID", DEFAULT_VALUE, "{9BD1C114-12C9-11D0-8E35-0020AFC81B8A}", TRUE },{ "CLSID\\{9BD1C114-12C9-11D0-8E35-0020AFC81B8A}", DEFAULT_VALUE, "Basic Read-Write Object", TRUE },{ "CLSID\\{9BD1C114-12C9-11D0-8E35-0020AFC81B8A}\\" SERVER_TYPE, DEFAULT_VALUE, MODULE_FILE_NAME, TRUE },

#if defined(THREADING_MODEL){ "CLSID\\{9BD1C114-12C9-11D0-8E35-0020AFC81B8A}\\" SERVER_TYPE, "ThreadingModel", THREADING_MODEL, FALSE },

#endif

};

const int verbose = 1;

HRESULT Uninstall(int iLastGoodEntry = sizeof(g_registryEntries)/sizeof(*g_registryEntries) - 1){

long result = 0;HRESULT hr = S_OK;for (int i = iLastGoodEntry; i >= 0; i--)

if (g_registryEntries[i].bDelete){

hr = S_OK;if (verbose > 1)

fprintf(stderr, "basicsvc: deleting key %s\n", g_registryEntries[i].pszSubKey);

result = RegDeleteKeyA(HKEY_CLASSES_ROOT, g_registryEntries[i].pszSubKey);if (result != ERROR_SUCCESS){

hr = MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, result);if (verbose)

fprintf(stderr, "basicsvc: error deleting key %s : %08x\n", g_registryEntries[i].pszSubKey, hr);

}}

return S_OK;}

HRESULT Install(HINSTANCE hInstance)

30

{char szFileName[MAX_PATH];if (!GetModuleFileNameA(hInstance, szFileName, MAX_PATH))

return E_FAIL;int cElems = sizeof(g_registryEntries)/sizeof(*g_registryEntries);for (int i = 0; i < cElems; i++){

HKEY hkey;DWORD dw;long err = RegCreateKeyExA(HKEY_CLASSES_ROOT,

g_registryEntries[i].pszSubKey,0, 0, REG_OPTION_NON_VOLATILE,KEY_SET_VALUE, 0,&hkey, &dw);

if (err == ERROR_SUCCESS){

const char *pszValue = g_registryEntries[i].pszValue;if (pszValue == MODULE_FILE_NAME)

pszValue = szFileName;err = RegSetValueExA(hkey, g_registryEntries[i].pszValueName,

0, REG_SZ, (const BYTE *)pszValue,lstrlenA(pszValue) + 1);

RegCloseKey(hkey);}

if (err != ERROR_SUCCESS){

Uninstall(i);return MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, err);

}}return S_OK;

}

// module lifetime

HINSTANCE g_hInstance = 0;

extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void*){

if (dwReason == DLL_PROCESS_ATTACH){

g_hInstance = hInstance;// Remove the following line if you are using TLS

DisableThreadLibraryCalls(hInstance);}return TRUE;

}

LONG g_cLocks = 0;

void LockModule(void){

InterlockedIncrement(&g_cLocks);}

void UnlockModule(void){

31

InterlockedDecrement(&g_cLocks);}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv){

if (rclsid == CLSID_CReadOnly)return g_readOnlyCF.QueryInterface(riid, ppv);

else if (rclsid == CLSID_CReadWrite)return g_readWriteCF.QueryInterface(riid, ppv);

// if we reach here, it is an unknown class (probably a registry error)*ppv = 0;return CLASS_E_CLASSNOTAVAILABLE;

}

STDAPI DllCanUnloadNow(void){

return g_cLocks ? S_FALSE : S_OK;}

STDAPI DllRegisterServer(void){

return Install(g_hInstance);}

STDAPI DllUnregisterServer(void){

return Uninstall();}

Sie werden übersetzt mit

g++ -c -o file.o file.cxx $(CC_FLAGS) $(C_DEFINES) $(IDLINCS) $(C_INCLUDES) \-I../proxy/$(OBJDIR)

und erzeugen die entsprechenden Objektdateien.Die Komponente wird zusammengebaut mit

g++ -o libbasicsvc.so \$(LIBRARY_LD_FLAGS) \obj/basicsvc.o obj/baseobjs.o obj/cf.o \obj/basicsvc_def.o \$(LIBRARY_LINKLIBS)

und registriert mit

regsvr libbasicsvc.so

32