767 lines
16 KiB
C++
767 lines
16 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Manager.cxx
|
||
|
||
Abstract:
|
||
|
||
InProc OR interface
|
||
|
||
Author:
|
||
|
||
Satish Thatte [SatishT] Feb-07-1996
|
||
|
||
Revision Hist:
|
||
|
||
SatishT 02-07-96 Created
|
||
|
||
--*/
|
||
|
||
|
||
#include <or.hxx>
|
||
|
||
|
||
//
|
||
// Manager (server-side) calls to the local OR interface. lclor.idl
|
||
//
|
||
|
||
error_status_t
|
||
ConnectDCOM(
|
||
IN OUT HPROCESS *phProcess,
|
||
OUT ULONG *pdwTimeoutInSeconds,
|
||
OUT MID *pLocalMid,
|
||
OUT ULONG *pfConnectFlags,
|
||
OUT DWORD *pAuthnLevel,
|
||
OUT DWORD *pImpLevel,
|
||
OUT DWORD *pcServerSvc,
|
||
OUT USHORT **aServerSvc,
|
||
OUT DWORD *pcClientSvc,
|
||
OUT USHORT **aClientSvc,
|
||
OUT DWORD *pThreadID
|
||
)
|
||
{
|
||
ORSTATUS status = OR_OK;
|
||
CProcess *hProcess;
|
||
|
||
StartDCOM();
|
||
|
||
*pdwTimeoutInSeconds = BaseTimeoutInterval;
|
||
*pLocalMid = gLocalMID;
|
||
|
||
// Fill in security parameters.
|
||
|
||
*pfConnectFlags = 0;
|
||
|
||
if (s_fEnableDCOM == FALSE) *pfConnectFlags |= CONNECT_DISABLEDCOM;
|
||
if (s_fMutualAuth) *pfConnectFlags |= CONNECT_MUTUALAUTH;
|
||
if (s_fSecureRefs) *pfConnectFlags |= CONNECT_SECUREREF;
|
||
|
||
*pAuthnLevel = s_lAuthnLevel;
|
||
*pImpLevel = s_lImpLevel;
|
||
*pcServerSvc = s_cServerSvc;
|
||
*aServerSvc = CopyArray(s_cServerSvc,s_aServerSvc,&status);
|
||
*pcClientSvc = s_cClientSvc;
|
||
*aClientSvc = CopyArray(s_cClientSvc,s_aClientSvc,&status);
|
||
|
||
if (status != OR_OK) return status;
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
*pThreadID = (*gpNextThreadID)++;
|
||
|
||
hProcess = new CProcess((long) *phProcess); // BUGBUG: this is a temp ID
|
||
// coming from bridge.cxx
|
||
|
||
if (hProcess)
|
||
{
|
||
gpProcess = *phProcess = hProcess;
|
||
gpProcessTable->Add(hProcess); // BUGBUG: and rundown an old process,
|
||
// if there is one, with the same _processID
|
||
}
|
||
else
|
||
{
|
||
status = OR_NOMEM;
|
||
}
|
||
|
||
OrDbgDetailPrint(("OR: Client connected\n"));
|
||
|
||
return(status);
|
||
}
|
||
|
||
|
||
error_status_t Disconnect(
|
||
IN OUT HPROCESS *phProcess
|
||
)
|
||
{
|
||
// ASSERT(*phProcess!=NULL); // BUGBUG: the right thing to do
|
||
if (*phProcess == NULL) return OR_OK;
|
||
|
||
CProcess *hProcess = *phProcess;
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
hProcess->Rundown();
|
||
gpProcessTable->Remove(*hProcess);
|
||
*phProcess = NULL;
|
||
DCOM_Started = FALSE;
|
||
return OR_OK;
|
||
}
|
||
|
||
|
||
|
||
error_status_t
|
||
AllocateReservedIds(
|
||
IN LONG cIdsToReserve,
|
||
OUT ID *pidReservedBase
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called by local clients to reserve a range of IDs which will
|
||
not conflict with any other local IDs.
|
||
|
||
Arguments:
|
||
|
||
cIdsToReserve - Number of IDs to reserve.
|
||
|
||
pidReservedBase - Starting value of the reserved IDs. The
|
||
lower DWORD of this can be increatmented to generate
|
||
cIdsToReserve unique IDs.
|
||
|
||
Return Value:
|
||
|
||
OR_OK
|
||
|
||
--*/
|
||
{
|
||
UINT type;
|
||
|
||
if (cIdsToReserve > 10 || cIdsToReserve < 0)
|
||
{
|
||
cIdsToReserve = 10;
|
||
}
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
*pidReservedBase = AllocateId(cIdsToReserve);
|
||
return(OR_OK);
|
||
}
|
||
|
||
|
||
error_status_t
|
||
GetOXID(
|
||
IN HPROCESS hProcess,
|
||
IN OXID Oxid,
|
||
IN DUALSTRINGARRAY *pdsaServerObjectResolverBindings,
|
||
IN long fApartment,
|
||
IN USHORT wProtseqId,
|
||
OUT OXID_INFO& OxidInfo,
|
||
OUT MID &Mid
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Discovers the OXID_INFO for an oxid. Will find local
|
||
OXIDs without any help from resolver process.
|
||
|
||
It needs OR bindings in order to resolve remote OXIDs.
|
||
REVIEW: Should the resolver process be involved in this?
|
||
|
||
Arguments:
|
||
|
||
hProcess - The context handle of the process.
|
||
|
||
Oxid - The OXID (a uuid) to resolve.
|
||
|
||
pdsaServerObjectResolverBindings - Compressed string bindings to
|
||
the OR on the server's machine.
|
||
|
||
fApartment - non-zero if the client is aparment model.
|
||
|
||
OxidInfo - If successful this will contain information about the oxid and
|
||
an expanded string binding to the server oxid's process.
|
||
|
||
Mid - The machine ID assigned locally for the remote machine.
|
||
This is obviously meaningful only for remote OXIDs.
|
||
|
||
Return Value:
|
||
|
||
OR_NOMEM - Common.
|
||
|
||
OR_BADOXID - Unable to resolve it.
|
||
|
||
OR_OK - Success.
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ResolveClientOXID OXID = %08x\n",Oxid));
|
||
|
||
COxid *pOxid;
|
||
CMid *pMid;
|
||
ORSTATUS status = OR_OK;
|
||
BOOL fNewMID = FALSE;
|
||
|
||
if (wProtseqId == 0) // Normal (non SCM) call
|
||
{
|
||
// In case of failure, zero out param pointers.
|
||
OxidInfo.psa = NULL;
|
||
}
|
||
|
||
if (!pdsaServerObjectResolverBindings)
|
||
pdsaServerObjectResolverBindings = gpLocalDSA;
|
||
|
||
ASSERT(dsaValid(pdsaServerObjectResolverBindings));
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
if (hProcess) hProcess->IsValid(); // don't validate for fake SCM calls
|
||
#endif
|
||
|
||
if (dsaCompare(gpLocalDSA,pdsaServerObjectResolverBindings)) // local OXID
|
||
{
|
||
pMid = gpLocalMid;
|
||
}
|
||
else
|
||
{
|
||
// Attempt to lookup MID
|
||
|
||
// CMidKey makes a copy of the bindings to maintain validity
|
||
|
||
CMidKey midkey(pdsaServerObjectResolverBindings,TRUE,status);
|
||
|
||
if (status != OR_OK) return status;
|
||
|
||
pMid = gpMidTable->Lookup(midkey);
|
||
|
||
if (NULL == pMid)
|
||
{
|
||
pMid = new(pdsaServerObjectResolverBindings->wNumEntries * sizeof(WCHAR))
|
||
CMid(pdsaServerObjectResolverBindings, status, wProtseqId);
|
||
|
||
// We initialize local MID autologically,
|
||
// therefore this has to be a remote MID
|
||
|
||
if (pMid && status == OR_OK)
|
||
{
|
||
status = gpMidTable->Add(pMid);
|
||
if (status != OR_OK)
|
||
{
|
||
delete pMid;
|
||
return status;
|
||
}
|
||
|
||
fNewMID = TRUE;
|
||
}
|
||
else
|
||
{
|
||
return (status == OR_OK) ? OR_NOMEM : status;
|
||
}
|
||
}
|
||
}
|
||
|
||
ASSERT(pMid); // otherwise we would have returned by now
|
||
|
||
Mid = pMid->GetMID();
|
||
|
||
pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid));
|
||
|
||
if (pMid->IsLocal())
|
||
{
|
||
ASSERT(!fNewMID);
|
||
|
||
if (pOxid)
|
||
{
|
||
return pOxid->GetInfo(&OxidInfo);
|
||
}
|
||
else // local OXIDs should be registered by server
|
||
{
|
||
return OR_BADOXID;
|
||
}
|
||
}
|
||
|
||
if (NULL == pOxid)
|
||
{
|
||
// Need to allocate the OXID. First step is to resolve it remotely.
|
||
|
||
if ( OxidInfo.psa == NULL ) // genuine resolve request rather
|
||
// than a phoney one from the SCM
|
||
{
|
||
status = pMid->ResolveRemoteOxid( // This op will also replace the
|
||
Oxid, // psa with one in shared memory
|
||
&OxidInfo
|
||
);
|
||
|
||
wProtseqId = pMid->ProtseqOfServer();
|
||
}
|
||
|
||
ASSERT( (status != OR_OK) || (OxidInfo.psa != NULL) );
|
||
|
||
if (status == OR_OK)
|
||
{
|
||
DUALSTRINGARRAY *pdsaT = dsaSMCopy(OxidInfo.psa);
|
||
|
||
if (!pdsaT)
|
||
{
|
||
return OR_NOMEM;
|
||
}
|
||
|
||
MIDL_user_free(OxidInfo.psa); // free the original and replace
|
||
OxidInfo.psa = pdsaT; // with shared memory compressed copy
|
||
|
||
pOxid = new COxid(
|
||
Oxid,
|
||
pMid,
|
||
wProtseqId,
|
||
OxidInfo
|
||
);
|
||
|
||
// remote OXID belongs to ping process ..
|
||
|
||
if ((NULL != pOxid) && (gpPingProcess->OwnOxid(pOxid) == OR_OK))
|
||
{
|
||
status = gpOxidTable->Add(pOxid);
|
||
}
|
||
else
|
||
{
|
||
OrMemFree(OxidInfo.psa);
|
||
delete pOxid;
|
||
return status;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MIDL_user_free(OxidInfo.psa);
|
||
return OR_BADOXID;
|
||
}
|
||
}
|
||
|
||
ASSERT( (status == OR_OK) && pOxid );
|
||
|
||
return pOxid->GetInfo(&OxidInfo);
|
||
}
|
||
|
||
|
||
error_status_t
|
||
ClientAddOID(
|
||
IN HPROCESS hProcess,
|
||
IN OID Oid,
|
||
IN OXID Oxid,
|
||
IN MID Mid
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates the set of OIDs in use by a process.
|
||
|
||
|
||
Arguments:
|
||
|
||
hProcess - Context handle for the process.
|
||
|
||
Oid - OID to add.
|
||
|
||
Oxid - OXID to which OID belongs.
|
||
|
||
Mid - MID for location of OXID server.
|
||
|
||
Return Value:
|
||
|
||
OR_OK - All updates completed ok.
|
||
|
||
OR_BADOXID - The Oxid was not found
|
||
|
||
OR_BADOID - The Oid could not be created or found
|
||
|
||
Notes:
|
||
|
||
Unlike the NT resolver, there is no possibility that the Oxid
|
||
is not in the gpOxidTable (since client and server Oxid objects
|
||
are in the same table).
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ClientAddOID\nOID = %08x\nOXID = %08x\nMID = %08x\n",
|
||
Oid,Oxid,Mid));
|
||
|
||
ORSTATUS status = OR_OK;
|
||
|
||
// Lookup up the oxid owning this new oid.
|
||
|
||
COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,Mid));
|
||
|
||
if (NULL == pOxid)
|
||
{
|
||
return OR_BADOXID;
|
||
}
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
hProcess->IsValid();
|
||
#endif
|
||
|
||
CMid *pMid = pOxid->GetMid();
|
||
|
||
// Find or create the oid.
|
||
|
||
COid *pOid = gpOidTable->Lookup(CId2Key(Oid,Mid));
|
||
|
||
if (NULL == pOid)
|
||
{
|
||
ASSERT(!pMid->IsLocal()); // Local OID should be registered by server
|
||
|
||
pOid = new COid(Oid,pOxid);
|
||
|
||
if (NULL == pOid)
|
||
{
|
||
return OR_NOMEM;
|
||
}
|
||
|
||
status = gpOidTable->Add(pOid);
|
||
if (status != OR_OK)
|
||
{
|
||
delete pOid;
|
||
return status;
|
||
}
|
||
|
||
status = pMid->AddClientOid(pOid);
|
||
}
|
||
|
||
if (status == OR_OK) status = hProcess->AddOid(pOid);
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
error_status_t
|
||
ClientDropOID(
|
||
IN HPROCESS hProcess,
|
||
IN OID Oid,
|
||
IN MID Mid
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates the set of remote OIDs in use by a process.
|
||
|
||
|
||
Arguments:
|
||
|
||
hProcess - Context handle for the process.
|
||
|
||
Oid - OID to be removed.
|
||
|
||
Mid - MID to which Oid belongs.
|
||
|
||
Return Value:
|
||
|
||
OR_OK - All updates completed ok.
|
||
|
||
OR_BADOID - The Oid could not be found
|
||
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ClientDropOID\nOID = %08x\nMID = %08x\n",
|
||
Oid,Mid));
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
hProcess->IsValid();
|
||
#endif
|
||
|
||
COid * pOid = gpOidTable->Lookup(CId2Key(Oid,Mid));
|
||
|
||
if (pOid)
|
||
{
|
||
COid *pRemove = hProcess->DropOid(pOid);
|
||
|
||
if (pRemove == NULL)
|
||
{
|
||
|
||
#if DBG
|
||
{
|
||
GUID Moid;
|
||
MOIDFromOIDAndMID(Oid,Mid,&Moid);
|
||
ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \
|
||
it didn't own\n", hProcess->GetProcessID(), &Moid));
|
||
}
|
||
#endif // DBG
|
||
|
||
return OR_BADOID;
|
||
}
|
||
else
|
||
{
|
||
ASSERT(pRemove == pOid);
|
||
return OR_OK;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
#if DBG
|
||
{
|
||
GUID Moid;
|
||
MOIDFromOIDAndMID(Oid,Mid,&Moid);
|
||
ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \
|
||
doesn't exist\n", hProcess->GetProcessID(), &Moid));
|
||
}
|
||
#endif // DBG
|
||
|
||
return OR_BADOID;
|
||
}
|
||
}
|
||
|
||
|
||
error_status_t
|
||
ServerAllocateOXID(
|
||
IN HPROCESS hProcess,
|
||
IN long fApartment,
|
||
IN OXID_INFO *pOxidInfo,
|
||
IN DUALSTRINGARRAY *pdsaStringBindings,
|
||
OUT OXID &Oxid
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocates an OXID and 0 or more OIDs from the OR.
|
||
|
||
Arguments:
|
||
|
||
hProcess - The context handle of the process containing the OXID.
|
||
|
||
fApartment - is the server threading model apartment or free
|
||
|
||
OxidInfo - The OXID_INFO structure for the OXID without bindings.
|
||
|
||
pdsaStringBindings - Expanded string binding of the server.
|
||
|
||
Oxid - The OXID registered and returned.
|
||
|
||
Return Value:
|
||
|
||
OR_OK - success.
|
||
|
||
OR_NOMEM - Allocation of OXID failed.
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ServerAllocateOXID\n"));
|
||
|
||
ORSTATUS status = OR_OK;
|
||
|
||
COxid *pNewOxid;
|
||
|
||
// Save the string bindings back to the process
|
||
|
||
ASSERT(dsaValid(pdsaStringBindings));
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
hProcess->IsValid();
|
||
#endif
|
||
|
||
status = hProcess->ProcessBindings(pdsaStringBindings);
|
||
|
||
if (status != OR_OK)
|
||
{
|
||
return(status);
|
||
}
|
||
|
||
pNewOxid = new COxid(
|
||
hProcess,
|
||
*pOxidInfo,
|
||
fApartment
|
||
);
|
||
|
||
if (NULL == pNewOxid)
|
||
{
|
||
return(OR_NOMEM);
|
||
}
|
||
|
||
Oxid = pNewOxid->GetOXID();
|
||
|
||
// Add to process and lookup table.
|
||
|
||
status = hProcess->OwnOxid(pNewOxid);
|
||
|
||
VALIDATE((status, OR_NOMEM, 0));
|
||
|
||
if (OR_OK == status)
|
||
{
|
||
status = gpOxidTable->Add(pNewOxid);
|
||
if (status != OR_OK)
|
||
{
|
||
delete pNewOxid;
|
||
return status;
|
||
}
|
||
|
||
ComDebOut((DEB_OXID, "OXID successfully allocated: %08x\n", Oxid));
|
||
}
|
||
|
||
return(status);
|
||
}
|
||
|
||
|
||
error_status_t
|
||
ServerAllocateOID(
|
||
IN HPROCESS hProcess,
|
||
IN OXID Oxid,
|
||
OUT OID &Oid
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Registers an OID on behalf of an existing OXID.
|
||
|
||
Arguments:
|
||
|
||
hProcess - The context handle of the process containing the OXID and OIDs.
|
||
|
||
Oxid - The OXID associated with the OID (assumed local of course).
|
||
|
||
Oid - The OID to be allocated and returned.
|
||
|
||
Return Value:
|
||
|
||
OR_OK (0) - Success.
|
||
|
||
OR_NOMEM - OXID or one or more OIDs
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ServerAllocateOID, OXID = %08x\n", Oxid));
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
hProcess->IsValid();
|
||
#endif
|
||
|
||
COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID));
|
||
|
||
ORSTATUS status;
|
||
|
||
if (NULL == pOxid)
|
||
{
|
||
return(OR_BADOXID);
|
||
}
|
||
|
||
COid *pOid = new COid(pOxid);
|
||
|
||
if (NULL == pOid)
|
||
{
|
||
return OR_NOMEM;
|
||
}
|
||
|
||
status = pOxid->OwnOid(pOid);
|
||
|
||
if (status == OR_OK)
|
||
{
|
||
Oid = pOid->GetOID(); // out parameter
|
||
|
||
status = gpOidTable->Add(pOid);
|
||
if (status != OR_OK)
|
||
{
|
||
delete pOid;
|
||
return status;
|
||
}
|
||
|
||
// If the server doesn't want to keep the OID alive,
|
||
// this OID may rundown in six minutes unless
|
||
// someone references it in the meantime...
|
||
|
||
ComDebOut((DEB_OXID, "OID successfully allocated: %08x at offset = %x\n",
|
||
Oid,OR_OFFSET(pOid)));
|
||
|
||
pOxid->StartRundownThreadIfNecessary();
|
||
|
||
return OR_OK;
|
||
}
|
||
else
|
||
{
|
||
return OR_NOMEM;
|
||
}
|
||
}
|
||
|
||
error_status_t
|
||
ServerFreeOXID(
|
||
IN HPROCESS hProcess,
|
||
IN OXID Oxid,
|
||
IN ULONG cOids,
|
||
IN OID aOids[])
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Delete an OXID registered by the server, and all OIDs belonging to this OXID.
|
||
|
||
Arguments:
|
||
|
||
hProcess - The context handle of the process containing the OXID and OIDs.
|
||
|
||
Oxid - The OXID to be deleted (assumed local).
|
||
|
||
cOids - The number of OIDs to be deleted.
|
||
|
||
aOids - array of OIDs to be deleted.
|
||
|
||
Return Value:
|
||
|
||
OR_OK (0) - Success.
|
||
|
||
OR_BADOXID - OXID does not exist.
|
||
|
||
OR_NOACCESS - OXID does not belong to this process.
|
||
|
||
OR_BADOID - OID does not exist or does not belong to this OXID.
|
||
|
||
--*/
|
||
{
|
||
ComDebOut((DEB_OXID, "ServerFreeOXID: %08x MID = %x\n",
|
||
Oxid,gLocalMID));
|
||
|
||
CProtectSharedMemory protector; // locks through rest of lexical scope
|
||
|
||
#if DBG
|
||
hProcess->IsValid();
|
||
#endif
|
||
|
||
COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID));
|
||
|
||
if (NULL != pOxid)
|
||
{
|
||
#if DBG
|
||
OXID Oxid = pOxid->GetOXID(); // get this before pOxid potentially disappears
|
||
#endif
|
||
|
||
hProcess->DisownOxid(pOxid,TRUE); // this call is on the server's thread
|
||
// in the apartment case and in the server's
|
||
// process in both threading cases
|
||
|
||
ComDebOut((DEB_OXID, "OXID successfully removed: %08x\n",
|
||
Oxid));
|
||
|
||
return OR_OK;
|
||
}
|
||
else
|
||
{
|
||
return OR_BADOXID;
|
||
}
|
||
}
|
||
|