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.

239 lines
7.0 KiB

  1. /***************************************************************************\
  2. *
  3. * File: MsgTable.cpp
  4. *
  5. * Description:
  6. * MsgTable.cpp implements the "Message Table" object that provide a
  7. * dynamically generated v-table for messages.
  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 "MsgTable.h"
  19. #include "MsgClass.h"
  20. /***************************************************************************\
  21. *****************************************************************************
  22. *
  23. * class MsgTable
  24. *
  25. *****************************************************************************
  26. \***************************************************************************/
  27. /***************************************************************************\
  28. *
  29. * MsgTable::Build
  30. *
  31. * Build() builds and fully initializes a new MsgTable.
  32. *
  33. \***************************************************************************/
  34. HRESULT
  35. MsgTable::Build(
  36. IN const DUser::MessageClassGuts * pmcInfo,
  37. // Implementation information
  38. IN const MsgClass * pmcPeer, // "Owning" MsgClass
  39. OUT MsgTable ** ppmtNew) // Newly built MsgTable
  40. {
  41. AssertMsg(pmcPeer != NULL, "Must have a valid MsgClass peer");
  42. HRESULT hr = S_OK;
  43. //
  44. // Compute how much memory the MsgTable will take
  45. // - Find the Super
  46. // - Determine the number of messages. This is the number of messages
  47. // defined in the super + the number of _new_ (not overridden) messages.
  48. //
  49. int cSuperMsgs = 0, cNewMsgs = 0;
  50. const MsgClass * pmcSuper = pmcPeer->GetSuper();
  51. const MsgTable * pmtSuper = NULL;
  52. if (pmcSuper != NULL) {
  53. pmtSuper = pmcSuper->GetMsgTable();
  54. cSuperMsgs = pmtSuper->GetCount();
  55. for (int idx = 0; idx < pmcInfo->cMsgs; idx++) {
  56. if ((pmcInfo->rgMsgInfo[idx].pfn != NULL) &&
  57. (pmtSuper->Find(FindAtomW(pmcInfo->rgMsgInfo[idx].pszMsgName)) == 0)) {
  58. cNewMsgs++;
  59. }
  60. }
  61. } else {
  62. cNewMsgs = pmcInfo->cMsgs;
  63. }
  64. //
  65. // Allocate the new MsgTable
  66. //
  67. int cTotalMsgs = cSuperMsgs + cNewMsgs;
  68. int cbAlloc = sizeof(MsgTable) + cTotalMsgs * sizeof(MsgSlot);
  69. if ((cbAlloc > GM_EVENT) || (cTotalMsgs > 1024)) {
  70. PromptInvalid("MsgTable will contain too many methods.");
  71. return E_INVALIDARG;
  72. }
  73. void * pvAlloc = ProcessAlloc(cbAlloc);
  74. if (pvAlloc == NULL) {
  75. return E_OUTOFMEMORY;
  76. }
  77. MsgTable * pmtNew = placement_new(pvAlloc, MsgTable);
  78. pmtNew->m_cMsgs = cTotalMsgs;
  79. pmtNew->m_pmcPeer = pmcPeer;
  80. pmtNew->m_pmtSuper = pmtSuper;
  81. //
  82. // Setup message entries
  83. // - Copy messages from super-class
  84. // - Override and add messages from new class
  85. //
  86. // NOTE: We are using GArrayS<> to store the array of this pointers. The
  87. // data stored in here points to the beginning of the array of data.
  88. // Before this array, we store the size, but we don't need to worry about
  89. // that here.
  90. //
  91. if (cTotalMsgs > 0) {
  92. MsgSlot * rgmsDest = pmtNew->GetSlots();
  93. int cThisDepth = pmtSuper != NULL ? pmtSuper->GetDepth() + 1 : 0;
  94. int cbThisOffset = cThisDepth * sizeof(void *);
  95. int idxAdd = 0;
  96. if (pmtSuper != NULL) {
  97. const MsgSlot * rgmsSrc = pmtSuper->GetSlots();
  98. for (idxAdd = 0; idxAdd < cSuperMsgs; idxAdd++) {
  99. rgmsDest[idxAdd] = rgmsSrc[idxAdd];
  100. }
  101. }
  102. Assert(idxAdd == cSuperMsgs);
  103. for (int idx = 0; idx < pmcInfo->cMsgs; idx++) {
  104. const DUser::MessageInfoGuts * pmi = &pmcInfo->rgMsgInfo[idx];
  105. ATOM atomMsg = 0;
  106. int idxMsg = -1;
  107. if (pmi->pfn == NULL) {
  108. continue; // Just skip this slot
  109. }
  110. if ((pmtSuper == NULL) || // No super
  111. ((atomMsg = FindAtomW(pmi->pszMsgName)) == 0) || // Message not yet defined
  112. ((idxMsg = pmtSuper->FindIndex(atomMsg)) < 0)) { // Message not in super
  113. //
  114. // Function is defined, so it should be added.
  115. //
  116. atomMsg = AddAtomW(pmi->pszMsgName);
  117. idxMsg = idxAdd++;
  118. }
  119. MsgSlot & ms = rgmsDest[idxMsg];
  120. ms.atomNameID = atomMsg;
  121. ms.cbThisOffset = cbThisOffset;
  122. ms.pfn = pmi->pfn;
  123. }
  124. AssertMsg(idxAdd == cTotalMsgs, "Should have added all messages");
  125. //
  126. // Check to see if any messages were not properly setup.
  127. //
  128. BOOL fMissing = FALSE;
  129. for (idx = 0; idx < cTotalMsgs; idx++) {
  130. if (rgmsDest[idx].pfn == NULL) {
  131. //
  132. // Function is not defined and is not in the super. This is
  133. // an error because it is being declared "new" and not being
  134. // defined.
  135. //
  136. WCHAR szMsgName[256];
  137. GetAtomNameW(rgmsDest[idx].atomNameID, szMsgName, _countof(szMsgName));
  138. Trace("ERROR: DUser: %S::%S() was not properly setup.\n",
  139. pmcInfo->pszClassName, szMsgName);
  140. fMissing = TRUE;
  141. }
  142. }
  143. if (fMissing) {
  144. PromptInvalid("Class registration does not have all functions properly setup.");
  145. hr = DU_E_MESSAGENOTIMPLEMENTED;
  146. goto ErrorExit;
  147. }
  148. }
  149. //
  150. // Done building- return out
  151. //
  152. *ppmtNew = pmtNew;
  153. return S_OK;
  154. ErrorExit:
  155. delete pmtNew;
  156. return hr;
  157. }
  158. /***************************************************************************\
  159. *
  160. * MsgTable::FindIndex
  161. *
  162. * FindIndex() finds the corresponding index for the specified
  163. * method / message.
  164. *
  165. \***************************************************************************/
  166. int
  167. MsgTable::FindIndex(
  168. IN ATOM atomNameID // Method to find
  169. ) const
  170. {
  171. const MsgSlot * rgSlots = GetSlots();
  172. for (int idx = 0; idx < m_cMsgs; idx++) {
  173. if (rgSlots[idx].atomNameID == atomNameID) {
  174. return idx;
  175. }
  176. }
  177. return -1;
  178. }
  179. /***************************************************************************\
  180. *
  181. * MsgTable::Find
  182. *
  183. * Find() finds the corresponding MsgSlot for the specified method / message.
  184. *
  185. \***************************************************************************/
  186. const MsgSlot *
  187. MsgTable::Find(
  188. IN ATOM atomNameID // Method to find
  189. ) const
  190. {
  191. int idx = FindIndex(atomNameID);
  192. if (idx >= 0) {
  193. return &(GetSlots()[idx]);
  194. } else {
  195. return NULL;
  196. }
  197. }