//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: rot.cxx // // Contents: methods for implementation of ROT // // Functions: // // // History: 11-Nov-92 Ricksa Created // 25-Mar-94 brucema #8914 CRunningObjectTable::Register // uninited variable // 25-Mar-94 #10736 Fixed CRotMonikerEnum::Skip to // return S_OK if skipping remainder of // enumeration // 07-Apr-94 brucema CRunningObjectTable::Register var init // 24-Jun-94 BruceMa Validate ROT items when enum'ing // 11-Jul-94 BruceMa Marshal moniker enumeration normal // 28-Jul-94 BruceMa Memory sift fix // 09-Jan-95 BruceMa Single thread ROT creation and enum'ing // 30-Jan-95 Ricksa New ROT. // 15-May-95 BruceMa Convert DDE ROT requests to UNC-based // //-------------------------------------------------------------------------- #include #ifndef DCOM #include #endif #include #include #include #include "crot.hxx" // Semaphore used to protect ROT COleStaticMutexSem g_RotSem; // Running object table object extern CRunningObjectTable *pROT = NULL; #define MEM_PUB 0 // memory allocated via CoTaskMemAlloc #define MEM_PRIV 1 // memory allocated via CPrivMemAlloc extern INTERNAL CreateCommonDdeWindow(void); //+------------------------------------------------------------------------- // // Member: GetMonikerCompareBuffer, private // // Synopsis: Get a buffer appropriate for comparing // // Arguments: [pmk] - input moniker // [pmkeqbuf] - comparison buffer // [pfiletime] - time of last change (optional) // [pifdMoniker] - output marshaled moniker (optional) // // Returns: S_OK // E_OUTOFMEMORY // // Algorithm: First reduce the input moniker. Then get the last change // time if requested. Then we marshal the reduced moniker if // that was requested. Finally, we build the ROT moniker // comparison buffer. // // History: 27-Nov-93 Ricksa Created // // Notes: This is just a helper that is used to reduce code size. // //-------------------------------------------------------------------------- HRESULT GetMonikerCompareBuffer( IMoniker *pmk, CTmpMkEqBuf *ptmpmkeqbuf, FILETIME *pfiletime, InterfaceData **ppifdMoniker) { CairoleDebugOut((DEB_ROT, "%p _IN GetMonikerCompareBuffer " "( %p , %p, %p , %p )\n", NULL, pmk, ptmpmkeqbuf, pfiletime, ppifdMoniker)); HRESULT hr; BEGIN_BLOCK CSafeBindCtx sbctx; CSafeMoniker smkReduced; hr = CreateBindCtx(0, &sbctx); if (hr != NOERROR) { CairoleDebugOut((DEB_ERROR, "GetMonikerCompareBuffer CreateBindCtx failed %lX\n", hr)); EXIT_BLOCK; } // reduce the moniker hr = pmk->Reduce(sbctx, MKRREDUCE_ALL, NULL, &smkReduced); if (FAILED(hr)) { CairoleDebugOut((DEB_ERROR, "GetMonikerCompareBuffer IMoniker::Reduce failed %lX\n", hr)); EXIT_BLOCK; } if ((IMoniker *) smkReduced == NULL) { smkReduced.Set(pmk); } if (pfiletime != NULL) { // Try to get the time of last change. We ignore the error // because this was the original behavior of OLE2. smkReduced->GetTimeOfLastChange(sbctx, NULL, pfiletime); } // Marshal the moniker if so requested if (ppifdMoniker != NULL) { // Stream to put marshaled interface in CXmitRpcStream xrpc; hr = CoMarshalInterface(&xrpc, IID_IMoniker, smkReduced, MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG); if (hr != NOERROR) { CairoleDebugOut((DEB_ERROR, "GetMonikerCompareBuffer CoMarshalInterface failed %lX\n", hr)); EXIT_BLOCK; } xrpc.AssignSerializedInterface(ppifdMoniker); } hr = BuildRotData( sbctx, smkReduced, ptmpmkeqbuf->GetBuf(), ptmpmkeqbuf->GetSize(), ptmpmkeqbuf->GetSizeAddr()); END_BLOCK; CairoleDebugOut((DEB_ROT, "%p OUT GetMonikerCompareBuffer " "( %lX ) [ %p ] \n", NULL, hr, (ppifdMoniker != NULL) ? *ppifdMoniker : NULL)); return hr; } //+------------------------------------------------------------------------- // // Member: ReleaseSCMInterfaceData // // Synopsis: Release interface data returned by the SCM // // Arguments: [pifd] - interface data to release // // Algorithm: Create an RPC stream and then pass that stream to // CoReleaseMarshalData to release any AddRefs and then // free the memory that the interface data lives in. // // History: 27-Jan-95 Ricksa Created // // Notes: This is designed specifically for processing interface // data returned by the SCM on Revoke from the ROT. // //-------------------------------------------------------------------------- void ReleaseInterfaceData(InterfaceData *pifd, DWORD dwMemType) { CairoleDebugOut((DEB_ROT, "%p _IN ReleaseInterfaceData " "( %p )\n", NULL, pifd)); if (pifd != NULL) { // Make our interface into a stream CXmitRpcStream xrpc(pifd); // Tell RPC to release it -- error is for debugging purposes only // since if this fails there isn't much we can do about it. #if DBG == 1 HRESULT hr = #endif // DBG CoReleaseMarshalData(&xrpc); #if DBG == 1 if (hr != NOERROR) { CairoleDebugOut((DEB_ERROR, "ReleaseInterfaceData CoReleaseMarshalData failed: %lx\n", hr)); } #endif // DBG == 1 #ifdef DCOM if (dwMemType == MEM_PUB) CoTaskMemFree(pifd); else MIDL_user_free(pifd); #else MIDL_user_free(pifd); #endif // DCOM } CairoleDebugOut((DEB_ROT, "%p OUT ReleaseInterfaceData ", NULL)); } //+------------------------------------------------------------------------- // // Member: CROTItem::~CROTItem // // Synopsis: Release data connected with the entry // // Algorithm: Clean up a rot entry by sending a revoke to the SCM for // the entry and taking the marshaled interfaces that the // SCM returns and releasing the data associated with them. // // History: 20-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- inline CROTItem::~CROTItem(void) { CairoleDebugOut((DEB_ROT, "%p _IN CROTItem::~CROTItem\n", this)); // Make sure we are in the correct apt. Win4Assert((_hApt == GetCurrentApartmentId()) && "CROTItem::~CROTItem from wrong apartment"); // This object is going away so we mark it invalid immediately _wItemSig = 0; // Place to put returned marshaled interfaces InterfaceData *pifdObject = NULL; InterfaceData *pifdName = NULL; HRESULT hr = gResolver.IrotRevoke(&_scmregkey, TRUE, &pifdObject, &pifdName); if (SUCCEEDED(hr)) { if (!_fDontCallApp) { ReleaseInterfaceData(pifdObject, MEM_PRIV); ReleaseInterfaceData(pifdName, MEM_PRIV); } } #if DBG == 1 else { CairoleDebugOut((DEB_ROT, "Revoke FAILED: %lx\n", hr)); } #endif // DBG == 1 CairoleDebugOut((DEB_ROT, "%p OUT CROTItem::~CROTItem\n", this)); } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::Create // // Synopsis: Create & initialize running object table object // // Returns: TRUE - ROT created successfully // FALSE - an error occurred. // // Algorithm: Create a new running ROT and check whether the creation // was successful. // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- BOOL CRunningObjectTable::Create(void) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Create\n", NULL)); // Need to synchronize ROT creation in a multithreaded environment COleStaticLock lckSem(g_RotSem); // The ROT may have been created by now if (pROT == NULL) { // Create running object table pROT = new CRunningObjectTable(); #if DBG == 1 if (pROT == NULL) { CairoleDebugOut((DEB_ERROR,"Couldn't allocate ROT!\n")); } #endif // DBG == 1 // Initialize the array of registrations - FALSE means we couldn't // allocate the memory. if (pROT && !pROT->_afvRotList.SetSize(ROT_DEF_SIZE, ROT_DEF_SIZE)) { CairoleDebugOut((DEB_ERROR,"Couldn't allocate ROT reg array!\n")); delete pROT; pROT = NULL; } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Create" "( %lX )\n", NULL, (pROT != NULL))); return pROT != NULL; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::~CRunningObjectTable // // Synopsis: Free ROT object // // History: 11-Nov-93 Ricksa Created // // Notes: This only occurs at process exit. // //-------------------------------------------------------------------------- CRunningObjectTable::~CRunningObjectTable(void) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::~CRunningObjectTable\n", this)); // Get the size of the table int cMax = _afvRotList.GetSize(); // Are there any entries in the table? if (cMax != 0) { CROTItem **pprot = (CROTItem **) _afvRotList.GetAt(0); // Clear out all the registrations for (int i = 0; i < cMax; i++) { if (pprot[i] != NULL) { delete pprot[i]; } } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::~CRunningObjectTable\n", this)); } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::QueryInterface // // Synopsis: Implements QI for the ROT object // // Arguments: [riid] - requested id // [ppvObj] - where to put output object. // // Returns: S_OK - interface is suppored // E_NOINTERFACE - requested interface is not supported // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::QueryInterface " "( %p , %p) \n", this, &riid, ppvObj)); HRESULT hr = S_OK; *ppvObj = NULL; if ((IsEqualIID(riid, IID_IRunningObjectTable)) || (IsEqualIID(riid, IID_IUnknown))) { *ppvObj = this; } else { hr = E_NOINTERFACE; } CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::QueryInterface " "( %lX ) [ %p ]\n", this, hr, *ppvObj)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::AddRef // // Synopsis: Add to reference count // // Returns: Current reference count // // History: 11-Nov-93 Ricksa Created // // Notes: Reference count is ignored with respect to object deletion // since this is a system object and does not go away until // CoUninitialize is called. // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CRunningObjectTable::AddRef() { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::AddRef\n", this)); CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::AddRef\n", this)); // Since this ignored we just return a non-zero indication return 1; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::Release // // Synopsis: Dec ref count // // Returns: Current reference count // // History: 11-Nov-93 Ricksa Created // // Notes: Reference count is ignored with respect to object deletion // since this is a system object and does not go away until // CoUninitialize is called. // // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CRunningObjectTable::Release() { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Release\n", this)); CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Release\n", this)); // Since this ignored we just return a non-zero indication return 1; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::CleanupApartment // // Synopsis: Cleans up left-over entries from the ROT when an // apartment exits. // // Arguments: [hApt] - apartment to cleanup // // Algorithm: Walk through the list local registrations finding each entry // that has a matching apartment and remove those entries. We // delete them (for WOW making sure we don't call back to the // app). // // History: 24-Jun-94 Rickhi Created // 29-Jun-94 AlexT Don't make yielding calls while holding // the mutex // //-------------------------------------------------------------------------- HRESULT CRunningObjectTable::CleanupApartment(HAPT hApt) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::CleanupApartment" "( %lX )\n", this, hApt)); // Make sure all threads are locked out during lookup COleStaticLock lckSem(g_RotSem); // Find a spot in the array for the object CROTItem **pprotitm = (CROTItem **) _afvRotList.GetAt(0); for (int i = 0; i < _afvRotList.GetSize(); i++) { CROTItem *protitm = pprotitm[i]; if ((protitm != NULL) && (protitm->GetAptId() == hApt)) { // Clean up the entry pprotitm[i] = NULL; if (IsWOWThread()) { // 16-bit OLE didn't clean up stale entries; we remove // them from the ROT but we don't call back to the // application. Who knows what the application might do // if we called them - they already have a missing Revoke. protitm->DontCallApp(); } delete protitm; } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::CleanupApartment" "( %lX )\n", this, S_OK)); return S_OK; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::Register // // Synopsis: Register an item in the ROT // // Arguments: [grfFlags] - whether registration keeps object alive // [punkObject] - object to register // [pmkObjectName] - moniker for object to register // [pdwRegister] - id for revoke // // Algorithm: Validate parameters input. Then create the moniker to register, // the comparison buffer and the marshaled moniker to put in the // ROT. Then marshal the object to put in the ROT. Create a // new local ROT item and reserve a space for it in our local // table. Send registration to the SCM and exit. // // History: 11-Nov-93 Ricksa Created // 26-Jul-94 AndyH #20843 - restarting OLE in the shared WOW // 27-Jan-94 Ricksa New ROT // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::Register( DWORD grfFlags, LPUNKNOWN punkObject, LPMONIKER pmkObjectName, DWORD FAR* pdwRegister) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Register" "( %lX , %p , %p , %p )\n", this, grfFlags, punkObject, pmkObjectName, pdwRegister)); COleTls Tls; CROTItem *protitm = NULL; HRESULT hr = S_OK; // Place to keep marshaled moniker buffer InterfaceData *pifdMoniker = NULL; // Where to put pointer to marshaled object InterfaceData *pifdObject = NULL; // Where to put the new ROT registration - set so an invalid // value to tell error exit whether it needs to be cleaned up DWORD idwPutItem = 0xFFFFFFFF; BEGIN_BLOCK // If we want to service OLE1 clients, we need to create the // common Dde window now if it has not already been done. if( !(Tls->dwFlags & OLETLS_DISABLE_OLE1DDE) ) { CreateCommonDdeWindow(); } // Validate parameters if ((grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE | ROTFLAGS_ALLOWANYCLIENT)) || !IsValidInterface(punkObject) || !IsValidInterface(pmkObjectName) || IsBadWritePtr(pdwRegister, sizeof(*pdwRegister))) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable:Register Invalid Paramter\n")); hr = E_INVALIDARG; EXIT_BLOCK; } *pdwRegister = 0; // So we can fill in last change time at registration in the SCM FILETIME filetime; // Get the moniker comparison buffer CTmpMkEqBuf tmeb; hr = GetMonikerCompareBuffer(pmkObjectName, &tmeb, &filetime, &pifdMoniker); if (FAILED(hr)) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::Register get mk compare buf failed\n")); EXIT_BLOCK; } // // Get the marshaled interface // // Stream to put marshaled interface in CXmitRpcStream xrpc; // The way we marshal this object depends on the liveness // characteristics specified by the caller of the operation. hr = CoMarshalInterface(&xrpc, IID_IUnknown, punkObject, MSHCTX_NOSHAREDMEM, NULL, grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK); if (hr != NOERROR) { // Exit if there is an error CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::Register marshal object failed\n")); EXIT_BLOCK; } xrpc.AssignSerializedInterface(&pifdObject); // Create an entry for the local registration table CROTItem *protitm = new CROTItem(); if (protitm == NULL) { // Either the allocation failed, or the constructor failed CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::Register create ROT item failed\n")); hr = E_OUTOFMEMORY; EXIT_BLOCK; } // Temporary holder for registration ID DWORD dwRotRegId; // ROT Table entry as opposed to the entry we are creating // which is called protitm. CROTItem **pprotitm; // Put it in the table and initalize signiture. { COleStaticLock lckSem(g_RotSem); // We lock here so we don't accidently pass out duplicate // signiture. It is important to note that we need to lock // anyway to put the item in the array. _wSigRotItem++; protitm->SetSig(_wSigRotItem); // Find a spot in the array for the object pprotitm = (CROTItem **) _afvRotList.GetAt(0); for (idwPutItem = 0; (int) idwPutItem < _afvRotList.GetSize(); idwPutItem++) { if (pprotitm[idwPutItem] == NULL) { break; } } // Was the table full? if ((int) idwPutItem < _afvRotList.GetSize()) { // No -- use an empty slot. pprotitm[idwPutItem] = protitm; } // Grow the array to fit the next entry. else if (!_afvRotList.InsertAt(idwPutItem, &protitm)) { // Couldn't reallocate memory hr = E_OUTOFMEMORY; EXIT_BLOCK; } // Build the registration ID dwRotRegId = MakeRegID(_wSigRotItem, idwPutItem); } #ifndef _CHICAGO_ WCHAR wszImageName[MAX_PATH]; WCHAR * pwszExeName = 0; if ( grfFlags & ROTFLAGS_ALLOWANYCLIENT ) { if ( ! GetModuleFileName( NULL, wszImageName, MAX_PATH ) ) { hr = HRESULT_FROM_WIN32( GetLastError() ); EXIT_BLOCK; } pwszExeName = wszImageName + lstrlenW(wszImageName) - 1; while ( (pwszExeName != wszImageName) && (pwszExeName[-1] != L'\\') ) pwszExeName--; } #endif // Notify SCM of the registration // // Note that CoGetCurrentProcess is for supporting the DDE layer // which needs to find objects in the same apartment only. // hr = gResolver.IrotRegister( tmeb.GetMkEqBuf(), pifdObject, pifdMoniker, &filetime, CoGetCurrentProcess(), #ifndef _CHICAGO_ pwszExeName, #endif protitm->GetScmRegKey()); if (SUCCEEDED(hr)) { *pdwRegister = dwRotRegId; } END_BLOCK; if (SUCCEEDED(hr)) { // We pass the marshaled interface buffers off to the SCM so // it actually owns the ref counting (which is why it returns // copies of the buffer on Revoke. However, we still have // copies of the buffer memore here which we have to free or // leak memory. #ifdef DCOM CoTaskMemFree(pifdMoniker); CoTaskMemFree(pifdObject); #else MIDL_user_free(pifdMoniker); MIDL_user_free(pifdObject); #endif } else { // Clean up marshaled interfaces since the call has failed. ReleaseInterfaceData(pifdMoniker, MEM_PUB); ReleaseInterfaceData(pifdObject, MEM_PUB); // Error clean up. if (protitm != NULL) { if (idwPutItem != 0xFFFFFFFF) { // Registration failed on the SCM so clean up our local // registration. COleStaticLock lckSem(g_RotSem); // We have to use GetAt because the table could have grown CROTItem **pprotitm = (CROTItem **) _afvRotList.GetAt(idwPutItem); pprotitm[idwPutItem] = NULL; } // Free the item for the ROT. delete protitm; } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Register" "( %lX ) [ %lX ]\n", this, hr, *pdwRegister)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::Revoke // // Synopsis: Remove a previously registered item from the table. // // Arguments: [dwRegister] - registration id // // Returns: S_OK - item was revoked // E_INVALIDARG - dwRegister is invalid // // Algorithm: Convert local registration to SCM registration. Send revoke // to the SCM. Release data associated with SCM ROT entries. // // History: 11-Nov-93 Ricksa Created // 27-Nov-95 Ricksa New ROT // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::Revoke(DWORD dwRegister) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Revoke" "( %lX )\n", this, dwRegister)); // Default response to bad argument HRESULT hr = E_INVALIDARG; // Entry CROTItem *protitm; // Convert handle to pointer DWORD idwIndexToEntry; WORD wItemSig; GetSigAndIndex(dwRegister, &wItemSig, &idwIndexToEntry); BEGIN_BLOCK // Lock from other processes so another simultaneous revoke // will not cause something strange to happen. COleStaticLock lckSem(g_RotSem); protitm = GetRotItem(idwIndexToEntry); if (protitm != NULL) { // Found an entry so verify its signiture if (protitm->ValidSig(wItemSig)) { // Entry is valid so clear it out from the table CROTItem **pprotitm = (CROTItem **) _afvRotList.GetAt(idwIndexToEntry); *pprotitm = NULL; hr = S_OK; } } END_BLOCK; // We get out of the block and unlock our list and then RPC the // call to the SCM so we don't hold our lock for the duration of // an RPC. if (hr == S_OK) { // Release the ROT item's memory. delete protitm; } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Revoke" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::IsRunning // // Synopsis: See if object is running // // Arguments: [pmkObjectName] - name of item to search for // // Returns: S_OK - item is running // S_FALSE - item is not running // // Algorithm: Validate input parameters. Then build a moniker comparison // buffer. Then ask the ROT if there is a registration for // the input moniker. // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::IsRunning(LPMONIKER pmkObjectName) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IsRunning" "( %p )\n", this, pmkObjectName)); HRESULT hr = E_INVALIDARG; // Validate input parameters if (IsValidInterface(pmkObjectName)) { // Create a buffer for the comparison CTmpMkEqBuf tmpMkEqBuf; // Get comparison buffer if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL, NULL)) == NOERROR) { // Look into the hint table for the object if (IsInScm(tmpMkEqBuf.GetMkEqBuf())) { // Ask SCM for the object hr = gResolver.IrotIsRunning(tmpMkEqBuf.GetMkEqBuf()); } else { // If it isn't in the hint table, there is no reason // to RPC to the ROT. hr = S_FALSE; } } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IsRunning" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::GetObject // // Synopsis: Get an object from the ROT // // Arguments: [pmkObjectName] - name of object to search for // [ppunkObject] - where to put interface pointer. // // Returns: S_OK - found and returned object. // MK_E_UNAVAILABLE - not found // // Algorithm: Convert the local registration ID to the SCM registration // ID. Then send the request on to the SCM. // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::GetObject( LPMONIKER pmkObjectName, LPUNKNOWN *ppunkObject) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::GetObject " "( %p , %p )\n", this, pmkObjectName, ppunkObject)); // Validate arguments HRESULT hr = E_INVALIDARG; // Validate input parameters if (IsValidInterface(pmkObjectName) && !IsBadWritePtr(ppunkObject, sizeof(*ppunkObject))) { *ppunkObject = NULL; // Create a buffer for the comparison CTmpMkEqBuf tmpMkEqBuf; // Get comparison buffer if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL, NULL)) == NOERROR) { // Note: Process ID is 0 because we don't care about the // process any registration will do. hr = IGetObject(tmpMkEqBuf.GetMkEqBuf(), ppunkObject, 0); } else { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::GetObject couldn't get comp buf\n")); } } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::GetObject" "( %lX ) [ %p ]\n", this, hr, *ppunkObject)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::IGetObject // // Synopsis: Internal call to get an object from the ROT // // Arguments: [pmkObjectName] - name of object to search for // [ppunkObject] - where to put interface pointer. // [dwThreadID] - thread ID for the object // // Returns: S_OK - found and returned object. // MK_E_UNAVAILABLE - not found // // Algorithm: Build a moniker comparison buffer. Send request to the // SCM. Then unmarshal the result from the SCM. If the // unmarshal fails, then notify the SCM that the registration // is invalid. // // History: 30-Jan-95 Ricksa Created // // Notes: This exists because OLE 1.0 compatibility requires support // for determining whether an object is already in the ROT // for the given process. // // Because this is an internal call, there is no parameter // validation. // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::IGetObject( MNKEQBUF *pmkeqbuf, LPUNKNOWN FAR* ppunkObject, DWORD dwThreadID) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IGetObject" "( %p , %p , %lX )\n", this, pmkeqbuf, ppunkObject, dwThreadID)); // Validate arguments HRESULT hr = E_INVALIDARG; BEGIN_BLOCK // Loop because there can be multiple bad entries in the SCM // We loop 5 because we can theoretically loop forever so we // want to give up after we give a good long try that should // most likely work. for (int i = 0; i < 5; i++) { // Look into the hint table for the object if (!IsInScm(pmkeqbuf)) { // If it isn't in the hint table, there is no reason // to RPC to the ROT. hr = MK_E_UNAVAILABLE; break; } // Ask SCM for the object SCMREGKEY scmregkey; InterfaceData *pifdObject = NULL; hr = gResolver.IrotGetObject(dwThreadID, pmkeqbuf, &scmregkey, &pifdObject); if (FAILED(hr)) { // SCM couldn't find it so we are done. break; } if (ppunkObject == NULL) { // This is really an IsRunning from DDE so we can exit // now. hr = NOERROR; // free the buffer allocated MIDL_user_free(pifdObject); // Exit because we are done. break; } // Now we have to unmarshal the object to really get the // object. CXmitRpcStream xrpc(pifdObject); hr = CoUnmarshalInterface(&xrpc, IID_IUnknown, (void **) ppunkObject); // Whether there was an error or not we need to dump the // memory that RPC allocated on our behalf. MIDL_user_free(pifdObject); if (hr == NOERROR) { // We got our object so we are done. break; } // Tell ROT that we couldn't unmarshal this object so the entry // is bad. We ignore any errors from the SCM because there isn't // anything we could do about it anyway. // Dummy parameters for revoke - we don't care about these and // the SCM will not return them because we are a client and // can't call CoReleaseMarshalData anyway. InterfaceData *pifdDummy1 = NULL; InterfaceData *pifdDummy2 = NULL; gResolver.IrotRevoke(&scmregkey, FALSE, &pifdDummy1, &pifdDummy2); // We couldn't get the object so we try again to see if there is // another registration that we could use. } END_BLOCK; CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IGetObject" "( %lX ) [ %p ]\n", this, hr, ((ppunkObject == NULL) ? NULL : *ppunkObject))); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::NoteChangeTime // // Synopsis: Set the time of last change in the ROT // // Arguments: [dwRegister] - registration id of object // [pfiletime] - file time of change. // // Returns: S_OK - new time set // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::NoteChangeTime( DWORD dwRegister, FILETIME *pfiletime) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::NoteChangeTime" "( %lX , %p )\n", this, dwRegister, pfiletime)); // Default result to bad argument. HRESULT hr = E_INVALIDARG; BEGIN_BLOCK // Validate that parameters are valid if (IsBadReadPtr(pfiletime, sizeof(FILETIME))) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::NoteChangeTime invalid time param\n")); EXIT_BLOCK; } SCMREGKEY ScmRegKey; { // Lock from other threads so a revoke will not cause something // strange to happen. COleStaticLock lckSem(g_RotSem); // Convert handle to pointer DWORD idwIndexToEntry; WORD wItemSig; GetSigAndIndex(dwRegister, &wItemSig, &idwIndexToEntry); CROTItem *protitm = GetRotItem(idwIndexToEntry); if ((protitm == NULL) || !protitm->ValidSig(wItemSig)) { // Entry is valid so clear it out from the table CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::NoteChangeTime invalid reg key\n")); EXIT_BLOCK; } ScmRegKey = *(protitm->GetScmRegKey()); } // Outside the scope of the lock, call the SCM and returns // it's results. hr = gResolver.IrotNoteChangeTime(&ScmRegKey, pfiletime); END_BLOCK; CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::NoteChangeTime" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::GetTimeOfLastChange // // Synopsis: Get time of last change for a given object // // Arguments: [pmkObjectName] - name of object // [pfiletime] - where to put the time of change // // Returns: S_OK - got time of last change. // MK_E_UNAVAILABLE - moniker is not in the table // // History: 11-Nov-93 Ricksa Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::GetTimeOfLastChange( LPMONIKER pmkObjectName, FILETIME *pfiletime) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::GetTimeOfLastChange" "( %p , %p )\n", this, pmkObjectName, pfiletime)); HRESULT hr = E_INVALIDARG; BEGIN_BLOCK // Validate input parameters if (!IsValidInterface(pmkObjectName) || IsBadWritePtr(pfiletime, sizeof(pfiletime))) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::GetTimeOfLastChange invalid params\n")); EXIT_BLOCK; } // Create a buffer for the comparison CTmpMkEqBuf tmpMkEqBuf; // Get comparison buffer if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL, NULL)) != NOERROR) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::GetTimeOfLastChange couldn't get comp buf failed\n")); EXIT_BLOCK; } // Look into the hint table for the object if (!IsInScm(tmpMkEqBuf.GetMkEqBuf())) { // If it isn't in the hint table, there is no reason // to RPC to the ROT. hr = MK_E_UNAVAILABLE; EXIT_BLOCK; } // Ask SCM for the object SCMREGKEY scmregkey; InterfaceData *pifdObject = NULL; hr = gResolver.IrotGetTimeOfLastChange(tmpMkEqBuf.GetMkEqBuf(), pfiletime); END_BLOCK; CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::GetTimeOfLastChange" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::EnumRunning // // Synopsis: Get an enumerator for all objects in the ROT // // Arguments: [ppenumMoniker] - where to put enumerator interface // // Returns: S_OK - successfully built enumerator // E_OUTOFMEMORY - could not build enumerator // // Algorithm: Constructor an enumerator object. Then get the list of // all running monikers from the SCM. Finally, put that list // into the enumerator object. // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRunningObjectTable::EnumRunning(LPENUMMONIKER *ppenumMoniker) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::EnumRunning" "( %p )\n", this, ppenumMoniker)); HRESULT hr = E_INVALIDARG; CRotMonikerEnum *protenumMoniker = NULL; MkInterfaceList *pMkIFList = NULL; BEGIN_BLOCK if (IsBadWritePtr(ppenumMoniker, sizeof(*ppenumMoniker))) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::EnumRunning invalid params\n")); EXIT_BLOCK; } protenumMoniker = new CRotMonikerEnum(); if ((protenumMoniker == NULL) || !protenumMoniker->CreatedOk()) { CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::EnumRunning couldn't create enumerator\n")); hr = E_OUTOFMEMORY; EXIT_BLOCK; } hr = gResolver.IrotEnumRunning(&pMkIFList); if (hr != NOERROR) { // Return the error from the SCM CairoleDebugOut((DEB_ERROR, "CRunningObjectTable::EnumRunning call to SCM failed\n")); EXIT_BLOCK; } hr = protenumMoniker->LoadResultFromScm(pMkIFList); if (hr == NOERROR) { *ppenumMoniker = protenumMoniker; protenumMoniker = NULL; } END_BLOCK if (protenumMoniker != NULL) { // If our local pointer is not NULL then we just delete it and // ignore the reference count since this means an error occurred. delete protenumMoniker; } if (pMkIFList != NULL) { // Free all the entries for (DWORD i = 0; i < pMkIFList->dwSize; i++) { MIDL_user_free(pMkIFList->apIFDList[i]); } // Then free the structure itself MIDL_user_free(pMkIFList); } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::EnumRunning" "( %lX ) [ %p ]\n", this, hr, *ppenumMoniker)); return hr; } //+------------------------------------------------------------------------- // // Member: CRunningObjectTable::GetObjectByPath // // Synopsis: Locate object in ROT by path // // Arguments: [lpstrPath] - path to locate in the rot // [ppunkObject] - where to put the object if requested // [dwThreadID] - what thread the object s/b in // // Returns: S_OK - successfully built enumerator // E_OUTOFMEMORY - could not build enumerator // // Algorithm: Build a buffer full of objects from the local table then // consult the ROT directory. // // History: 30-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CRunningObjectTable::IGetObjectByPath( LPOLESTR lpstrPath, LPUNKNOWN *ppunkObject, DWORD dwThreadID) { CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IGetObjectByPath" "( %p , %p , %lX )\n", this, lpstrPath, ppunkObject, dwThreadID)); HRESULT hr = S_FALSE; // Where we put the moniker we use for the moniker CSafeMoniker smk; if (ppunkObject) { *ppunkObject = NULL; } // Create a buffer for the comparison CTmpMkEqBuf tmpMkEqBuf; hr = CreateFileMonikerComparisonBuffer(lpstrPath, tmpMkEqBuf.GetBuf(), tmpMkEqBuf.GetSize(), tmpMkEqBuf.GetSizeAddr()); if (SUCCEEDED(hr)) { hr = IGetObject(tmpMkEqBuf.GetMkEqBuf(), ppunkObject, dwThreadID); } CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IGetObjectByPath" "( %lX ) [ %p ]\n", this, hr, ((ppunkObject == NULL) ? NULL : *ppunkObject))); return hr; } //+------------------------------------------------------------------------- // // Member: GetRunningObjectTable // // Synopsis: Get a pointer to the ROT // // Arguments: [reserved] - reserved! // [pprot] - where to put interface pointer // // Returns: S_OK - got pointer // E_UNEXPECTED - table not initialized // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) { OLETRACEIN((API_GetRunningObjectTable, PARAMFMT("reserved= %x, pprot= %p"), pprot)); CairoleDebugOut((DEB_ROT, "%p _IN GetRunningObjectTable" "( %p )\n", NULL, pprot)); HRESULT hr = CO_E_NOTINITIALIZED; if ((pROT == NULL) && (g_cProcessInits > 0)) { // If we haven't created it, create it now. CRunningObjectTable::Create(); } *pprot = pROT; // will be NULL in error case if (pROT != NULL) { hr = S_OK; } CALLHOOKOBJECTCREATE(hr,CLSID_NULL,IID_IRunningObjectTable,(IUnknown **)pprot); CairoleDebugOut((DEB_ROT, "%p OUT GetRunningObjectTable" "( %lX ) [ %p ]\n", NULL, hr, *pprot)); OLETRACEOUT((API_GetRunningObjectTable, hr)); return hr; } //+------------------------------------------------------------------------- // // Function: CleanROTForApartment // // Synopsis: Get rid of running object table entries for the current APT. // // History: 24-Jun-94 Rickhi Created // //-------------------------------------------------------------------------- void CleanROTForApartment(void) { CairoleDebugOut((DEB_ROT, "%p _IN CleanROTForApartment" "\n", NULL)); if (pROT) { pROT->CleanupApartment(GetCurrentApartmentId()); } CairoleDebugOut((DEB_ROT, "%p OUT CleanROTForApartment" "\n", NULL)); } //+------------------------------------------------------------------------- // // Function: DestroyRunningObjectTable // // Synopsis: Get rid of running object table // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- void DestroyRunningObjectTable(void) { CairoleDebugOut((DEB_ROT, "%p _IN DestroyRunningObjectTable" "\n", NULL)); // It doesn't matter what the ref count is, when OLE goes, the ROT goes too. delete pROT; pROT = NULL; #ifndef DCOM // Our endpoint is history. Note that this just resides here as a // convenient place for this to happen (and for historical reasons // since it used to serve some practical purpose for being here). epiForProcess.MakeEndpointInvalid(); #endif CairoleDebugOut((DEB_ROT, "%p OUT DestroyRunningObjectTable" "\n", NULL)); } //+------------------------------------------------------------------------- // // Member: CMonikerPtrBuf::CMonikerPtrBuf // // Synopsis: Copy constructor for the buffer // // Arguments: [mkptrbuf] - buffer to copy // // History: 20-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- CMonikerPtrBuf::CMonikerPtrBuf(CMonikerPtrBuf& mkptrbuf) : CMonikerBag(mkptrbuf) { CairoleDebugOut((DEB_ROT, "%p _IN CMonikerPtrBuf::CMonikerPtrBuf" "( %p )\n", this, &mkptrbuf)); // Now AddRef the copied monikers so they stay around IMoniker **ppmk = GetArrayBase(); for (DWORD i = 0; i < GetMax(); i++) { ppmk[i]->AddRef(); } CairoleDebugOut((DEB_ROT, "%p OUT CMonikerPtrBuf::CMonikerPtrBuf" "( %p )\n", this)); } //+------------------------------------------------------------------------- // // Member: CMonikerPtrBuf::~CMonikerPtrBuf // // Synopsis: Free items // // History: 23-Dec-93 Ricksa Created // // Notes: This object assumes that it gets its monikers addref'd // so it is up to this object to free them. // //-------------------------------------------------------------------------- CMonikerPtrBuf::~CMonikerPtrBuf(void) { CairoleDebugOut((DEB_ROT, "%p _IN CMonikerPtrBuf::~CMonikerPtrBuf" "\n", this)); DWORD dwSize = GetMax(); if (dwSize > 0) { IMoniker **ppmk = GetArrayBase(); for (DWORD i = 0; i < dwSize; i++) { ppmk[i]->Release(); } } CairoleDebugOut((DEB_ROT, "%p OUT CMonikerPtrBuf::~CMonikerPtrBuf" "\n", this)); } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::CRotMonikerEnum // // Synopsis: Constructor for ROT moniker enumerator // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- CRotMonikerEnum::CRotMonikerEnum(void) : _cRefs(1), _dwOffset(0) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::CRotMonikerEnum" "\n", this)); // Header does the work CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::CRotMonikerEnum" "\n", this)); } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::CRotMonikerEnum // // Synopsis: Copy constructor for ROT moniker enumerator // // Arguments: [rotenumMoniker] - Enumerator to copy from // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- CRotMonikerEnum::CRotMonikerEnum(CRotMonikerEnum& rotenumMoniker) : _cRefs(1), _dwOffset(rotenumMoniker._dwOffset), _mkptrbuf(rotenumMoniker._mkptrbuf) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::CRotMonikerEnum" "( %p )\n", this, &rotenumMoniker)); // Header does the work CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::CRotMonikerEnum" "\n", this)); } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::QueryInterface // // Synopsis: QI for ROT moniker enumerator // // Arguments: [riid] - requested interface // [ppvObj] - where to put requested interface // // Returns: S_OK - returned interface // E_NOINTERFACE - requested interface is not supported // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRotMonikerEnum::QueryInterface(REFIID riid, void **ppvObj) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::QueryInterface" "( %p , %p )\n", this, &riid, ppvObj)); HRESULT hr = S_OK; BEGIN_BLOCK *ppvObj = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumMoniker)) { *ppvObj = (LPVOID)this; AddRef(); EXIT_BLOCK; } hr = E_NOINTERFACE; END_BLOCK CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::QueryInterface" "( %lX ) [ %p ]\n", this, hr, *ppvObj)); return hr; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::AddRef // // Synopsis: Add to ref count // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CRotMonikerEnum::AddRef(void) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::AddRef" "\n", this)); InterlockedIncrement((LONG *) &_cRefs); CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::AddRef" "( %lX )\n", this, _cRefs)); return _cRefs; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::Release // // Synopsis: Release reference count // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CRotMonikerEnum::Release(void) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Release" "\n", this)); LONG lRefs = InterlockedDecrement((LONG *) &_cRefs); if (0 == lRefs) { delete this; } CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Release" "( %lX )\n", this, lRefs)); return (ULONG) lRefs; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::Next // // Synopsis: Get next number of requested monikers from the buffer // // Arguments: [celt] - number of items requested // [reelt] - where to put table of monikers // [pceltFetched] - number of monikers retrieved // // Returns: S_OK - all requested monikers successfully retrieved // S_FALSE - entire buffer not filled. // // Algorithm: Loop through list returning monikers. // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRotMonikerEnum::Next( ULONG celt, LPMONIKER *reelt, ULONG *pceltFetched) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Next" "( %lX , %p , %p )\n", this, celt, reelt, pceltFetched)); // Validate pceltFetched if ((celt != 1) && (pceltFetched != NULL)) { *pceltFetched = 0; } // Loop loading monikers until request is satisfied or we run out for (ULONG i = 0; i < celt; i++) { IMoniker *pmk = _mkptrbuf.GetItem(_dwOffset++); if (pmk == NULL) { break; } reelt[i] = pmk; } if (pceltFetched != NULL) { *pceltFetched = i; } HRESULT hr = (i == celt) ? S_OK : S_FALSE; CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Next" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::Skip // // Synopsis: Skip designated number of monikers // // Arguments: [celt] - number to skip // // Returns: S_OK - skipped requested number // S_FALSE - # skipped greater than remaining // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRotMonikerEnum::Skip(ULONG celt) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Skip" "( %lX )\n", this, celt)); // Error return -- assume count to skip is larger than number of items HRESULT hr = S_FALSE; if (_dwOffset + celt <= _mkptrbuf.GetMax()) { _dwOffset += celt; hr = S_OK; } else { _dwOffset = _mkptrbuf.GetMax(); } CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Skip" "( %lX )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::Reset // // Synopsis: Reset the enumerator // // Returns: S_OK // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRotMonikerEnum::Reset(void) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Reset" "\n", this)); _dwOffset = 0; CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Reset" "\n", this)); return S_OK; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::Clone // // Synopsis: Make a copy of the current enumerator // // Arguments: [ppenumMoniker] - where to put copy // // Returns: S_OK - moniker successfully cloned // E_OUTOFMEMORY - not enough memory to clone // // History: 11-Nov-93 Ricksa Created // //-------------------------------------------------------------------------- STDMETHODIMP CRotMonikerEnum::Clone(LPENUMMONIKER FAR* ppenumMoniker) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Clone" "( %p )\n", this, ppenumMoniker)); // Error return HRESULT hr = S_OK; // Use copy constructor to create duplicate enumerator CRotMonikerEnum *pcrotenumMoniker = new CRotMonikerEnum(*this); if ((pcrotenumMoniker == NULL) || !pcrotenumMoniker->CreatedOk()) { delete pcrotenumMoniker; hr = E_OUTOFMEMORY; } else { *ppenumMoniker = (LPENUMMONIKER) pcrotenumMoniker; } CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Clone" "( %lX ) [ %p ]\n", this, hr, *ppenumMoniker)); return hr; } //+------------------------------------------------------------------------- // // Member: CRotMonikerEnum::LoadResultFromScm // // Synopsis: Add a list of monikers to enumerator from an object server // // Arguments: [pMkIFList] - list to use for input // // Returns: S_OK - moniker added // E_OUTOFMEMORY - could not add any more to buffer // // History: 11-Nov-93 Ricksa Created // 27-Jan-95 Ricksa New ROT // // Note: // //-------------------------------------------------------------------------- HRESULT CRotMonikerEnum::LoadResultFromScm(MkInterfaceList *pMkIFList) { CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::LoadResultFromScm" "( %p )\n", this, pMkIFList)); HRESULT hr = S_OK; for (DWORD i = 0; i < pMkIFList->dwSize; i++) { // Where to put the unmarshaled moniker IMoniker *pmk; // Unmarshal the interface from the buffer CXmitRpcStream xrpc(pMkIFList->apIFDList[i]); hr = CoUnmarshalInterface(&xrpc, IID_IMoniker, (void **) &pmk); if (FAILED(hr)) { // Really two important possibilities for failure: (1) Out of // memory or (2) Somekind of communication failure during the // unmarshal. Out of memory means that we are pretty well dead // so we will return that error and ignore the others since // if the moniker is remotely served, it can actually have // gone away before we got around to unmarshaling it. if (hr == E_OUTOFMEMORY) { break; } continue; } // Put the moniker in the array _mkptrbuf.Add(pmk); } CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::LoadResultFromScm" "( %lX )\n", this, hr)); return hr; } //+--------------------------------------------------------------------------- // // Function: GetLocalRunningObjectForDde // // Synopsis: Searches for and optionally returns an object by path for // the DDE layer. // // Effects: Attempts to find an entry in the local ROT that matches // the provided path. If there is a hit in the table, and // ppunkObject is not NULL, then it also returns a pointer // to the object. // // Arguments: [lpstrPath] -- Path to search for // [ppunkObject] -- Output for the object pointer // // Returns: S_OK - Found object in local ROT // S_FALSE - Didn't find object in local ROT // OTHER - Something else happened. // // History: 6-29-94 kevinro Created // // Notes: // //---------------------------------------------------------------------------- HRESULT GetLocalRunningObjectForDde( LPOLESTR lpstrPath, LPUNKNOWN *ppunkObject) { CairoleDebugOut((DEB_ROT, "%p _IN GetLocalRunningObjectForDde" "( %p , %p )\n", NULL, lpstrPath, ppunkObject)); HRESULT hr = S_FALSE; // POSTPPC - We're getting close to RTM for NT/PPC, so we'll make this fix // for Chicago only for now #ifdef _CHICAGO_ // We create a file moniker here to ensure that the name we test against // the ROT is in UNC form LPMONIKER pMnk; LPBINDCTX pBc; LPWSTR pwszDisplayName; hr = CreateFileMoniker(lpstrPath, &pMnk); if (FAILED(hr)) { return hr; } hr = CreateBindCtx(NULL, &pBc); if (FAILED(hr)) { pMnk->Release(); return hr; } hr = pMnk->GetDisplayName(pBc, NULL, &pwszDisplayName); if (FAILED(hr)) { pMnk->Release(); pBc->Release(); return hr; } // If there currently isn't a local ROT, then the object surely isn't // registered. if (pROT != NULL) { hr = pROT->IGetObjectByPath(pwszDisplayName, ppunkObject, CoGetCurrentProcess()); } else { hr = S_FALSE; } // Cleanup pMnk->Release(); pBc->Release(); CoTaskMemFree(pwszDisplayName); #else // // If there currently isn't a local ROT, then the object surely isn't // registered. // if (pROT != NULL) { hr = pROT->IGetObjectByPath(lpstrPath, ppunkObject, CoGetCurrentProcess()); } #endif // _CHICAGO_ CairoleDebugOut((DEB_ROT, "%p OUT GetLocalRunningObjectForDde" "( %lX ) [ %p ]\n", NULL, hr, ((ppunkObject == NULL) ? NULL : *ppunkObject))); return(hr); } //+--------------------------------------------------------------------------- // // Function: GetObjectFromRotByPath // // Synopsis: Searches for and optionally returns an object by path for // pbkect binding. // // Effects: Attempts to find an entry in the ROT that matches // the provided path. If there is a hit in the table, and // ppunkObject is not NULL, then it also returns a pointer // to the object. // // Arguments: [lpstrPath] -- Path to search for // [ppunkObject] -- Output for the object pointer // // Returns: S_OK - Found object in local ROT // S_FALSE - Didn't find object in local ROT // OTHER - Something else happened. // // History: 30-Jan-95 Ricksa Created // // Notes: // //---------------------------------------------------------------------------- HRESULT GetObjectFromRotByPath( LPOLESTR lpstrPath, LPUNKNOWN *ppunkObject) { CairoleDebugOut((DEB_ROT, "%p _IN GetObjectFromRotByPath" "( %p , %p )\n", NULL, lpstrPath, ppunkObject)); HRESULT hr = S_FALSE; // Is the rot in existence yet? if (pROT == NULL) { // No - create the ROT. Remember that pROT is real pointer to the // running object table. GetRunningObjectTable returns this and // initializes it if it is NULL. This is why we don't pay very much // attention to prot. IRunningObjectTable *prot; GetRunningObjectTable(0, &prot); // Note that we don't have to release the prot because the ROT // doesn't care about its reference count. Its lifetime is independent // of the reference count. } if (pROT != NULL) { hr = pROT->IGetObjectByPath(lpstrPath, ppunkObject, 0); } CairoleDebugOut((DEB_ROT, "%p OUT GetObjectFromRotByPath" "( %lX ) [ %p ]\n", NULL, hr, *ppunkObject)); return(hr); }