|
|
1.1 ! root 1: /************************************************************************* ! 2: ** ! 3: ** OLE 2 Sample Code ! 4: ** ! 5: ** classfac.c ! 6: ** ! 7: ** This file contains the implementation for IClassFactory for both the ! 8: ** server and the client version of the OUTLINE app. ! 9: ** ! 10: ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ! 11: ** ! 12: *************************************************************************/ ! 13: ! 14: #include "outline.h" ! 15: ! 16: OLEDBGDATA ! 17: ! 18: extern LPOUTLINEAPP g_lpApp; ! 19: ! 20: ! 21: /* OLE2NOTE: this object illustrates the manner in which to statically ! 22: ** (compile-time) initialize an interface VTBL. ! 23: */ ! 24: static IClassFactoryVtbl g_AppClassFactoryVtbl = { ! 25: AppClassFactory_QueryInterface, ! 26: AppClassFactory_AddRef, ! 27: AppClassFactory_Release, ! 28: AppClassFactory_CreateInstance, ! 29: AppClassFactory_LockServer ! 30: }; ! 31: ! 32: ! 33: /* AppClassFactory_Create ! 34: ** ---------------------- ! 35: ** create an instance of APPCLASSFACTORY. ! 36: ** NOTE: type of pointer returned is an IClassFactory* interface ptr. ! 37: ** the returned pointer can be directly passed to ! 38: ** CoRegisterClassObject and released later by calling the ! 39: ** Release method of the interface. ! 40: */ ! 41: LPCLASSFACTORY WINAPI AppClassFactory_Create(void) ! 42: { ! 43: LPAPPCLASSFACTORY lpAppClassFactory; ! 44: LPMALLOC lpMalloc; ! 45: ! 46: if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) ! 47: return NULL; ! 48: ! 49: lpAppClassFactory = (LPAPPCLASSFACTORY)lpMalloc->lpVtbl->Alloc( ! 50: lpMalloc, (sizeof(APPCLASSFACTORY))); ! 51: lpMalloc->lpVtbl->Release(lpMalloc); ! 52: if (! lpAppClassFactory) return NULL; ! 53: ! 54: lpAppClassFactory->m_lpVtbl = &g_AppClassFactoryVtbl; ! 55: lpAppClassFactory->m_cRef = 1; ! 56: lpAppClassFactory->m_cLock = 0; ! 57: ! 58: return (LPCLASSFACTORY)lpAppClassFactory; ! 59: } ! 60: ! 61: ! 62: /************************************************************************* ! 63: ** OleApp::IClassFactory interface implementation ! 64: *************************************************************************/ ! 65: ! 66: STDMETHODIMP AppClassFactory_QueryInterface( ! 67: LPCLASSFACTORY lpThis, REFIID riid, LPVOID FAR* ppvObj) ! 68: { ! 69: LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; ! 70: SCODE scode; ! 71: ! 72: // Two interfaces supported: IUnknown, IClassFactory ! 73: ! 74: if (IsEqualIID(riid, &IID_IClassFactory) || ! 75: IsEqualIID(riid, &IID_IUnknown)) { ! 76: lpAppClassFactory->m_cRef++; // A pointer to this object is returned ! 77: *ppvObj = lpThis; ! 78: scode = S_OK; ! 79: } ! 80: else { // unsupported interface ! 81: *ppvObj = NULL; ! 82: scode = E_NOINTERFACE; ! 83: } ! 84: ! 85: return ResultFromScode(scode); ! 86: } ! 87: ! 88: ! 89: STDMETHODIMP_(ULONG) AppClassFactory_AddRef(LPCLASSFACTORY lpThis) ! 90: { ! 91: LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; ! 92: return ++lpAppClassFactory->m_cRef; ! 93: } ! 94: ! 95: STDMETHODIMP_(ULONG) AppClassFactory_Release(LPCLASSFACTORY lpThis) ! 96: { ! 97: LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; ! 98: LPMALLOC lpMalloc; ! 99: ! 100: if (--lpAppClassFactory->m_cRef != 0) // Still used by others ! 101: return lpAppClassFactory->m_cRef; ! 102: ! 103: // Free storage ! 104: if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR) ! 105: return 0; ! 106: ! 107: lpMalloc->lpVtbl->Free(lpMalloc, lpAppClassFactory); ! 108: lpMalloc->lpVtbl->Release(lpMalloc); ! 109: return 0; ! 110: } ! 111: ! 112: ! 113: STDMETHODIMP AppClassFactory_CreateInstance ( ! 114: LPCLASSFACTORY lpThis, ! 115: LPUNKNOWN lpUnkOuter, ! 116: REFIID riid, ! 117: LPVOID FAR* lplpvObj ! 118: ) ! 119: { ! 120: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 121: LPOLEDOC lpOleDoc; ! 122: HRESULT hrErr; ! 123: ! 124: OLEDBG_BEGIN2("AppClassFactory_CreateInstance\r\n") ! 125: ! 126: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 127: *lplpvObj = NULL; ! 128: ! 129: /********************************************************************* ! 130: ** OLE2NOTE: this is an SDI app; it can only create and support one ! 131: ** instance. After the instance is created, the OLE libraries ! 132: ** should not call CreateInstance again. it is a good practise ! 133: ** to specifically guard against this. ! 134: *********************************************************************/ ! 135: ! 136: if (lpOutlineApp->m_lpDoc != NULL) ! 137: return ResultFromScode(E_UNEXPECTED); ! 138: ! 139: /* OLE2NOTE: create a new document instance. by the time we return ! 140: ** from this method the document's refcnt must be 1. ! 141: */ ! 142: lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE); ! 143: lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpDoc; ! 144: if (! lpOleDoc) { ! 145: OLEDBG_END2 ! 146: return ResultFromScode(E_OUTOFMEMORY); ! 147: } ! 148: ! 149: /* OLE2NOTE: retrieve pointer to requested interface. the ref cnt ! 150: ** of the object after OutlineApp_CreateDoc is 0. this call to ! 151: ** QueryInterface will increment the refcnt to 1. the object ! 152: ** returned from IClassFactory::CreateInstance should have a ! 153: ** refcnt of 1 and be controlled by the caller. If the caller ! 154: ** releases the document, the document should be destroyed. ! 155: */ ! 156: hrErr = OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj); ! 157: ! 158: OLEDBG_END2 ! 159: return hrErr; ! 160: } ! 161: ! 162: ! 163: STDMETHODIMP AppClassFactory_LockServer ( ! 164: LPCLASSFACTORY lpThis, ! 165: BOOL fLock ! 166: ) ! 167: { ! 168: LPAPPCLASSFACTORY lpAppClassFactory = (LPAPPCLASSFACTORY)lpThis; ! 169: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 170: HRESULT hrErr; ! 171: ! 172: OLEDBG_BEGIN2("AppClassFactory_LockServer\r\n") ! 173: ! 174: #if defined( _DEBUG ) ! 175: if (fLock) { ! 176: ++lpAppClassFactory->m_cLock; ! 177: ! 178: OleDbgOutRefCnt3( ! 179: "AppClassFactory_LockServer: cLock++\r\n", ! 180: lpAppClassFactory, lpAppClassFactory->m_cLock); ! 181: } else { ! 182: ! 183: /* OLE2NOTE: when there are no open documents and the app is not ! 184: ** under the control of the user and there are no outstanding ! 185: ** locks on the app, then revoke our ClassFactory to enable the ! 186: ** app to shut down. ! 187: */ ! 188: OleDbgAssertSz (lpAppClassFactory->m_cLock > 0, ! 189: "AppClassFactory_LockServer(FALSE) called with cLock == 0" ! 190: ); ! 191: ! 192: --lpAppClassFactory->m_cLock; ! 193: ! 194: if (lpAppClassFactory->m_cLock == 0) { ! 195: OleDbgOutRefCnt2( ! 196: "AppClassFactory_LockServer: UNLOCKED\r\n", ! 197: lpAppClassFactory, lpAppClassFactory->m_cLock); ! 198: } else { ! 199: OleDbgOutRefCnt3( ! 200: "AppClassFactory_LockServer: cLock--\r\n", ! 201: lpAppClassFactory, lpAppClassFactory->m_cLock); ! 202: } ! 203: } ! 204: #endif // _DEBUG ! 205: ! 206: /* OLE2NOTE: in order to hold the application alive we call ! 207: ** CoLockObjectExternal to add a strong reference to our app ! 208: ** object. this will keep the app alive when all other external ! 209: ** references release us. if the user issues File.Exit the ! 210: ** application will shut down in any case ignoring any ! 211: ** outstanding LockServer locks because CoDisconnectObject is ! 212: ** called in OleApp_CloseAllDocsAndExitCommand. this will ! 213: ** forceably break any existing strong reference counts ! 214: ** including counts that we add ourselves by calling ! 215: ** CoLockObjectExternal and guarantee that the App object gets ! 216: ** its final release (ie. cRefs goes to 0). ! 217: */ ! 218: hrErr = OleApp_Lock(lpOleApp, fLock, TRUE /* fLastUnlockReleases */); ! 219: ! 220: OLEDBG_END2 ! 221: return hrErr; ! 222: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.