/*++ 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 // // 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; } }