//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: scmrot.hxx // // Contents: Implementation of classes for the ROT in the SCM // // Functions: RoundTo8 - round size to 8 byte boundary // CalcIfdSize - calculate size needed for marhaled interface // SizeMnkEqBufForRotEntry - calculate size for moniker eq buffer // AllocateAndCopy - create copy of a marshaled interface // GetEntryFromScmReg - convert SCMREGKEY to ROT entry ptr // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- #include "act.hxx" #if 0 // #ifdef _CHICAGO_ CStaticPortableMutex CScmRot::_mxs; // mutex semaphore #endif //+------------------------------------------------------------------------- // // Function: RoundTo8 // // Synopsis: Round size to next 8 byte boundary // // Arguments: [sizeToRound] - Size to round // // Returns: Input rounded to the next 8 byte boundary // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- inline size_t RoundTo8(size_t sizeToRound) { return (sizeToRound + 7) & ~7; } //+------------------------------------------------------------------------- // // Function: CalcIfdSize // // Synopsis: Calculate size required by a marshaled interface // // Arguments: [pifd] - interface whose size to calculate // // Returns: size required for interface // // Algorithm: Get size from the interface and round to next 8 bytes so // data packed following this buffer will be nicely aligned. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- size_t CalcIfdSize(InterfaceData *pifd) { CairoleDebugOut((DEB_ROT, "%p _IN CalcIfdSize ( %p )\n", NULL, pifd)); size_t sizeRet = RoundTo8(IFD_SIZE(pifd)); CairoleDebugOut((DEB_ROT, "%p OUT CalcIfdSize ( %lx )\n", NULL, sizeRet)); return sizeRet; } //+------------------------------------------------------------------------- // // Function: SizeMnkEqBufForRotEntry // // Synopsis: Calculate 8 byte aligned size for moniker equality buffer // // Arguments: [pmnkeqbuf] - Moniker equality buffer // // Returns: 8 byte aligned size of moniker buffer. // // Algorithm: Calculate size for the moniker equality buffer from input // buffer and then round to next 8 byte boundary // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- size_t SizeMnkEqBufForRotEntry(MNKEQBUF *pmnkeqbuf) { CairoleDebugOut((DEB_ROT, "%p _IN SizeMnkEqBufForRotEntry ( %p )\n", NULL, pmnkeqbuf)); size_t sizeRet = RoundTo8((sizeof(MNKEQBUF) - 1) + pmnkeqbuf->cdwSize); CairoleDebugOut((DEB_ROT, "%p OUT SizeMnkEqBufForRotEntry ( %lx )\n", NULL, sizeRet)); return sizeRet; } //+------------------------------------------------------------------------- // // Function: AllocateAndCopy // // Synopsis: Make a copy of the input marshaled interface // // Arguments: [pifdIn] - input marshaled interface. // // Returns: Copy of input marshaled interface. // // Algorithm: Calculate size required for marshaled interface. Allocate // memory for the interface and then copy input interface into // the new buffer. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- InterfaceData *AllocateAndCopy(InterfaceData *pifdIn) { CairoleDebugOut((DEB_ROT, "%p _IN AllocateAndCopy ( %p )\n", NULL, pifdIn)); DWORD dwSizeObj = CalcIfdSize(pifdIn); InterfaceData *pifd = (InterfaceData *) MIDL_user_allocate(dwSizeObj); if (pifd) { // Copy all the data. Remember that pifdIn was allocated rounded // to an 8 byte boundary so we will not run off the end of the // memory buffer memcpy(pifd, pifdIn, dwSizeObj); } CairoleDebugOut((DEB_ROT, "%p OUT AllocateAndCopy ( %lx )\n", NULL, pifd)); return pifd; } //+------------------------------------------------------------------------- // // Function: GetEntryFromScmReg // // Synopsis: Convert SCMREGKEY into a pointer to a ROT entry if possible // // Arguments: [psrk] - Pointer to a SCMREGKEY // // Returns: NULL - psrk not valid // ROT entry for the given input key // // Algorithm: Take the pointer portion of the key and make sure that // it points to enough memory so that we can validate the // signiture in the object. Then validate the signiture in // the object and return a pointer to the object. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmRotEntry *GetEntryFromScmReg(SCMREGKEY *psrk) { CairoleDebugOut((DEB_ROT, "%p _IN GetEntryFromScmReg ( %p )\n", NULL, psrk)); CScmRotEntry *psreRet = NULL; CScmRotEntry *psre = (CScmRotEntry *) psrk->dwEntryLoc; // Make sure pointer is pointer to valid memory - it s/b read write // memory since we allocated it and updated it. if (!IsBadReadPtr(psre, sizeof(*psre)) && !IsBadWritePtr(psre, sizeof(*psre))) { // Make sure signitures are valid if (psre->IsValid(psrk->dwScmId)) { psreRet = psre; } } CairoleDebugOut((DEB_ROT, "%p OUT GetEntryFromScmReg ( %lx )\n", NULL, psreRet)); return psreRet; } //+------------------------------------------------------------------------- // // Member: CScmRotEntry::CScmRotEntry // // Synopsis: Create a ROT entry for a registration // // Arguments: [dwScmRotId] - signiture for item // [pmkeqbuf] - moniker equality buffer to use // [pfiletime] - file time to use // [dwProcessID] - process id to use // [pifdObject] - marshaled interface for the object // [pifdObjectName] - marshaled moniker for the object // // Algorithm: Initialize data and calcualte offsets into the object for // the variable length data. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmRotEntry::CScmRotEntry( DWORD dwScmRotId, MNKEQBUF *pmkeqbuf, FILETIME *pfiletime, DWORD dwProcessID, #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, InterfaceData *pifdObject, InterfaceData *pifdObjectName) : _dwSig(SCMROT_SIG), _dwScmRotId(dwScmRotId), _dwProcessID(dwProcessID), _filetimeLastChange(*pfiletime), _pifdObject((InterfaceData *) &_ab[0]) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::CScmRotEntry " "( %lx , %p , %p , %lx , %p , %p )\n", this, pmkeqbuf, pfiletime, dwProcessID, pifdObject, pifdObjectName)); #ifndef _CHICAGO_ _pToken = pToken; if ( _pToken ) _pToken->AddRef(); #endif // Copy data for object to preallocated area _pifdObject->ulCntData = pifdObject->ulCntData; memcpy(&_pifdObject->abData[0], &pifdObject->abData[0], _pifdObject->ulCntData); // Calculate the location of the equality buffer in the allocated data DWORD dwOffsetMnkEqBuf = CalcIfdSize(_pifdObject); _pmkeqbufKey = (MNKEQBUF *) &_ab[dwOffsetMnkEqBuf]; // Copy data for moniker equality buffer into preallocated area _pmkeqbufKey->cdwSize = pmkeqbuf->cdwSize; memcpy(&_pmkeqbufKey->abEqData[0], &pmkeqbuf->abEqData[0], _pmkeqbufKey->cdwSize); // Calculate the location of the moniker name buffer _pifdObjectName = (InterfaceData *) &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey)]; // Copy in the data for the moniker name _pifdObjectName->ulCntData = pifdObjectName->ulCntData; memcpy(&_pifdObjectName->abData[0], &pifdObjectName->abData[0], _pifdObjectName->ulCntData); if ( pwszWinstaDesktop ) { _pwszWinstaDesktop = (WCHAR *) &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey) + CalcIfdSize(_pifdObjectName)]; lstrcpyW( _pwszWinstaDesktop, pwszWinstaDesktop ); } else { _pwszWinstaDesktop = NULL; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::CScmRotEntry \n", this)); } //+------------------------------------------------------------------------- // // Member: CScmRotEntry::IsEqual // // Synopsis: Determine if input key is equal to the ROT entry's key // // Arguments: [pKey] - Key to use for the test // [cbKey] - Count of bytes in key // // Returns: TRUE - input key equals this object's key // FALSE - keys are not equal // // Algorithm: If the two sizes are equal then compare the actual data // buffers and return the result of that compare. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- BOOL CScmRotEntry::IsEqual(LPVOID pKey, UINT cbKey) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::IsEqual " "( %p , %lx )\n", this, pKey, cbKey)); BOOL fRet = FALSE; if (cbKey == _pmkeqbufKey->cdwSize) { fRet = memcmp(pKey, &_pmkeqbufKey->abEqData[0], cbKey) == 0; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::IsEqual ( %lx )\n", this, fRet)); return fRet; } //+------------------------------------------------------------------------- // // Member: CScmRot::Register // // Synopsis: Add entry to the ROT // // Arguments: [pmkeqbuf] - moniker equality buffer to use // [pfiletime] - file time to use // [dwProcessID] - process id to use // [pifdObject] - marshaled interface for the object // [pifdObjectName] - marshaled moniker for the object // // Returns: NOERROR - successfully registered // E_OUTOFMEMORY // // Algorithm: Lock the ROT from all other threads. The create a new // entry and determine if there is an eqivalent entry in // the ROT. Calculate the hash value and then put the // entry into our hash table. Finally, build a registration // key to return to the caller. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::Register( #if 1 // #ifndef _CHICAGO_ CProcess *pProcess, #endif WCHAR *pwszWinstaDesktop, MNKEQBUF *pmnkeqbuf, InterfaceData *pifdObject, InterfaceData *pifdObjectName, FILETIME *pfiletime, DWORD dwProcessID, WCHAR *pwszServerExe, SCMREGKEY *psrkRegister) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Register " "( %p , %p , %p , %p , %lx , %p )\n", this, pmnkeqbuf, pifdObject, pifdObjectName, pfiletime, dwProcessID, psrkRegister)); // Assume that there is a memory problem HRESULT hr = E_OUTOFMEMORY; CToken * pToken; pToken = pProcess->GetToken(); if ( pwszServerExe ) { HKEY hKey; LONG RegStatus; WCHAR wszAppid[40]; DWORD Size; RegStatus = ERROR_SUCCESS; // The pwszServerExe string may contain an AppId string or // a module name. If it looks like a GUID string, we can bypass // the AppId lookup. Otherwise, we go to the Registry to if ( pwszServerExe[0] == L'{' ) { // Use the given string as the AppId lstrcpyn(wszAppid, pwszServerExe, sizeof(wszAppid)/sizeof(WCHAR)); } else { // Try to map the Exe name to an AppId if ( ! ghAppidMachine ) RegStatus = OpenClassesRootKeys(); if ( ERROR_SUCCESS == RegStatus ) { RegStatus = RegOpenKeyEx( ghAppidMachine, pwszServerExe, NULL, KEY_READ, &hKey ); } if ( ERROR_SUCCESS == RegStatus ) { Size = sizeof(wszAppid); RegStatus = RegQueryValueEx( hKey, L"AppId", NULL, NULL, (BYTE *)wszAppid, &Size ); RegCloseKey( hKey ); } if ( RegStatus != ERROR_SUCCESS ) return CO_E_WRONG_SERVER_IDENTITY; } CAppidData Appid( wszAppid, pToken ); BOOL Access; Access = FALSE; // Load appid info from the matching side of the registry DWORD dwAppidFlags = 0; #if defined(_WIN64) dwAppidFlags = pProcess->Is64Bit() ? CAT_REG64_ONLY : CAT_REG32_ONLY; #endif hr = Appid.Load(dwAppidFlags); if ( S_OK == hr ) Access = Appid.CertifyServer( pProcess ); if ( ! Access ) return CO_E_WRONG_SERVER_IDENTITY; // // NULL these to indicate that any client can connect to this // registration. // pwszWinstaDesktop = NULL; pToken = NULL; } // Lock for the duration of the call CPortableLock lck(_mxs); // Bump the id _dwIdCntr++; // Build a record to put into the table CScmRotEntry *psreNew = new( pwszWinstaDesktop ? (lstrlenW(pwszWinstaDesktop)+1)*sizeof(WCHAR) : 0, CalcIfdSize(pifdObject), SizeMnkEqBufForRotEntry(pmnkeqbuf), CalcIfdSize(pifdObjectName)) CScmRotEntry(_dwIdCntr, pmnkeqbuf, pfiletime, dwProcessID, #ifndef _CHICAGO_ pToken, #else NULL, #endif pwszWinstaDesktop, pifdObject, pifdObjectName); if (psreNew != NULL) { DWORD dwHash; CScmRotEntry * psreRunning; #ifndef _CHICAGO_ psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf ); #else psreRunning = GetRotEntry( NULL, pwszWinstaDesktop, pmnkeqbuf ); #endif dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0); // Put record into the hash table _sht.SetAt(dwHash, psreNew); #if 1 // #ifndef _CHICAGO_ // Update the hint table _rht.SetIndicator(dwHash); #endif // !_CHICAGO_ // Build return value psreNew->SetScmRegKey(psrkRegister); // Map return result based on prior existence of the object. hr = (psreRunning == NULL) ? NOERROR : MK_S_MONIKERALREADYREGISTERED; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Register " " ( %lx )\n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::Revoke // // Synopsis: Remove entry from the ROT // // Arguments: [psrkRegister] - registration to revoke // [fServer] - whether this is the object server // [ppifdObject] - output marshaled interface (optional) // [ppifdName] - output marshaled moniker (optional) // // Returns: NOERROR - successfully removed. // E_INVALIDARG // // Algorithm: Convert SCMREGKEY to anentry in the ROT. Remove the // entry from the hash table. If this is the object server // for the entry, then return the marshaled interfaces // so the object server can release them. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::Revoke( SCMREGKEY *psrkRegister, BOOL fServer, InterfaceData **ppifdObject, InterfaceData **ppifdName) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Revoke " "( %p , %lx , %p , %p )\n", this, fServer, ppifdObject, ppifdName)); HRESULT hr = E_INVALIDARG; // Lock for the duration of the call CPortableLock lck(_mxs); // Verify registration key CScmRotEntry *psreToRemove = GetEntryFromScmReg(psrkRegister); if (psreToRemove != NULL) { // Get the has value DWORD dwHash = ScmRotHash(psreToRemove->Key(), psreToRemove->cKey(), 0); // Remove object from the list _sht.RemoveEntry(dwHash, psreToRemove); // Is this a server doing a revoke? if (fServer) { // Error handling here - suppose these allocations fail, what // can we do? The bottom line is nothing. This will cause a // memory leak in the server because they can't release the // marshaled data. However, this is assumed to be a rare // occurance and will really only cause the moniker to live // longer than it ought to which should not be too serious. *ppifdObject = AllocateAndCopy(psreToRemove->GetObject()); *ppifdName = AllocateAndCopy(psreToRemove->GetMoniker()); } // Free the entry delete psreToRemove; #if 1 // #ifndef _CHICAGO_ // See if bucket is empty if (_sht.IsBucketEmpty(dwHash)) { // Update the hint table. _rht.ClearIndicator(dwHash); } #endif // !_CHICAGO_ hr = S_OK; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Revoke " " ( %lx ) [ %p, %p ] \n", this, hr, (ppifdObject != NULL) ? *ppifdObject : NULL, (ppifdName != NULL) ? *ppifdName : NULL)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::IsRunning // // Synopsis: Determine if there is a registered entry for an item // // Arguments: [pmnkeqbuf] - Moniker equality buffer to search for // // Returns: NOERROR - moniker is registered as running // S_FALSE - moniker is not running. // // Algorithm: Get the entry for the moniker equality buffer if there is // one. If there is one, then return NOERROR otherwise return // S_FALSE. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::IsRunning( #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, MNKEQBUF *pmnkeqbuf) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::IsRunning " "( %p )\n", this, pmnkeqbuf)); // Lock for the duration of the call CPortableLock lck(_mxs); #if 1 // #ifndef _CHICAGO_ CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf ); #else CScmRotEntry *psreRunning = GetRotEntry(pwszWinstaDesktop, pmnkeqbuf); #endif HRESULT hr = (psreRunning != NULL) ? S_OK : S_FALSE; CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::IsRunning " " ( %lx ) \n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::GetObject // // Synopsis: Get running object for input // // Arguments: [dwProcessID] - process id of object (optional) // [pmnkeqbuf] - moniker equality buffer // [psrkRegister] - output registration id. // [ppifdObject] - marshaled interface for registration // // Returns: NOERROR - got object // MK_E_UNAVAILABLE - registration could not be found // // Algorithm: If not process ID is input, then search for the first // matching entry that we can find. Otherwise, search the // hash for the entry with both the same key and the same // process id. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::GetObject( #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, DWORD dwProcessID, MNKEQBUF *pmnkeqbuf, SCMREGKEY *psrkRegister, InterfaceData **ppifdObject) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetObject " "( %lx , %p , %p , %p )\n", this, dwProcessID, pmnkeqbuf, psrkRegister, ppifdObject)); HRESULT hr = MK_E_UNAVAILABLE; // Lock for the duration of the call CPortableLock lck(_mxs); CScmRotEntry *psreRunning; if (dwProcessID == 0) { psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf ); } else { // Special search based on process ID - get the head of the list // for the bucket psreRunning = (CScmRotEntry *) _sht.GetBucketList( ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0)); // Search list for a matching entry while (psreRunning != NULL) { if ((psreRunning->GetProcessID() == dwProcessID) && psreRunning->IsEqual(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize)) { // We found a match so we are done. break; } // Try the next item in the bucket. psreRunning = (CScmRotEntry *) psreRunning->GetNext(); } } if (psreRunning != NULL) { hr = E_OUTOFMEMORY; *ppifdObject = AllocateAndCopy(psreRunning->GetObject()); if (*ppifdObject != NULL) { hr = NOERROR; } // Build return registration key psreRunning->SetScmRegKey(psrkRegister); } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetObject " " ( %lx ) [ %p ] \n", this, hr, *ppifdObject)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::NoteChangeTime // // Synopsis: Set the time of last change for a ROT entry // // Arguments: [psrkRegister] - ID of entry to change // [pfiletime] - new time for the entry. // // Returns: NOERROR - time set // E_INVALIDARG - ROT entry could not be found // // Algorithm: Convert SCMREGKEY into a pointer to a ROT entry and then // update the time of that entry. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::NoteChangeTime( SCMREGKEY *psrkRegister, FILETIME *pfiletime) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::NoteChangeTime " "( %p , %p )\n", this, psrkRegister, pfiletime)); HRESULT hr = E_INVALIDARG; // Lock for the duration of the call CPortableLock lck(_mxs); CScmRotEntry *psre = GetEntryFromScmReg(psrkRegister); if (psre != NULL) { psre->SetTime(pfiletime); hr = S_OK; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::NoteChangeTime " " ( %lx ) \n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::GetTimeOfLastChange // // Synopsis: Get time of last change for a moniker in the ROT // // Arguments: [pmnkeqbuf] - Moniker equality buffer // [pfiletime] - Where to put the time // // Returns: NOERROR - got the time // MK_E_UNAVAILABLE - couldn't find an entry/ // // Algorithm: Search the hash for an entry with the same moniker. If // found, then copy out the time. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::GetTimeOfLastChange( #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, MNKEQBUF *pmnkeqbuf, FILETIME *pfiletime) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetTimeOfLastChange " "( %p , %p )\n", this, pmnkeqbuf, pfiletime)); HRESULT hr = MK_E_UNAVAILABLE; // Lock for the duration of the call CPortableLock lck(_mxs); #if 1 // #ifndef _CHICAGO_ CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf ); #else CScmRotEntry *psreRunning = GetRotEntry(pwszWinstaDesktop, pmnkeqbuf); #endif if (psreRunning != NULL) { psreRunning->GetTime(pfiletime); hr = S_OK; } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetTimeOfLastChange " " ( %lx ) \n", this, hr)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::EnumRunning // // Synopsis: Get a list of all the monikers that are currently running // // Arguments: [ppMkIFList] - Where to put list of monikers running // // Returns: NOERROR - got list // E_OUTOFMEMORY - couldn't allocate space for the list // // Algorithm: Loop through the ROT copying out the marshaled moniker buffers // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- HRESULT CScmRot::EnumRunning( #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, MkInterfaceList **ppMkIFList) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::EnumRunning " "( %p )\n", this, ppMkIFList)); HRESULT hr = E_OUTOFMEMORY; // Lock for the duration of the call CPortableLock lck(_mxs); *ppMkIFList = NULL; MkInterfaceList *pMkIFList = NULL; // This is the upper limit on how much space we'll need. DWORD dwSize = sizeof(MkInterfaceList) + (_sht.GetCount() - 1) * sizeof(InterfaceData *); // Allocate buffer pMkIFList = (MkInterfaceList *) MIDL_user_allocate(dwSize); // We use this to keep track fof the number of monikers we are returning DWORD dwOffset = 0; if (pMkIFList != NULL) { // Iterate list getting the pointers CScmHashIter shi(&_sht); CScmRotEntry *psre; while ((psre = (CScmRotEntry *) shi.GetNext()) != NULL) { InterfaceData *pifdForOutput; if ( psre->WinstaDesktop() && (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) ) continue; #ifndef _CHICAGO_ if ( S_OK != pToken->MatchToken2(psre->Token(), FALSE) ) continue; if ( gbSAFERROTChecksEnabled ) { HRESULT hr = pToken->CompareSaferLevels(psre->Token()); // S_FALSE: pToken is of lesser authorization, i.e., this // is untrusted code calling into trusted code. if (hr == S_FALSE) { DbgPrint("RPCSS: SCMROT: SAFER level did not match.\n"); continue; } } #endif pifdForOutput = AllocateAndCopy(psre->GetMoniker()); if (pifdForOutput == NULL) { goto Exit; } // Put copy in the array pMkIFList->apIFDList[dwOffset] = pifdForOutput; // We bump the count because it makes clean up easier dwOffset++; } // Teller caller and cleanup that everything went ok. hr = S_OK; // Set the output buffer to the buffer we have allocated. *ppMkIFList = pMkIFList; // Set the size of the object to return pMkIFList->dwSize = dwOffset; } Exit: if (FAILED(hr)) { // We failed so clean up if (pMkIFList != NULL) { // Clean up the moniker interfaces that were allocated for (DWORD i = 0; i < dwOffset; i++) { MIDL_user_free(pMkIFList->apIFDList[i]); } // Clean up the table structure itself MIDL_user_free(pMkIFList); } } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::EnumRunning " " ( %lx ) [ %p ]\n", this, hr, *ppMkIFList)); return hr; } //+------------------------------------------------------------------------- // // Member: CScmRot::GetRotEntry // // Synopsis: Search ROT for entry that matches the equality buffer input. // // Arguments: [pmnkeqbuf] - Moniker equality buffer to search for. // // Returns: NULL - no entry could be found // Pointer to ROT entry with matching key // // Algorithm: Calculate the hash value for the input buffer. The search // the hash table for the matching value. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmRotEntry *CScmRot::GetRotEntry( #if 1 // #ifndef _CHICAGO_ CToken *pToken, #endif WCHAR *pwszWinstaDesktop, MNKEQBUF *pmnkeqbuf) { CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetRotEntry " "( %p )\n", this, pmnkeqbuf)); DWORD dwHash; CScmRotEntry * psre; dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0); psre = (CScmRotEntry *) _sht.GetBucketList( dwHash ); for ( ; psre != NULL; psre = (CScmRotEntry *) psre->GetNext() ) { if ( psre->IsEqual(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize) ) { // // Note that this routine is actually called during a Register // to see if there is a duplicate moniker and also during a // client Lookup. This makes things a little complicated. // // The winsta\desktop param can only be null in two instances. // + While doing a Register from a service or RunAs server. The // pToken will also be null. // + While doing a ROT lookup during a secure remote activation. // The pToken will be non-null. We only check that the SIDs // match in this case. // // During an usecure activation the pToken will be NULL. The // winsta/desktop will actually be "" in this case (see // Activation) to allow us to distinguish just this case. // // The ROT entry's winsta\desktop can be null if a service or RunAs // server registered a globally available object. // // Existing registration is globally available. if ( ! psre->WinstaDesktop() ) break; // // NULL token and winsta/desktop means a server is doing a register // for a globally available object, return the match. // NULL token but non-null ("") winsta/desktop is a lookup from a // remote unsecure client, no match. // if ( ! pToken ) { if ( ! pwszWinstaDesktop ) break; else continue; } Win4Assert( psre->Token() ); if ( pwszWinstaDesktop && (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) ) continue; // Check to make sure the token matches if(S_OK != pToken->MatchToken2(psre->Token(), FALSE)) continue; // Check to make sure that the safer token matches if ( gbSAFERROTChecksEnabled ) { HRESULT hr = pToken->CompareSaferLevels(psre->Token()); // S_FALSE: pToken is of lesser authorization, i.e., this // is untrusted code calling into trusted code. if (hr == S_FALSE) { DbgPrint("RPCSS: SCMROT: SAFER level did not match.\n"); continue; } } break; } } CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetRotEntry " " ( %p )\n", this, psre)); return psre; }