#include error_status_t Connect( OUT HPROCESS *pProcess, OUT ULONG *pdwTimeoutInSeconds, OUT DUALSTRINGARRAY **ppdsaOrBindings, OUT MID *pLocalMid, IN long cIdsToReserve, OUT ID *pidReservedBase, 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; status = ConnectDCOM( pProcess, pdwTimeoutInSeconds, pLocalMid, pfConnectFlags, pAuthnLevel, pImpLevel, pcServerSvc, aServerSvc, pcClientSvc, aClientSvc, pThreadID ); if (status == OR_OK) { status = AllocateReservedIds( cIdsToReserve, pidReservedBase ); } if (status == OR_OK) { *ppdsaOrBindings = (DUALSTRINGARRAY *) PrivMemAlloc( gpLocalDSA->wNumEntries * sizeof(WCHAR) + sizeof(DUALSTRINGARRAY) ); if (*ppdsaOrBindings) { dsaCopy(*ppdsaOrBindings, gpLocalDSA); } else { status = OR_NOMEM; } } return status; } error_status_t ClientResolveOXID( IN HPROCESS phProcess, IN OXID *poxidServer, IN DUALSTRINGARRAY *pssaServerObjectResolverBindings, IN long fApartment, OUT OXID_INFO *poxidInfo, OUT MID *pLocalMidOfRemote) { return GetOXID( phProcess, *poxidServer, pssaServerObjectResolverBindings, fApartment, 0, // wProtseqId not specified *poxidInfo, *pLocalMidOfRemote ); } error_status_t ServerAllocateOXIDAndOIDs( IN HPROCESS hProcess, OUT OXID *poxidServer, IN long fApartment, IN unsigned long cOids, OUT OID aOid[ ], OUT unsigned long *pcOidsAllocated, IN OXID_INFO *pOxidInfo, IN DUALSTRINGARRAY *pdsaStringBindings, IN DUALSTRINGARRAY *pdsaSecurityBindings) { ComDebOut((DEB_OXID, "Calling ServerAllocateOXIDAndOIDs\n")); DUALSTRINGARRAY *pdsaMergedBindings; ORSTATUS status = MergeBindings( pdsaStringBindings, pdsaSecurityBindings, &pdsaMergedBindings ); if (status != OR_OK) return status; status = ServerAllocateOXID( hProcess, fApartment, pOxidInfo, pdsaMergedBindings, *poxidServer ); if (status == OR_OK) { ComDebOut((DEB_OXID, "Calling ServerAllocateOIDs\n")); status = ServerAllocateOIDs( hProcess, poxidServer, cOids, aOid, pcOidsAllocated ); } else { ComDebOut((DEB_OXID, "Not Calling ServerAllocateOIDs, status = %d\n", status)); } return status; } error_status_t ServerAllocateOIDs( IN HPROCESS hProcess, IN OXID *poxidServer, IN unsigned long cOids, OUT OID aOid[ ], OUT unsigned long *pcOidsAllocated) { ComDebOut((DEB_ITRACE, "Entering ServerAllocateOIDs\n")); ORSTATUS status; *pcOidsAllocated = 0; for (ULONG i = 0; i < cOids; i++) { status = ServerAllocateOID( hProcess, *poxidServer, aOid[i] ); if (status != OR_OK) { *pcOidsAllocated = i; break; } else { (*pcOidsAllocated)++; } } return status; } error_status_t ServerFreeOXIDAndOIDs( IN HPROCESS hProcess, IN OXID oxidServer, IN unsigned long cOids, IN OID aOids[ ]) { return ServerFreeOXID( hProcess, oxidServer, cOids, aOids ); } VOID CALLBACK RundownTimerProc( HWND hwnd, // handle of window for timer messages UINT uMsg, // WM_TIMER message UINT idEvent, // timer identifier DWORD dwTime // current system time ) { return; if (idEvent != IDT_DCOM_RUNDOWN) return; // shouldn't happen -- this is only // used as callback for one timer // find the OXID for this thread COleTls tls; ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwTid == GetCurrentThreadId()); ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwPid == GetCurrentProcessId()); MOXID Moxid = ((OXIDEntry *)tls->pOXIDEntry)->moxid; OXID Oxid; MID Mid; OXIDFromMOXID(Moxid,&Oxid); MIDFromMOXID(Moxid,&Mid); CProtectSharedMemory protector; // locks through rest of lexical scope COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid)); ASSERT(pOxid); ComDebOut((DEB_OXID, "Attempting Rundown in apartment OXID = %08x PID = %d\n", Oxid,GetCurrentProcessId())); // find the RemUnk for this OXID -- we want only the IRundown interface IRundown *pRemUnk = tls->pRemoteUnk; // If there is no RemUnk, nothing is marshalled, so forget about rundown if (!pRemUnk) return; ComDebOut((DEB_OXID, "There is a RemUnk for apartment OXID = %08x PID = %d\n", Oxid,GetCurrentProcessId())); // go and check your OIDs here pOxid->RundownOidsIfNecessary(pRemUnk); } DWORD _stdcall RundownThread(void *self) { return 0; DWORD dwLoopCount = 0; COxid *pSelf = (COxid*) self; // store away "this" pointer while (TRUE) { ::Sleep(RUNDOWN_TIMER_INTERVAL); // BUGBUG: use Sleep() from CTime? dwLoopCount++; ComDebOut((DEB_OXID, "Attempting Rundown in PID = %d\n", GetCurrentProcessId())); CProtectSharedMemory protector; // locks through rest of lexical scope IRundown *pRemUnk = gpMTARemoteUnknown; // If there is no RemUnk, nothing is marshalled, so forget about rundown if (!pRemUnk) return OR_OK; ComDebOut((DEB_OXID, "There is a RemUnk for free OXID = %08x PID = %d\n", pSelf->GetOXID(),GetCurrentProcessId())); ASSERT(!IsBadWritePtr(pRemUnk,sizeof(CRemoteUnknown))); pSelf->RundownOidsIfNecessary(pRemUnk); } return OR_OK; } DWORD _stdcall PingThread(void) // BUGBUG: need another thread to watch over this one? { return 0; while (TRUE) { Sleep(BasePingInterval); { CProtectSharedMemory protector; // locks through rest of scope except where // temporarily released ORSTATUS status; // First do rundown detection -- this may cause deletes from ping sets COxidTableIterator OxidIter(gpPingProcess->_MyOxids); for (COxid *pOxid = OxidIter.Next(); pOxid != NULL; pOxid = OxidIter.Next()) { pOxid->RundownOidsIfNecessary(NULL); // No IRundown param needed } // Then do pinging CMidTableIterator MidIter(*gpMidTable); for (CMid *pMid = MidIter.Next(); pMid != NULL; pMid = MidIter.Next()) { if (pMid != gpLocalMid) { status = pMid->PingServer(); } } } } return OR_OK; } error_status_t ResolveClientOXID( handle_t hClient, void *hProcess, OXID *poxidServer, DUALSTRINGARRAY *pdsaServerBindings, LONG fApartment, USHORT wProtseqId, OXID_INFO *poxidInfo, MID *pDestinationMid ) { return GetOXID( (CProcess*)hProcess, *poxidServer, pdsaServerBindings, fApartment, wProtseqId, *poxidInfo, *pDestinationMid ); }