2025-04-27 07:49:33 -04:00

960 lines
28 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1997.
//
// File: globals.cxx
//
// Contents: Implementation of Class used to encapsulate shared global
// data structures for DCOM95.
//
// History: 13-Feb-96 SatishT Created
//
//--------------------------------------------------------------------------
#include <or.hxx>
#include <winsock.h>
//--------------------------------------------------------------------------
//
// some helper stuff for calling winsock functions dynamically
//
// CODEWORK - move this into dynload.cxx and dynload.hxx in ole32\common
//
//--------------------------------------------------------------------------
extern "C" {
// implemented in epts.c
BOOL LoadWSockIfNecessary();
struct hostent * COMgethostbyname(const char *name);
char * COMinet_ntoa(struct in_addr addr);
};
//
// Helper function which initializes local DSA and string of protocol
// sequences, and as a side effect, starts all remote protocols
//
static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc";
static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols";
//
// Helper function for local only situation
//
void
SetDefaultSecurity(SharedSecVals *gpSecVals)
{
// init security part for pure local operation
gpSecVals->s_fEnableDCOM = FALSE;
gpSecVals->s_fEnableRemoteLaunch = FALSE;
gpSecVals->s_fEnableRemoteConnect = FALSE;
gpSecVals->s_lAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
gpSecVals->s_lImpLevel = RPC_C_IMP_LEVEL_ANONYMOUS;
gpSecVals->s_fMutualAuth = FALSE;
gpSecVals->s_fSecureRefs = FALSE;
gpSecVals->s_cServerSvc = 0;
gpSecVals->s_aServerSvc = NULL;
gpSecVals->s_cClientSvc = 0;
gpSecVals->s_aClientSvc = NULL;
gpSecVals->s_cChannelHook = 0;
gpSecVals->s_aChannelHook = NULL;
}
ORSTATUS
SetPureLocal(
OUT PWSTR &pwstrProtseqs,
OUT DUALSTRINGARRAY * &pdsaProtseqs,
OUT USHORT &cRemoteProtseqs,
OUT USHORT * &aRemoteProtseqs
)
{
// init protocol sequence part for pure local operation
cRemoteProtseqs = 0;
aRemoteProtseqs = NULL;
pwstrProtseqs = (WCHAR*) OrMemAlloc(2*sizeof(WCHAR));
if (NULL == pwstrProtseqs)
{
return OR_NOMEM;
}
pwstrProtseqs[0] = pwstrProtseqs[1] = 0;
pdsaProtseqs = (DUALSTRINGARRAY*)
OrMemAlloc(sizeof(DUALSTRINGARRAY) + 3 * sizeof(WCHAR));
if (NULL == pdsaProtseqs)
{
OrMemFree(pwstrProtseqs);
return OR_NOMEM;
}
memset(pdsaProtseqs, 0, sizeof(DUALSTRINGARRAY) + 3 * sizeof(WCHAR));
pdsaProtseqs->wNumEntries = 4;
pdsaProtseqs->wSecurityOffset = 2;
return OR_OK;
}
//
// Helper functions to query registry and initialize
// variables for remote protocol info
//
ORSTATUS
ListenOnRemoteProtocols(
OUT PWSTR &pwstrProtseqs
)
{
ORSTATUS status = OR_OK;
// Initialize out parameter
pwstrProtseqs = NULL;
DWORD dwType;
DWORD dwLenBuffer = InitialProtseqBufferLength;
HKEY hKey;
status =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
gpwstrProtocolsPath,
0,
KEY_READ,
&hKey);
if (status == ERROR_SUCCESS)
{
do
{
OrMemFree(pwstrProtseqs);
pwstrProtseqs = (WCHAR*) OrMemAlloc(dwLenBuffer);
if (pwstrProtseqs)
{
status = RegQueryValueEx(hKey,
gpwstrProtocolsValue,
0,
&dwType,
(PBYTE)pwstrProtseqs,
&dwLenBuffer
);
}
else
{
RegCloseKey(hKey);
return OR_NOMEM;
}
}
while (status == ERROR_MORE_DATA);
}
RegCloseKey(hKey);
if (status != ERROR_SUCCESS)
{
OrMemFree(pwstrProtseqs);
return status;
}
PWSTR pwstr = pwstrProtseqs;
while(*pwstr)
{
// skip leading whitespace
while ((*pwstr == L'\t') || (*pwstr == L' '))
pwstr++;
USHORT id = GetProtseqId(pwstr);
if ((0 != id) && (ID_NP != id) && !IsLocal(id))
{
status = UseProtseqIfNecessary(id);
// ronans - DCOMHTTP:
if (id == ID_DCOMHTTP)
{
*gpfClientHttp = TRUE;
}
}
pwstr = OrStringSearch(pwstr, 0) + 1;
}
return OR_OK;
}
const int MAX_IP_BINDINGS = 100;
void
SetInetBindings(
IN USHORT id,
IN OUT PWSTR * const &aBindings,
IN OUT USHORT * const &aProtseqs,
IN OUT USHORT &cRemoteProtseqs,
IN OUT USHORT &psaLen
)
{
PWSTR pwstrStringBinding = NULL;
if (!LoadWSockIfNecessary())
{
// ronans: CODEWORK we should have better failure reporting here
return;
}
struct hostent *hostentry = COMgethostbyname( NULL ); // get local IP addresses
if (hostentry == (struct hostent *) 0)
{
return;
}
char * szAddress = NULL;
for (int NumNetworkAddress = 0;
hostentry->h_addr_list[NumNetworkAddress] != 0;
NumNetworkAddress++
)
{
szAddress = COMinet_ntoa(*((struct in_addr*)hostentry->h_addr_list[NumNetworkAddress]));
USHORT cAddrLen = lstrlenA(szAddress) + 1;
WCHAR *pwstrAddr = (WCHAR*) alloca(sizeof(WCHAR)*cAddrLen);
if(!(MultiByteToWideChar(CP_ACP,
0,
szAddress,
-1,
pwstrAddr,
cAddrLen)))
{
return;
}
RPC_STATUS status = RpcStringBindingComposeW(
NULL,
gaProtseqInfo[id].pwstrProtseq,
pwstrAddr,
GetEndpoint(id),
NULL,
&pwstrStringBinding
);
aProtseqs[cRemoteProtseqs] = id;
aBindings[cRemoteProtseqs] = pwstrStringBinding;
cRemoteProtseqs++;
psaLen += OrStringLen(pwstrStringBinding) + 1;
pwstrStringBinding = NULL;
}
}
ORSTATUS
GetResolverBindings(
OUT DUALSTRINGARRAY *&pdsaProtseqs,
OUT USHORT &cRemoteProtseqs,
OUT USHORT * &aRemoteProtseqs
)
{
ORSTATUS status = OR_OK;
DUALSTRINGARRAY *pdsaPS = NULL;
// Initialize out parameters
pdsaProtseqs =NULL;
cRemoteProtseqs = 0;
aRemoteProtseqs = NULL;
RPC_BINDING_VECTOR *pbv = NULL;
PWSTR pwstrT;
USHORT psaLen = 0;
DWORD i;
status = RpcServerInqBindings(&pbv);
ASSERT(status == RPC_S_NO_BINDINGS || pbv != NULL);
// ronans - DCOMHTTP
if (status == RPC_S_NO_BINDINGS)
{
// No registered remote protocol available
return status;
}
PWSTR aBindings[MAX_PROTSEQ_IDS];
USHORT aProtseqs[MAX_PROTSEQ_IDS];
// this is for internet protocols only
BOOL protseqs_done[2] = {FALSE,FALSE};
// Build array of protseqs id's and addresses we're listening to.
for(i = 0; i < pbv-> Count; i++)
{
PWSTR pwstrStringBinding;
status = RpcBindingToStringBinding(pbv->BindingH[i], &pwstrStringBinding);
if (status != RPC_S_OK)
{
break;
}
ASSERT(pwstrStringBinding);
status = RpcStringBindingParse(
pwstrStringBinding,
NULL,
&pwstrT,
NULL,
NULL,
NULL
);
if (status != RPC_S_OK)
{
break;
}
USHORT id = GetProtseqId(pwstrT);
if (!IsLocal(id))
{
if ((id == ID_TCP) || (id == ID_UDP)) // an IP protocol
{
// We need a special dispensation for IP bindings since these
// may change as a result of RAS connection/disconnection
// The changes are not reflected in InqBindings since the
// socket(s) are acquired before the change occurred
// IP protocols may have multiple addresses and may get into aProtseqs,
// etc, multiple times and are counted multiple times. This seems
// benign, but needs to be watched.
// if we do show multiple bindings per protocol, we only want to process
// each protocol once using the standard SetInetBindings code path
if (protseqs_done[id-ID_TCP])
{
continue;
}
else
{
protseqs_done[id-ID_TCP] = TRUE;
}
SetInetBindings(id,aBindings,aProtseqs,cRemoteProtseqs,psaLen);
}
else
{
aProtseqs[cRemoteProtseqs] = id;
aBindings[cRemoteProtseqs] = pwstrStringBinding;
cRemoteProtseqs++;
psaLen += OrStringLen(pwstrStringBinding) + 1;
// ronans - DCOMHTTP:
// treat http as a normal case as it shows up in the bindings
// (this shouldn't happen under windows 95 with the current RPC implementation)
// but it may in future
if (id == ID_DCOMHTTP)
{
*gpfClientHttp = FALSE;
}
}
}
else
{
RpcStringFree(&pwstrStringBinding);
}
status = RpcStringFree(&pwstrT);
ASSERT(status == RPC_S_OK && pwstrT == 0);
}
if (pbv)
status = RpcBindingVectorFree(&pbv);
ASSERT(pbv == 0 && status == RPC_S_OK);
if (cRemoteProtseqs == 0)
{
// No remote bindings
return RPC_S_NO_BINDINGS;
}
// for non NT networks accessed through NT security client, get the default
// server principal name -- this works primarily for Netware right now.
// See BUGBUG below for generality problem
WCHAR * pwszPrincName;
status = RpcServerInqDefaultPrincNameW(
RPC_C_AUTHN_WINNT,
&pwszPrincName
);
if (status != RPC_S_OK)
{
pwszPrincName = L""; // No name, nothing in DSA
}
// string bindings final null, authn and authz service, principal name and two final nulls
USHORT cPrincNameLen = lstrlenW(pwszPrincName);
psaLen += 1 + 2 + cPrincNameLen + 2;
pdsaPS = new (psaLen * sizeof(WCHAR)) DUALSTRINGARRAY;
aRemoteProtseqs = (USHORT *) OrMemAlloc(sizeof(USHORT)*cRemoteProtseqs);
if (pdsaPS == NULL || aRemoteProtseqs == NULL)
{
for ( i = 0; i < cRemoteProtseqs; i++ )
{
status = RpcStringFree(&aBindings[i]);
ASSERT(status == RPC_S_OK);
}
return OR_NOMEM;
}
pdsaPS->wNumEntries = psaLen;
pdsaPS->wSecurityOffset = psaLen - (4 + cPrincNameLen);
pwstrT = pdsaPS->aStringArray;
for ( i = 0; i < cRemoteProtseqs; i++ )
{
OrStringCopy(pwstrT, aBindings[i]);
pwstrT += OrStringLen(aBindings[i]) + 1;
aRemoteProtseqs[i] = aProtseqs[i];
status = RpcStringFree(&aBindings[i]);
ASSERT(status == RPC_S_OK);
}
if (psaLen == 6)
{
// No remote bindings, put in first null.
pdsaPS->aStringArray[0] = 0;
pwstrT++;
}
// Zero final terminator
*pwstrT = 0;
// Security authn service
pwstrT++;
*pwstrT = RPC_C_AUTHN_WINNT; // BUGBUG: need fix for generality
// Authz service, -1 means none // BUGBUG: -1 causes errors
pwstrT++;
*pwstrT = 0;
// Copy Principal name
pwstrT++;
OrStringCopy(pwstrT, pwszPrincName);
// Final, final NULLS
pwstrT += cPrincNameLen;
pwstrT[0] = 0;
pwstrT[1] = 0;
ASSERT(dsaValid(pdsaPS));
pdsaProtseqs = CompressStringArray(pdsaPS,TRUE);
delete pdsaPS;
if (pdsaProtseqs == NULL)
{
return OR_NOMEM;
}
return OR_OK;
}
//+-------------------------------------------------------------------------
//
// Helper: InitRemoteProtocols
//
// Synopsis: Initializing remote protocols either
// as part of shared memory initialization or
// in response to an RPCSS wakeup event
//
// Return Value: OR_OK if remote protocols were successfully initialized
// Error returned by one of the subsidiary helpers otherwise
//
// History: 08-Nov-96 SatishT Created
//
//--------------------------------------------------------------------------
ORSTATUS
InitRemoteProtocols(
OUT PWSTR &pwstrProtseqs,
OUT DUALSTRINGARRAY * &pdsaProtseqs,
OUT USHORT &cRemoteProtseqs,
OUT USHORT * &aRemoteProtseqs
)
{
ORSTATUS status;
{
//
// It is OK to release the lock here because the only memory structure
// we are using is the gaProtseqInfo array, which is local to this (RPCSS)
// process, and since this happens on the main RPCSS thread before other
// threads are started for listening, there is no chance of interference
//
CTempReleaseSharedMemory temp;
status = ListenOnRemoteProtocols(pwstrProtseqs);
}
if (status == OR_OK)
{
status = GetResolverBindings(
pdsaProtseqs,
cRemoteProtseqs,
aRemoteProtseqs
);
}
if (status != OR_OK)
{
status = OR_I_PURE_LOCAL;
ORSTATUS local_status = SetPureLocal(
pwstrProtseqs,
pdsaProtseqs,
cRemoteProtseqs,
aRemoteProtseqs
);
if (local_status != OR_OK) status = local_status;
}
ASSERT(dsaValid(pdsaProtseqs));
return status;
}
//
// Helper Macros for constructor below only
//
#define AssignAndAdvance(Var,Type) \
Type **Var = (Type **) pb; \
pb += sizeof(Type *);
#define CopySharedPointer(Var,Type) \
Var = *((Type **) pb); \
pb += sizeof(Type *);
// prototypes for functions defined in objex.cxx
HRESULT ReadRegistry();
RPC_STATUS ComputeSecurityPackages();
//+-------------------------------------------------------------------------
//
// Member: CSharedGlobals::ResetGlobals
//
// Synopsis: ReRead Shared Memory Values,
// They Have Changed because RPCSS was Launched
//
// History: 13-Feb-96 SatishT Created
//
//--------------------------------------------------------------------------
void CSharedGlobals::ResetGlobals()
{
ASSERT((_hSm != NULL) || (_pb != NULL));
BYTE * pb = _pb;
HWND *RpcssWindow = (HWND *) pb;
pb += sizeof(HWND);
gpIdSequence = (LONG *) pb;
pb += sizeof(LONG);
gpdwLastCrashedProcessCheckTime = (DWORD *) pb;
pb += sizeof(DWORD);
gpNextThreadID = (DWORD *) pb;
pb += sizeof(DWORD);
gpcRemoteProtseqs = (USHORT *) pb;
pb += sizeof(USHORT);
gpfRemoteInitialized = (USHORT *) pb;
pb += sizeof(USHORT);
gpfSecurityInitialized = (USHORT *) pb;
pb += sizeof(USHORT);
gpfClientHttp = (USHORT *) pb;
pb += sizeof(USHORT);
gpSecVals = (SharedSecVals *) pb;
pb += sizeof(SharedSecVals);
CopySharedPointer(gpRemoteProtseqIds,USHORT) // see macro above
CopySharedPointer(gpwstrProtseqs,WCHAR)
CopySharedPointer(gpLocalDSA,DUALSTRINGARRAY)
CopySharedPointer(gpLocalMid,CMid)
CopySharedPointer(gpPingProcess,CProcess)
CopySharedPointer(gpOidTable,COidTable)
CopySharedPointer(gpOxidTable,COxidTable)
CopySharedPointer(gpMidTable,CMidTable)
CopySharedPointer(gpProcessTable,CProcessTable)
}
//+-------------------------------------------------------------------------
//
// Member: CSharedGlobals::InitGlobals
//
// Synopsis: Setup Shared Memory Values,
// This may involve initializing remote protocols
// in response to an RPCSS wakeup event
//
// History: 08-Nov-96 SatishT Created
// 23-May-97 SatishT Added fRpcssReinit for RAS reinit
//
//--------------------------------------------------------------------------
ORSTATUS
CSharedGlobals::InitGlobals(BOOL fCreated, BOOL fRpcssReinit)
{
ASSERT((_hSm != NULL) || (_pb != NULL));
ORSTATUS status = OR_OK;
BYTE * pb = _pb;
// We assume that the RPCSS window is the first thing in the
// shared memory block. Don't change its position!
HWND *RpcssWindow = (HWND *) pb;
pb += sizeof(HWND);
gpIdSequence = (LONG *) pb;
pb += sizeof(LONG);
gpdwLastCrashedProcessCheckTime = (DWORD *) pb;
pb += sizeof(DWORD);
gpNextThreadID = (DWORD *) pb;
pb += sizeof(DWORD);
gpcRemoteProtseqs = (USHORT *) pb;
pb += sizeof(USHORT);
gpfRemoteInitialized = (USHORT *) pb;
pb += sizeof(USHORT);
gpfSecurityInitialized = (USHORT *) pb;
pb += sizeof(USHORT);
gpfClientHttp = (USHORT *) pb;
pb += sizeof(USHORT);
gpSecVals = (SharedSecVals *) pb;
pb += sizeof(SharedSecVals);
AssignAndAdvance(DCOMProtseqIds,USHORT) // see macro above
AssignAndAdvance(DCOMProtseqs,WCHAR)
AssignAndAdvance(LocalDSA,DUALSTRINGARRAY)
AssignAndAdvance(LocalMid,CMid)
AssignAndAdvance(PingProcess,CProcess)
AssignAndAdvance(OidTable,COidTable)
AssignAndAdvance(OxidTable,COxidTable)
AssignAndAdvance(MidTable,CMidTable)
AssignAndAdvance(ProcessTable,CProcessTable)
// The remainder of the shared memory block contains
// page allocators for the various shared memory structures
_aPageAllocators = (CPageAllocator*) pb;
if (fCreated) // if we got here first, so create the tables
{
memset(_pb, 0, GLOBALS_TABLE_SIZE);
// Initialize the sequence number for AllocateId, the last time crashed
// processes were detected and the thread ID sequence in shared memory
*gpIdSequence = 1;
*gpdwLastCrashedProcessCheckTime = 0;
*gpNextThreadID = GetTickCount();
*gpfRemoteInitialized = FALSE;
*gpfSecurityInitialized = FALSE;
*gpfClientHttp = FALSE;
// I know this is paranoid but I have been bitten before ..
gpRemoteProtseqIds = NULL;
gpwstrProtseqs = NULL;
gpLocalDSA = NULL;
gpLocalMid = NULL;
gpPingProcess = NULL;
gpOxidTable = NULL;
gpOidTable = NULL;
gpMidTable = NULL;
gpProcessTable = NULL;
// Compute Default Security -- services and flags
SetDefaultSecurity(gpSecVals);
// Get standard DCOM flags from registry
ReadRegistry();
// Initialize local MID object to NULL
*LocalMid = NULL;
// initialize RPCSS's process object in shared memory
// to NULL. This will be reset by RPCSS when launched.
*PingProcess = NULL;
// initialize RPCSS's messaging window in shared memory
// to NULL. This will be reset by RPCSS when launched.
*RpcssWindow = NULL;
// Initialize the page-based allocators for all shared
// memory data structures -- and do it before allocating
// the hash tables in shared memory!
for (USHORT i = 0; i < NUM_PAGE_ALLOCATORS; i++)
{
_aPageAllocators[i].Initialize(
AllocatorEntrySize[i],
AllocatorPageSize[i],
OrMemAlloc,
OrMemFree,
FALSE
);
}
// Need to assign this here before use
ASSIGN_PAGE_ALLOCATOR(CResolverHashTable)
// Assume 16 exporting processes/threads.
*OxidTable = (COxidTable*) new CResolverHashTable(OXID_TABLE_SIZE);
// Assume 11 exported OIDs per process/thread.
*OidTable = (COidTable*) new CResolverHashTable(OID_TABLE_SIZE);
// Assume 16 machine locations for OXIDs.
*MidTable = (CMidTable*) new CResolverHashTable(MID_TABLE_SIZE);
// Assume 16 simultaneouly active local processes.
*ProcessTable = (CProcessTable*) new CResolverHashTable(PROCESS_TABLE_SIZE);
}
// set up page allocators
ASSIGN_PAGE_ALLOCATOR(COid)
ASSIGN_PAGE_ALLOCATOR(COxid)
ASSIGN_PAGE_ALLOCATOR(CMid)
ASSIGN_PAGE_ALLOCATOR(CProcess)
ASSIGN_PAGE_ALLOCATOR(CClassReg)
// This is not strictly necessary since these tables are allocated
// only when the shared file mapping is created, but the (possibly duplicate)
// initialization does no harm
ASSIGN_PAGE_ALLOCATOR(CResolverHashTable)
// Can't use ASSIGN_PAGE_ALLOCATOR for this one:
// CLinkList::Link_ALLOCATOR_INDEX won't work the same way
CLinkList::Link::_pAlloc = &_aPageAllocators[Link_ALLOCATOR_INDEX];
CLinkList::Link::_fPageAllocatorInitialized = TRUE;
if (gfThisIsRPCSS)
{
// initialize RPCSS's HWND for messages in shared memory
*RpcssWindow = ghRpcssWnd;
ASSERT(ghRpcssWnd); // it should be initialized by the time we get here
}
PWSTR pwstr = NULL;
DUALSTRINGARRAY *pdsa = NULL;
USHORT *aProtseqIds = NULL;
if (*gpfRemoteInitialized == FALSE || fRpcssReinit == TRUE)
{
BOOL fNewDSA = FALSE;
MID SavedMID = 0;
RPC_STATUS remote_status = RPC_S_OK;
// Remote protocol and security package init happens only in RPCSS
if (gfThisIsRPCSS)
{
// initialize RPCSS's process object in shared memory if necessary
if (*PingProcess == NULL)
{
*PingProcess = new CProcess(0);
}
if (*gpfSecurityInitialized == FALSE)
{
// initialize installed security package info
remote_status = ComputeSecurityPackages();
if (remote_status == RPC_S_OK)
{
*gpfSecurityInitialized = TRUE;
}
}
if (remote_status == RPC_S_OK)
{
// initialize remote protocol strings and
// the DSA bindings of local OR in shared memory
remote_status = InitRemoteProtocols(
pwstr,
pdsa,
*gpcRemoteProtseqs,
aProtseqIds
);
}
if (remote_status == RPC_S_OK)
{
*gpfRemoteInitialized = TRUE;
fNewDSA = !gpLocalDSA || !dsaCompare(gpLocalDSA,pdsa);
}
else if (remote_status == OR_I_PURE_LOCAL)
// InitRemoteProtocols failed or only http is registered,
// but we set pure local
{
if (*gpfClientHttp)
*gpfRemoteInitialized = TRUE;
fNewDSA = (*LocalMid == NULL);
}
if (!fNewDSA)
// we aren't going to use the output of InitRemoteProtocols
{
OrMemFree(pwstr);
OrMemFree(pdsa);
OrMemFree(aProtseqIds);
}
if (remote_status != RPC_S_OK && remote_status != OR_I_PURE_LOCAL)
{
return remote_status;
}
// delete the bogus stuff, if new DSA, but steal the old MID
if (fNewDSA && *LocalMid != NULL)
{
SavedMID = (*LocalMid)->GetMID();
(*MidTable)->Remove(**LocalMid);
}
}
else if (*LocalMid == NULL)
{
// set up some bogus stuff temporarily
status = SetPureLocal(
pwstr,
pdsa,
*gpcRemoteProtseqs,
aProtseqIds
);
if (status == OR_OK)
{
fNewDSA = TRUE;
}
}
if (fNewDSA)
{
// Need to initialize gpRemoteProtseqIds here because the CMid
// constructor uses this value
gpRemoteProtseqIds = *DCOMProtseqIds = aProtseqIds;
*DCOMProtseqs = pwstr;
*LocalDSA = pdsa;
ASSERT(dsaValid(pdsa));
// initialize local Mid object in shared memory
ORSTATUS MidOK;
MID NewMID = SavedMID ? SavedMID : AllocateId();
*LocalMid = new CMid(*LocalDSA,MidOK,0,NewMID,FALSE);
if (MidOK != OR_OK)
{
delete *LocalMid;
*LocalMid = NULL;
}
// Add local CMid object to global shared table
if (*LocalMid && *MidTable)
status = (*MidTable)->Add(*LocalMid);
}
}
gpRemoteProtseqIds = *DCOMProtseqIds;
gpwstrProtseqs = *DCOMProtseqs;
gpLocalDSA = *LocalDSA;
gpLocalMid = *LocalMid;
gpPingProcess = *PingProcess;
gpOxidTable = *OxidTable;
gpOidTable = *OidTable;
gpMidTable = *MidTable;
gpProcessTable = *ProcessTable;
ASSERT(dsaValid(gpLocalDSA));
return status;
}
//+-------------------------------------------------------------------------
//
// Member: CSharedGlobals::CSharedGlobals
//
// Synopsis: Create table of globals for DCOM95
//
// Arguments: [pwszName] - name for shared memory
//
// Algorithm: Create and map in shared memory for the table
//
// History: 13-Feb-96 SatishT Created
//
//--------------------------------------------------------------------------
CSharedGlobals::CSharedGlobals(WCHAR *pwszName, ORSTATUS &status)
/*---
NOTE: This constructor uses the shared allocator. Objects of this class
should not be created before the shared allocator is initialized.
---*/
{
BOOL fCreated = FALSE;
status = OR_OK;
_hSm = CreateSharedFileMapping(
pwszName,
GLOBALS_TABLE_SIZE,
GLOBALS_TABLE_SIZE,
NULL,
NULL,
PAGE_READWRITE,
(void **) &_pb,
&fCreated
);
Win4Assert(_hSm && _pb && "CSharedGlobals create shared file mapping failed");
if ((_hSm == NULL) || (_pb == NULL))
{
status = OR_INTERNAL_ERROR;
return;
}
status = InitGlobals(fCreated);
}