//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998 // // File: guidlist.cpp // // Contents: Classes for marshalling, unmarshalling Guids // // History: 24-Oct-98 SitaramR Created // //--------------------------------------------------------------------------- #include "main.h" //************************************************************* // // CGuidList::CGuidList, ~CGuidList // // Purpose: Constructor, destructor // //************************************************************* CGuidList::CGuidList() : m_pExtGuidList(0), m_bGuidsChanged(FALSE) { } CGuidList::~CGuidList() { FreeGuidList( m_pExtGuidList ); } void FreeGuidList( GUIDELEM *pGuidList ) { while ( pGuidList ) { // // Free snapin guids // GUIDELEM *pTemp; GUIDELEM *pGuidSnp = pGuidList->pSnapinGuids; while ( pGuidSnp ) { pTemp = pGuidSnp->pNext; delete pGuidSnp; pGuidSnp = pTemp; } pTemp = pGuidList->pNext; delete pGuidList; pGuidList = pTemp; } } //************************************************************* // // CGuidList::UnMarshallGuids // // Purpose: Converts string representation of guids to list // of guids. // // Parameters: pszGuids - String to convert // // Returns: S_OK if successful // //************************************************************* HRESULT CGuidList::UnMarshallGuids( TCHAR *pszGuids ) { // // Format is [{ext guid1}{snapin guid1}..{snapin guidn}][{ext guid2}...]...\0 // Both extension and snapin guids are in ascending order. // TCHAR *pchCur = pszGuids; XGuidElem xGuidElem; GUIDELEM *pGuidExtTail = 0; if ( pszGuids == 0 || lstrcmpi( pszGuids, TEXT(" ") ) == 0 ) { // // Empty property case, so nothing to unmarshall // m_pExtGuidList = 0; return S_OK; } // // Outer loop over extensions // while ( *pchCur ) { if ( *pchCur == TEXT('[') ) pchCur++; else return E_FAIL; GUID guidExt; if ( ValidateGuid( pchCur ) ) StringToGuid( pchCur, &guidExt ); else return E_FAIL; GUIDELEM *pGuidExt = new GUIDELEM; if ( pGuidExt == 0 ) return E_OUTOFMEMORY; pGuidExt->guid = guidExt; pGuidExt->pSnapinGuids = 0; pGuidExt->pNext = 0; // // Append to end of list // if ( pGuidExtTail == 0 ) xGuidElem.Set( pGuidExt ); else pGuidExtTail->pNext = pGuidExt; pGuidExtTail = pGuidExt; // // Move past '{', then skip until next '{ // pchCur++; while ( *pchCur && *pchCur != TEXT('{') ) pchCur++; if ( !(*pchCur) ) return E_FAIL; // // Inner loop over snapin guids // GUIDELEM *pGuidSnapinTail = 0; while ( *pchCur != TEXT(']') ) { GUID guidSnp; if ( ValidateGuid( pchCur ) ) StringToGuid( pchCur, &guidSnp ); else return E_FAIL; GUIDELEM *pGuidSnapin = new GUIDELEM; if ( pGuidSnapin == 0 ) return E_OUTOFMEMORY; pGuidSnapin->guid = guidSnp; pGuidSnapin->pSnapinGuids = 0; pGuidSnapin->pNext = 0; // // Append to end of list // if ( pGuidSnapinTail == 0 ) pGuidExtTail->pSnapinGuids = pGuidSnapin; else pGuidSnapinTail->pNext = pGuidSnapin; pGuidSnapinTail = pGuidSnapin; while ( *pchCur && *pchCur != TEXT('}') ) pchCur++; if ( !(*pchCur) ) return E_FAIL; pchCur++; if ( *pchCur != TEXT('{') && *pchCur != TEXT(']') ) return E_FAIL; } // inner while pchCur++; } // outer while m_pExtGuidList = xGuidElem.Acquire(); return S_OK; } //************************************************************* // // CGuidList::MarshallGuids // // Purpose: Converts list of guids to string representation // // Parameters: xValueOut - String representation returned here // // Returns: S_OK if successful // //************************************************************* HRESULT CGuidList::MarshallGuids( XPtrST& xValueOut ) { // // Get count of guids to allocate sufficient space up front // DWORD dwCount = 1; GUIDELEM *pGuidExt = m_pExtGuidList; while ( pGuidExt ) { dwCount++; GUIDELEM *pGuidSnapin = pGuidExt->pSnapinGuids; while ( pGuidSnapin ) { dwCount++; pGuidSnapin = pGuidSnapin->pNext; } pGuidExt = pGuidExt->pNext; } LONG lSize = dwCount * (GUID_LENGTH + 6); TCHAR *pszValue = new TCHAR[lSize]; if ( pszValue == 0 ) return E_OUTOFMEMORY; xValueOut.Set( pszValue ); TCHAR *pchCur = pszValue; // // Actual marshalling // if ( m_pExtGuidList == 0 ) { HRESULT hr; // // Adsi doesn't commit null strings, so use ' ' instead // hr = StringCchCopy( pchCur, lSize, TEXT(" ") ); return hr; } pGuidExt = m_pExtGuidList; while ( pGuidExt ) { DmAssert( lSize > GUID_LENGTH * 2 + (pchCur-pszValue) ); *pchCur = TEXT('['); pchCur++; GuidToString( &pGuidExt->guid, pchCur ); pchCur += GUID_LENGTH; GUIDELEM *pGuidSnp = pGuidExt->pSnapinGuids; while ( pGuidSnp ) { DmAssert( lSize > GUID_LENGTH + (pchCur-pszValue) ); GuidToString( &pGuidSnp->guid, pchCur ); pchCur += GUID_LENGTH; pGuidSnp = pGuidSnp->pNext; } *pchCur = TEXT(']'); pchCur++; pGuidExt = pGuidExt->pNext; } *pchCur = 0; return S_OK; } //************************************************************* // // CGuidList::Update // // Purpose: Updates in memory list with guid info // // Parameters: bAdd - Add or delete // pGuidExtension - Extension's guid // pGuidSnapin - Snapin's guid // // Returns: S_OK if successful // //************************************************************* HRESULT CGuidList::Update( BOOL bAdd, GUID *pGuidExtension, GUID *pGuidSnapin ) { HRESULT hr = E_FAIL; GUIDELEM *pTrailPtr = NULL; GUIDELEM *pCurPtr = m_pExtGuidList; while ( pCurPtr != NULL ) { if ( *pGuidExtension == pCurPtr->guid ) { hr = UpdateSnapinGuid( bAdd, pCurPtr, pGuidSnapin ); if ( FAILED(hr) ) return hr; if ( pCurPtr->pSnapinGuids == NULL ) { // // Remove extension from list // if ( pTrailPtr == NULL ) m_pExtGuidList = pCurPtr->pNext; else pTrailPtr->pNext = pCurPtr->pNext; delete pCurPtr; m_bGuidsChanged = TRUE; } return S_OK; } else if ( CompareGuid( pGuidExtension, &pCurPtr->guid ) < 0 ) { // // Since guids are in ascending order, // pGuidExtension is not in list, add if necessary // if ( bAdd ) { GUIDELEM *pGuidExt = new GUIDELEM; if ( pGuidExt == 0 ) return E_OUTOFMEMORY; pGuidExt->pSnapinGuids = new GUIDELEM; if ( pGuidExt->pSnapinGuids == 0 ) { delete pGuidExt; return E_OUTOFMEMORY; } pGuidExt->guid = *pGuidExtension; pGuidExt->pNext = pCurPtr; pGuidExt->pSnapinGuids->guid = *pGuidSnapin; pGuidExt->pSnapinGuids->pSnapinGuids = 0; pGuidExt->pSnapinGuids->pNext = 0; if ( pTrailPtr == 0) m_pExtGuidList = pGuidExt; else pTrailPtr->pNext = pGuidExt; m_bGuidsChanged = TRUE; } return S_OK; } else // compareguid { // // Advance down the list // pTrailPtr = pCurPtr; pCurPtr = pCurPtr->pNext; } } // while // // End of list or null list, add guid at end if necessary // if ( bAdd ) { GUIDELEM *pGuidExt = new GUIDELEM; if ( pGuidExt == 0 ) return E_OUTOFMEMORY; pGuidExt->pSnapinGuids = new GUIDELEM; if ( pGuidExt->pSnapinGuids == 0 ) { delete pGuidExt; return E_OUTOFMEMORY; } pGuidExt->guid = *pGuidExtension; pGuidExt->pNext = 0; pGuidExt->pSnapinGuids->guid = *pGuidSnapin; pGuidExt->pSnapinGuids->pSnapinGuids = 0; pGuidExt->pSnapinGuids->pNext = 0; if ( pTrailPtr == 0) m_pExtGuidList = pGuidExt; else pTrailPtr->pNext = pGuidExt; m_bGuidsChanged = TRUE; } return S_OK; } //************************************************************* // // CGuidList::UpdateSnapinGuid // // Purpose: Updates snapin list with guid info // // Parameters: bAdd - Add or delete // pExtGuid - Extension's guid ptr // pGuidSnapin - Snapin's guid // // Returns: S_OK if successful // //************************************************************* HRESULT CGuidList::UpdateSnapinGuid( BOOL bAdd, GUIDELEM *pExtGuid, GUID *pGuidSnapin ) { GUIDELEM *pTrailPtr = 0; GUIDELEM *pCurPtr = pExtGuid->pSnapinGuids; while ( pCurPtr != NULL ) { if ( *pGuidSnapin == pCurPtr->guid ) { if ( !bAdd ) { if ( pTrailPtr == NULL ) pExtGuid->pSnapinGuids = pCurPtr->pNext; else pTrailPtr->pNext = pCurPtr->pNext; delete pCurPtr; m_bGuidsChanged = TRUE; } return S_OK; } else if ( CompareGuid( pGuidSnapin, &pCurPtr->guid ) < 0 ) { // // Since guids are in ascending order, // pGuidSnapin is not in list, add if necessary // if ( bAdd ) { GUIDELEM *pGuidSnp = new GUIDELEM; if ( pGuidSnp == 0 ) return E_OUTOFMEMORY; pGuidSnp->guid = *pGuidSnapin; pGuidSnp->pSnapinGuids = 0; pGuidSnp->pNext = pCurPtr; if ( pTrailPtr == NULL ) pExtGuid->pSnapinGuids = pGuidSnp; else pTrailPtr->pNext = pGuidSnp; m_bGuidsChanged = TRUE; } return S_OK; } else { // // Advance down the list // pTrailPtr = pCurPtr; pCurPtr = pCurPtr->pNext; } } // while // // End of list or null list, add guid at end if necessary // if ( bAdd ) { GUIDELEM *pGuidSnp = new GUIDELEM; if ( pGuidSnp == 0 ) return E_OUTOFMEMORY; pGuidSnp->guid = *pGuidSnapin; pGuidSnp->pSnapinGuids = 0; pGuidSnp->pNext = 0; if ( pTrailPtr == 0 ) pExtGuid->pSnapinGuids = pGuidSnp; else pTrailPtr->pNext = pGuidSnp; m_bGuidsChanged = TRUE; } return S_OK; }