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.

278 lines
6.7 KiB

  1. /***************************************************************************\
  2. *
  3. * File: ClassLibrary.cpp
  4. *
  5. * Description:
  6. * ClassLibrary.h implements the library of "message classes" that have been
  7. * registered with DirectUser.
  8. *
  9. *
  10. * History:
  11. * 8/05/2000: JStall: Created
  12. *
  13. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  14. *
  15. \***************************************************************************/
  16. #include "stdafx.h"
  17. #include "Msg.h"
  18. #include "ClassLibrary.h"
  19. #include "MsgClass.h"
  20. #include "MsgObject.h"
  21. /***************************************************************************\
  22. *****************************************************************************
  23. *
  24. * class ClassLibrary
  25. *
  26. *****************************************************************************
  27. \***************************************************************************/
  28. ClassLibrary g_cl;
  29. ClassLibrary *
  30. GetClassLibrary()
  31. {
  32. return &g_cl;
  33. }
  34. /***************************************************************************\
  35. *
  36. * ClassLibrary::~ClassLibrary
  37. *
  38. * ~ClassLibrary() cleans up resources used by a ClassLibrary.
  39. *
  40. \***************************************************************************/
  41. ClassLibrary::~ClassLibrary()
  42. {
  43. //
  44. // Need to directly destroy the MsgClass's since they are allocated in
  45. // process memory.
  46. //
  47. while (!m_lstClasses.IsEmpty()) {
  48. MsgClass * pmc = m_lstClasses.UnlinkHead();
  49. ProcessDelete(MsgClass, pmc);
  50. }
  51. }
  52. /***************************************************************************\
  53. *
  54. * ClassLibrary::RegisterGutsNL
  55. *
  56. * RegisterGutsNL() registers the implementation of a MsgClass so that it can
  57. * be instantiated. The MsgClass may already exist if it was previously
  58. * registered, but can not be instantiated until the implementation has also
  59. * been registered. The implementation can only be registered once.
  60. *
  61. \***************************************************************************/
  62. HRESULT
  63. ClassLibrary::RegisterGutsNL(
  64. IN OUT DUser::MessageClassGuts * pmcInfo, // Guts information
  65. OUT MsgClass ** ppmc) // OPTIONAL Class
  66. {
  67. HRESULT hr = S_OK;
  68. m_lock.Enter();
  69. MsgClass * pmc;
  70. hr = BuildClass(pmcInfo->pszClassName, &pmc);
  71. if (FAILED(hr)) {
  72. goto Cleanup;
  73. }
  74. hr = pmc->RegisterGuts(pmcInfo);
  75. if (SUCCEEDED(hr) && (ppmc != NULL)) {
  76. *ppmc = pmc;
  77. }
  78. hr = S_OK;
  79. Cleanup:
  80. m_lock.Leave();
  81. return hr;
  82. }
  83. /***************************************************************************\
  84. *
  85. * ClassLibrary::RegisterStubNL
  86. *
  87. * RegisterStubNL() registers a Stub to use a MsgClass. Many Stubs may
  88. * register the same MsgClass, but they can not instantiate a new instance
  89. * until the implementation has also been registered.
  90. *
  91. \***************************************************************************/
  92. HRESULT
  93. ClassLibrary::RegisterStubNL(
  94. IN OUT DUser::MessageClassStub * pmcInfo, // Stub information
  95. OUT MsgClass ** ppmc) // OPTIONAL Class
  96. {
  97. HRESULT hr = S_OK;
  98. m_lock.Enter();
  99. MsgClass * pmc;
  100. hr = BuildClass(pmcInfo->pszClassName, &pmc);
  101. if (FAILED(hr)) {
  102. goto Cleanup;
  103. }
  104. hr = pmc->RegisterStub(pmcInfo);
  105. if (SUCCEEDED(hr) && (ppmc != NULL)) {
  106. *ppmc = pmc;
  107. }
  108. hr = S_OK;
  109. Cleanup:
  110. m_lock.Leave();
  111. return hr;
  112. }
  113. /***************************************************************************\
  114. *
  115. * ClassLibrary::RegisterSuperNL
  116. *
  117. * RegisterSuperNL() registers a Super to use a MsgClass. Many Supers may
  118. * register the same MsgClass, but they can not instantiate a new instance
  119. * until the implementation has also been registered.
  120. *
  121. \***************************************************************************/
  122. HRESULT
  123. ClassLibrary::RegisterSuperNL(
  124. IN OUT DUser::MessageClassSuper * pmcInfo, // Super information
  125. OUT MsgClass ** ppmc) // OPTIONAL class
  126. {
  127. HRESULT hr = S_OK;
  128. m_lock.Enter();
  129. MsgClass * pmc;
  130. hr = BuildClass(pmcInfo->pszClassName, &pmc);
  131. if (FAILED(hr)) {
  132. goto Cleanup;
  133. }
  134. hr = pmc->RegisterSuper(pmcInfo);
  135. if (SUCCEEDED(hr) && (ppmc != NULL)) {
  136. *ppmc = pmc;
  137. }
  138. hr = S_OK;
  139. Cleanup:
  140. m_lock.Leave();
  141. return hr;
  142. }
  143. /***************************************************************************\
  144. *
  145. * ClassLibrary::MarkInternal
  146. *
  147. * MarkInternal() marks a class as being internally implemented inside DUser.
  148. *
  149. \***************************************************************************/
  150. void
  151. ClassLibrary::MarkInternal(
  152. IN HCLASS hcl) // Class to mark internal
  153. {
  154. MsgClass * pmc = ValidateMsgClass(hcl);
  155. AssertMsg(pmc != NULL, "Must give a valid class");
  156. pmc->MarkInternal();
  157. #if DBG
  158. if (pmc->GetSuper() != NULL) {
  159. AssertMsg(pmc->GetSuper()->IsInternal(), "Super class must also be internal");
  160. }
  161. #endif
  162. }
  163. /***************************************************************************\
  164. *
  165. * ClassLibrary::FindClass
  166. *
  167. * FindClass() finds a class by name already in the library. If the class is
  168. * not found, NULL is returned.
  169. *
  170. \***************************************************************************/
  171. const MsgClass *
  172. ClassLibrary::FindClass(
  173. IN ATOM atomName // Name of class
  174. ) const
  175. {
  176. if (atomName == 0) {
  177. return NULL;
  178. }
  179. //
  180. // First, see if the class already exists.
  181. //
  182. MsgClass * pmcCur = m_lstClasses.GetHead();
  183. while (pmcCur != NULL) {
  184. if (pmcCur->GetName() == atomName) {
  185. return pmcCur;
  186. }
  187. pmcCur = pmcCur->GetNext();
  188. }
  189. return NULL;
  190. }
  191. /***************************************************************************\
  192. *
  193. * ClassLibrary::BuildClass
  194. *
  195. * BuildClass() adds a MsgClass into the library. If the MsgClass already
  196. * is in the library, the existing implementation is returned.
  197. *
  198. \***************************************************************************/
  199. HRESULT
  200. ClassLibrary::BuildClass(
  201. IN LPCWSTR pszClassName, // Class information
  202. OUT MsgClass ** ppmc) // MsgClass
  203. {
  204. //
  205. // Search for the class
  206. //
  207. MsgClass * pmcNew = const_cast<MsgClass *> (FindClass(FindAtomW(pszClassName)));
  208. if (pmcNew != NULL) {
  209. *ppmc = pmcNew;
  210. return S_OK;
  211. }
  212. //
  213. // Build a new class
  214. //
  215. HRESULT hr = MsgClass::Build(pszClassName, &pmcNew);
  216. if (FAILED(hr)) {
  217. return hr;
  218. }
  219. m_lstClasses.Add(pmcNew);
  220. *ppmc = pmcNew;
  221. return S_OK;
  222. }