File:  [WindowsNT SDKs] / mstools / ole20 / samples / outline / classfac.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:24:38 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*************************************************************************
**
**    OLE 2 Sample Code
**
**    classfac.c
**
**    This file contains the implementation for IClassFactory for both the
**    server and the client version of the OUTLINE app. 
**
**    (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/

#include "outline.h"

OLEDBGDATA

extern LPOUTLINEAPP             g_lpApp;


/* OLE2NOTE: this object illustrates the manner in which to statically
**    (compile-time) initialize an interface VTBL.
*/
static IClassFactoryVtbl g_AppClassFactoryVtbl = {
    AppClassFactory_QueryInterface,
    AppClassFactory_AddRef,
    AppClassFactory_Release,
    AppClassFactory_CreateInstance,
    AppClassFactory_LockServer
};


/* AppClassFactory_Create
** ----------------------
**    create an instance of APPCLASSFACTORY. 
**    NOTE: type of pointer returned is an IClassFactory* interface ptr.
**			the returned pointer can be directly passed to
**			CoRegisterClassObject and released later by calling the
**			Release method of the interface.
*/
LPCLASSFACTORY WINAPI AppClassFactory_Create(void)
{
    LPAPPCLASSFACTORY lpAppClassFactory;
    LPMALLOC lpMalloc;
    
    if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) 
        return NULL;
    
    lpAppClassFactory = (LPAPPCLASSFACTORY)lpMalloc->lpVtbl->Alloc(
            lpMalloc, (sizeof(APPCLASSFACTORY)));
    lpMalloc->lpVtbl->Release(lpMalloc);
    if (! lpAppClassFactory) return NULL;

    lpAppClassFactory->m_lpVtbl = &g_AppClassFactoryVtbl;
    lpAppClassFactory->m_cRef   = 1;
    lpAppClassFactory->m_cLock  = 0;

    return (LPCLASSFACTORY)lpAppClassFactory;
}


/*************************************************************************
** OleApp::IClassFactory interface implementation
*************************************************************************/

STDMETHODIMP AppClassFactory_QueryInterface(
        LPCLASSFACTORY lpThis, REFIID riid, LPVOID FAR* ppvObj)
{
    LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis;
    SCODE scode;

    // Two interfaces supported: IUnknown, IClassFactory

    if (IsEqualIID(riid, &IID_IClassFactory) || 
			IsEqualIID(riid, &IID_IUnknown)) {
        lpAppClassFactory->m_cRef++;   // A pointer to this object is returned
        *ppvObj = lpThis;
        scode = S_OK;
    }
    else {                 // unsupported interface
        *ppvObj = NULL;
        scode = E_NOINTERFACE;
    }

    return ResultFromScode(scode);
}


STDMETHODIMP_(ULONG) AppClassFactory_AddRef(LPCLASSFACTORY lpThis)
{
    LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis;
    return ++lpAppClassFactory->m_cRef;
}

STDMETHODIMP_(ULONG) AppClassFactory_Release(LPCLASSFACTORY lpThis)
{
    LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis;
    LPMALLOC lpMalloc;

    if (--lpAppClassFactory->m_cRef != 0) // Still used by others
        return lpAppClassFactory->m_cRef;

    // Free storage
    if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) 
        return 0;

    lpMalloc->lpVtbl->Free(lpMalloc, lpAppClassFactory);
    lpMalloc->lpVtbl->Release(lpMalloc);
    return 0;
}


STDMETHODIMP AppClassFactory_CreateInstance (
        LPCLASSFACTORY      lpThis,
        LPUNKNOWN           lpUnkOuter,
        REFIID              riid,
        LPVOID FAR*         lplpvObj
)
{
    LPOUTLINEAPP	lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
    LPOLEDOC		lpOleDoc;
    HRESULT			hrErr;

    OLEDBG_BEGIN2("AppClassFactory_CreateInstance\r\n")

    /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
    *lplpvObj = NULL;

    /*********************************************************************
    ** OLE2NOTE: this is an SDI app; it can only create and support one
    **    instance. After the instance is created, the OLE libraries
    **    should not call CreateInstance again. it is a good practise
    **    to specifically guard against this.
    *********************************************************************/

    if (lpOutlineApp->m_lpDoc != NULL)
        return ResultFromScode(E_UNEXPECTED);

    /* OLE2NOTE: create a new document instance. by the time we return
	**    from this method the document's refcnt must be 1.
    */
    lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
    lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpDoc;
    if (! lpOleDoc) {
        OLEDBG_END2
        return ResultFromScode(E_OUTOFMEMORY);
    }

    /* OLE2NOTE: retrieve pointer to requested interface. the ref cnt
    **    of the object after OutlineApp_CreateDoc is 0. this call to
    **    QueryInterface will increment the refcnt to 1. the object
    **    returned from IClassFactory::CreateInstance should have a
    **    refcnt of 1 and be controlled by the caller. If the caller
    **    releases the document, the document should be destroyed.
    */
    hrErr = OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);

    OLEDBG_END2
    return hrErr;
}


STDMETHODIMP AppClassFactory_LockServer (
        LPCLASSFACTORY      lpThis,
        BOOL                fLock
)
{
    LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis;
    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
	HRESULT hrErr;

    OLEDBG_BEGIN2("AppClassFactory_LockServer\r\n")

#if defined( _DEBUG )
    if (fLock) {
        ++lpAppClassFactory->m_cLock;

        OleDbgOutRefCnt3(
                "AppClassFactory_LockServer: cLock++\r\n", 
				lpAppClassFactory, lpAppClassFactory->m_cLock);
    } else {

        /* OLE2NOTE: when there are no open documents and the app is not
        **    under the control of the user and there are no outstanding
        **    locks on the app, then revoke our ClassFactory to enable the
        **    app to shut down.
        */
        OleDbgAssertSz (lpAppClassFactory->m_cLock > 0,
                "AppClassFactory_LockServer(FALSE) called with cLock == 0"
        );

		--lpAppClassFactory->m_cLock;

        if (lpAppClassFactory->m_cLock == 0) {
            OleDbgOutRefCnt2(
                    "AppClassFactory_LockServer: UNLOCKED\r\n", 
					lpAppClassFactory, lpAppClassFactory->m_cLock);
        } else {
            OleDbgOutRefCnt3(
                    "AppClassFactory_LockServer: cLock--\r\n",
					lpAppClassFactory, lpAppClassFactory->m_cLock);
        }
    }
#endif	// _DEBUG
		
	/* OLE2NOTE: in order to hold the application alive we call
	**    CoLockObjectExternal to add a strong reference to our app
	**    object. this will keep the app alive when all other external
	**    references release us. if the user issues File.Exit the
	**    application will shut down in any case ignoring any
	**    outstanding LockServer locks because CoDisconnectObject is
	**    called in OleApp_CloseAllDocsAndExitCommand. this will
	**    forceably break any existing strong reference counts
	**    including counts that we add ourselves by calling
	**    CoLockObjectExternal and guarantee that the App object gets
	**    its final release (ie. cRefs goes to 0).
	*/
	hrErr = OleApp_Lock(lpOleApp, fLock, TRUE /* fLastUnlockReleases */);

    OLEDBG_END2
 	return hrErr;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.