|
|
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.