Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
6.9 KiB

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