// // virtualdefs.h // // Contains definitions for pure virtual functions which must defined via // the IDispatch. This header is used in CTBGlobal.cpp and CTBShell.cpp // // WHY did I do it this way instead of object inheritance? // // OLE Automation requires the IDL file objects to inherit // IDispatch members. The IDispatch object contains pure virtual // functions as a layout, which must be defined by me, the user of it. // The problem is, I have two objects which need to define identical code. // To prevent this, I just included the source. // // Object inheritance will not work in this case because if I define // an object which defines the pure virtual functions, and eventually // inherit them through CTBShell and CTBGlobal, it will still not work // because I also inherited the automatic IDL generated header which // makes a second path to undefined pure virtual function. I COULD // make two objects with two names (to have two different parents) but // I would end up duplicating code again.. It looks like this: // // pure virtual methods // | // / \ // / \ // / \ // / \ // / \ // OLE Obj 1 OLE Obj 2 // | | // | <-1-- | <-2------ including this file at this layer // | | // My Obj 1 My Obj 2 // // // Copyright (C) 2001 Microsoft Corporation // // Author: a-devjen (Devin Jenson) // // CTBOBJECT::Init // // Initializes the TypeInfo and RefIID. // // No return value. void CTBOBJECT::Init(REFIID RefIID) { RefCount = 0; ObjRefIID = RefIID; // Load actual "code" into memory.. its referenced as ITypeInfo, // but think of it as like a DLL, but you can't access it the // same way. if (FAILED(SCPLoadTypeInfoFromThisModule(RefIID, &TypeInfo))) { _ASSERT(FALSE); TypeInfo = NULL; } else TypeInfo->AddRef(); } // CTBOBJECT::UnInit // // Releases the type info. // // No return value. void CTBOBJECT::UnInit(void) { // Release the TypeInfo if we have it if(TypeInfo != NULL) TypeInfo->Release(); TypeInfo = NULL; } // // // Begin the IUnknown inherited interface // // // CTBOBJECT::QueryInterface // // This is a COM exported method used for retrieving the interface. // // Returns S_OK on success, or E_NOINTERFACE on failure. STDMETHODIMP CTBOBJECT::QueryInterface(REFIID RefIID, void **vObject) { // This interface is either IID_ITBGlobal, IID_ITBShell, // IID_IUnknown, or IID_IDispatch to get the TypeInfo... if (RefIID == ObjRefIID || RefIID == IID_IDispatch || RefIID == IID_IUnknown) *vObject = TypeInfo != NULL ? this : NULL; // We received an unsupported RefIID else { // De-reference the passed in pointer and error out *vObject = NULL; return E_NOINTERFACE; } // Add a reference if (*vObject != NULL) ((IUnknown*)*vObject)->AddRef(); return S_OK; } // CTBOBJECT::AddRef // // Simply increments a number indicating the number of objects that contain // a reference to this object. // // Returns the new reference count. STDMETHODIMP_(ULONG) CTBOBJECT::AddRef(void) { return InterlockedIncrement(&RefCount); } // CTBOBJECT::Release // // Simply decrements a number indicating the number of objects that contain // a reference to this object. If the resulting reference count is zero, // no objects contain a reference handle, therefore delete itself from // memory as it is no longer used. // // Returns the new reference count. STDMETHODIMP_(ULONG) CTBOBJECT::Release(void) { // Decrememt if (InterlockedDecrement(&RefCount) != 0) // Return the new value return RefCount; // It is 0, so delete itself delete this; return 0; } // // // Begin the IDispatch inherited interface // // // CTBOBJECT::GetTypeInfoCount // // Retrieves the number of TypeInfo's we have. // // Returns S_OK on success, or E_POINTER on failure. STDMETHODIMP CTBOBJECT::GetTypeInfoCount(UINT *TypeInfoCount) { __try { // We never have more than 1 type info per object *TypeInfoCount = 1; } __except (EXCEPTION_EXECUTE_HANDLER) { // This really should never happen... _ASSERT(FALSE); return E_POINTER; } return S_OK; } // CTBOBJECT::GetTypeInfo // // Retrieves a pointer to the specified TypeInfo. // // Returns S_OK on success, or E_POINTER on failure. STDMETHODIMP CTBOBJECT::GetTypeInfo(UINT TypeInfoNum, LCID Lcid, ITypeInfo **TypeInfoPtr) { // Check our interface first _ASSERT(TypeInfo != NULL); __try { // The only TypeInfo we have is the one in this object... *TypeInfoPtr = TypeInfo; TypeInfo->AddRef(); } __except (EXCEPTION_EXECUTE_HANDLER) { // This really should never happen... _ASSERT(FALSE); return E_POINTER; } return S_OK; } // CTBOBJECT::GetIDsOfNames // // Get ID's of the specified names in our TypeInfo. // // Returns any HRESULT value. STDMETHODIMP CTBOBJECT::GetIDsOfNames(REFIID RefIID, OLECHAR **NamePtrList, UINT NameCount, LCID Lcid, DISPID *DispID) { HRESULT Result; // Check our pointer first _ASSERT(TypeInfo != NULL); // Use the TypeInfo of this function instead Result = TypeInfo->GetIDsOfNames(NamePtrList, NameCount, DispID); // Assert uncommon return values _ASSERT(Result == S_OK || Result == DISP_E_UNKNOWNNAME); return Result; } // CTBOBJECT::Invoke // // Invokes a method in the TypeInfo. // // Returns any HRESULT value. STDMETHODIMP CTBOBJECT::Invoke(DISPID DispID, REFIID RefIID, LCID Lcid, WORD Flags, DISPPARAMS *DispParms, VARIANT *Variant, EXCEPINFO *ExceptionInfo, UINT *ArgErr) { HRESULT Result; // Check our pointer first _ASSERT(TypeInfo != NULL); // Invoke the method Result = TypeInfo->Invoke(this, DispID, Flags, DispParms, Variant, ExceptionInfo, ArgErr); _ASSERT(Result == S_OK); return Result; }