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

/***************************************************************************\
*
* File: MsgTable.cpp
*
* Description:
* MsgTable.cpp implements the "Message Table" object that provide a
* dynamically generated v-table for messages.
*
*
* History:
* 8/05/2000: JStall: Created
*
* Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
#include "stdafx.h"
#include "Msg.h"
#include "MsgTable.h"
#include "MsgClass.h"
/***************************************************************************\
*****************************************************************************
*
* class MsgTable
*
*****************************************************************************
\***************************************************************************/
/***************************************************************************\
*
* MsgTable::Build
*
* Build() builds and fully initializes a new MsgTable.
*
\***************************************************************************/
HRESULT
MsgTable::Build(
IN const DUser::MessageClassGuts * pmcInfo,
// Implementation information
IN const MsgClass * pmcPeer, // "Owning" MsgClass
OUT MsgTable ** ppmtNew) // Newly built MsgTable
{
AssertMsg(pmcPeer != NULL, "Must have a valid MsgClass peer");
HRESULT hr = S_OK;
//
// Compute how much memory the MsgTable will take
// - Find the Super
// - Determine the number of messages. This is the number of messages
// defined in the super + the number of _new_ (not overridden) messages.
//
int cSuperMsgs = 0, cNewMsgs = 0;
const MsgClass * pmcSuper = pmcPeer->GetSuper();
const MsgTable * pmtSuper = NULL;
if (pmcSuper != NULL) {
pmtSuper = pmcSuper->GetMsgTable();
cSuperMsgs = pmtSuper->GetCount();
for (int idx = 0; idx < pmcInfo->cMsgs; idx++) {
if ((pmcInfo->rgMsgInfo[idx].pfn != NULL) &&
(pmtSuper->Find(FindAtomW(pmcInfo->rgMsgInfo[idx].pszMsgName)) == 0)) {
cNewMsgs++;
}
}
} else {
cNewMsgs = pmcInfo->cMsgs;
}
//
// Allocate the new MsgTable
//
int cTotalMsgs = cSuperMsgs + cNewMsgs;
int cbAlloc = sizeof(MsgTable) + cTotalMsgs * sizeof(MsgSlot);
if ((cbAlloc > GM_EVENT) || (cTotalMsgs > 1024)) {
PromptInvalid("MsgTable will contain too many methods.");
return E_INVALIDARG;
}
void * pvAlloc = ProcessAlloc(cbAlloc);
if (pvAlloc == NULL) {
return E_OUTOFMEMORY;
}
MsgTable * pmtNew = placement_new(pvAlloc, MsgTable);
pmtNew->m_cMsgs = cTotalMsgs;
pmtNew->m_pmcPeer = pmcPeer;
pmtNew->m_pmtSuper = pmtSuper;
//
// Setup message entries
// - Copy messages from super-class
// - Override and add messages from new class
//
// NOTE: We are using GArrayS<> to store the array of this pointers. The
// data stored in here points to the beginning of the array of data.
// Before this array, we store the size, but we don't need to worry about
// that here.
//
if (cTotalMsgs > 0) {
MsgSlot * rgmsDest = pmtNew->GetSlots();
int cThisDepth = pmtSuper != NULL ? pmtSuper->GetDepth() + 1 : 0;
int cbThisOffset = cThisDepth * sizeof(void *);
int idxAdd = 0;
if (pmtSuper != NULL) {
const MsgSlot * rgmsSrc = pmtSuper->GetSlots();
for (idxAdd = 0; idxAdd < cSuperMsgs; idxAdd++) {
rgmsDest[idxAdd] = rgmsSrc[idxAdd];
}
}
Assert(idxAdd == cSuperMsgs);
for (int idx = 0; idx < pmcInfo->cMsgs; idx++) {
const DUser::MessageInfoGuts * pmi = &pmcInfo->rgMsgInfo[idx];
ATOM atomMsg = 0;
int idxMsg = -1;
if (pmi->pfn == NULL) {
continue; // Just skip this slot
}
if ((pmtSuper == NULL) || // No super
((atomMsg = FindAtomW(pmi->pszMsgName)) == 0) || // Message not yet defined
((idxMsg = pmtSuper->FindIndex(atomMsg)) < 0)) { // Message not in super
//
// Function is defined, so it should be added.
//
atomMsg = AddAtomW(pmi->pszMsgName);
idxMsg = idxAdd++;
}
MsgSlot & ms = rgmsDest[idxMsg];
ms.atomNameID = atomMsg;
ms.cbThisOffset = cbThisOffset;
ms.pfn = pmi->pfn;
}
AssertMsg(idxAdd == cTotalMsgs, "Should have added all messages");
//
// Check to see if any messages were not properly setup.
//
BOOL fMissing = FALSE;
for (idx = 0; idx < cTotalMsgs; idx++) {
if (rgmsDest[idx].pfn == NULL) {
//
// Function is not defined and is not in the super. This is
// an error because it is being declared "new" and not being
// defined.
//
WCHAR szMsgName[256];
GetAtomNameW(rgmsDest[idx].atomNameID, szMsgName, _countof(szMsgName));
Trace("ERROR: DUser: %S::%S() was not properly setup.\n",
pmcInfo->pszClassName, szMsgName);
fMissing = TRUE;
}
}
if (fMissing) {
PromptInvalid("Class registration does not have all functions properly setup.");
hr = DU_E_MESSAGENOTIMPLEMENTED;
goto ErrorExit;
}
}
//
// Done building- return out
//
*ppmtNew = pmtNew;
return S_OK;
ErrorExit:
delete pmtNew;
return hr;
}
/***************************************************************************\
*
* MsgTable::FindIndex
*
* FindIndex() finds the corresponding index for the specified
* method / message.
*
\***************************************************************************/
int
MsgTable::FindIndex(
IN ATOM atomNameID // Method to find
) const
{
const MsgSlot * rgSlots = GetSlots();
for (int idx = 0; idx < m_cMsgs; idx++) {
if (rgSlots[idx].atomNameID == atomNameID) {
return idx;
}
}
return -1;
}
/***************************************************************************\
*
* MsgTable::Find
*
* Find() finds the corresponding MsgSlot for the specified method / message.
*
\***************************************************************************/
const MsgSlot *
MsgTable::Find(
IN ATOM atomNameID // Method to find
) const
{
int idx = FindIndex(atomNameID);
if (idx >= 0) {
return &(GetSlots()[idx]);
} else {
return NULL;
}
}