//=--------------------------------------------------------------------------= // StrColl.Cpp //=--------------------------------------------------------------------------= // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. //=--------------------------------------------------------------------------= // // implementation for our simple strings collections. // #include "IPServer.H" #include "SimpleEnumVar.H" #include "StringsColl.H" // for asserts // SZTHISFILE //=--------------------------------------------------------------------------= // CStringsCollection::CStringsCollection //=--------------------------------------------------------------------------= // constructor. sets up the safearray pointer. // // Parameters: // SAFEARRAY - [in] the collection we're working with. // // Notes: // CStringCollection::CStringCollection ( SAFEARRAY *psa ) : m_psa(psa) { ASSERT(m_psa, "Bogus Safearray pointer!"); } //=--------------------------------------------------------------------------= // CStringCollection::~CStringCollection //=--------------------------------------------------------------------------= // // Notes: // CStringCollection::~CStringCollection() { } //=--------------------------------------------------------------------------= // CStringCollection::get_Count //=--------------------------------------------------------------------------= // returns the count of the things in the collection // // Parameters: // long * - [out] the count // // Output: // HRESULT - S_OK, one of the SAFEARRAY Scodes. // // Notes: // - we're assuming the safearray's lower bound is zero! // STDMETHODIMP CStringCollection::get_Count ( long *plCount ) { HRESULT hr; ASSERT(m_psa, "Who created a collection without a SAFEARRAY?"); CHECK_POINTER(plCount); // get the bounds. // hr = SafeArrayGetUBound(m_psa, 1, plCount); CLEARERRORINFORET_ON_FAILURE(hr); // add one since we're zero-offset // (*plCount)++; return S_OK; } //=--------------------------------------------------------------------------= // CStringCollection::get_Item //=--------------------------------------------------------------------------= // returns a string given an INDEX // // Parameters: // long - [in] the index to get it from // BSTR * - [out] the item // // Output: // HRESULT - S_OK, E_OUTOFMEMORY // // Notes: // STDMETHODIMP CStringCollection::get_Item ( long lIndex, BSTR *pbstrItem ) { HRESULT hr; CHECK_POINTER(pbstrItem); // get the element from the safearray // hr = SafeArrayGetElement(m_psa, &lIndex, pbstrItem); CLEARERRORINFORET_ON_FAILURE(hr); // otherwise, we've got it, so we can return // return S_OK; } //=--------------------------------------------------------------------------= // CStringCollection::get__NewEnum //=--------------------------------------------------------------------------= // returns a new IEnumVARIANT object with the collection in it. // // Parameters: // IUnknown ** - [out] new enumvariant object. // // Output: // HRESULT - S_OK, E_OUTOFMEMORY // // Notes: // STDMETHODIMP CStringCollection::get__NewEnum ( IUnknown **ppUnkNewEnum ) { HRESULT hr; long l; CHECK_POINTER(ppUnkNewEnum); // get the count of things in the SAFEARRAY // hr = get_Count(&l); CLEARERRORINFORET_ON_FAILURE(hr); // create the object. // *ppUnkNewEnum = (IUnknown *) new CSimpleEnumVariant(m_psa, l); if (!*ppUnkNewEnum) CLEARERRORINFORET(E_OUTOFMEMORY); // refcount is already 1, so we can leave. // return S_OK; } //=--------------------------------------------------------------------------= //=--------------------------------------------------------------------------= // CStringDynaCollection::CStringDynaCollection //=--------------------------------------------------------------------------= // constructor for this object. doesn't do very much. // // Parameters: // same as for CStringCollection // // Notes: // CStringDynaCollection::CStringDynaCollection ( SAFEARRAY *psa ) : CStringCollection(psa) { } //=--------------------------------------------------------------------------= // CStringDynaCollection::~CStringDynaCollection //=--------------------------------------------------------------------------= // destructor. // // Notes: // CStringDynaCollection::~CStringDynaCollection() { } //=--------------------------------------------------------------------------= // CStringDynaCollection::put_Item //=--------------------------------------------------------------------------= // sets the value of an item in the array. // // Parameters: // long - [in] index at which to put it // BSTR - [in] new value. // // Output: // HRESULT - S_OK, safearray Scode. // // Notes: // - NULLs are converted to "" // STDMETHODIMP CStringDynaCollection::put_Item ( long lIndex, BSTR bstr ) { HRESULT hr; long l; BSTR bstr2 = NULL; // get the count and verify our index // hr = get_Count(&l); RETURN_ON_FAILURE(hr); if (lIndex < 0 || lIndex >= l) CLEARERRORINFORET(E_INVALIDARG); // put out the string, convert NULLs to "" // if (!bstr) { bstr2 = SysAllocString(L""); RETURN_ON_NULLALLOC(bstr2); } hr = SafeArrayPutElement(m_psa, &lIndex, (bstr) ? bstr : bstr2); if (bstr2) SysFreeString(bstr2); CLEARERRORINFORET_ON_FAILURE(hr); return S_OK; } //=--------------------------------------------------------------------------= // CStringDynaCollection::Add //=--------------------------------------------------------------------------= // adds a new string to the end of the collection. // // Parameters: // BSTR - [in] the new string to add // // Notes: // STDMETHODIMP CStringDynaCollection::Add ( BSTR bstr ) { SAFEARRAYBOUND sab; BSTR bstr2 = NULL; HRESULT hr; long l; // get the current size of the array. // hr = get_Count(&l); RETURN_ON_FAILURE(hr); // add one new elemnt // sab.cElements = l + 1; sab.lLbound = 0; // redim the array. // hr = SafeArrayRedim(m_psa, &sab); CLEARERRORINFORET_ON_FAILURE(hr); // put the out string, converting NULLs to "" // if (!bstr) { bstr2 = SysAllocString(L""); RETURN_ON_NULLALLOC(bstr2); } hr = SafeArrayPutElement(m_psa, &l, (bstr) ? bstr : bstr2); if (bstr2) SysFreeString(bstr2); CLEARERRORINFORET_ON_FAILURE(hr); return S_OK; } //=--------------------------------------------------------------------------= // CStringDynaCollection::Remove //=--------------------------------------------------------------------------= // removes an element from the collection, and shuffles all the rest down to // fill up the space. // // Parameters: // long - [in] index of dude to remove. // // Output: // HRESULT - S_OK, safearray Scodes. // // Notes: // STDMETHODIMP CStringDynaCollection::Remove ( long lIndex ) { SAFEARRAYBOUND sab; HRESULT hr; BSTR bstr; long lCount; long x, y; // first get the count of things in our array. // hr = get_Count(&lCount); RETURN_ON_FAILURE(hr); // check the index // if (lIndex < 0 || lIndex >= lCount) CLEARERRORINFORET(E_INVALIDARG); // let's go through, shuffling everything down one. // for (x = lIndex, y = x + 1; x < lCount - 1; x++, y++) { // get the next element. // hr = SafeArrayGetElement(m_psa, &y, &bstr); CLEARERRORINFORET_ON_FAILURE(hr); // set it at the current location // hr = SafeArrayPutElement(m_psa, &x, bstr); CLEARERRORINFORET_ON_FAILURE(hr); } // we're at the last element. let's go and kill it. // sab.cElements = lCount - 1; sab.lLbound = 0; // CONSIDER: 9.95 -- there is a bug in oleaut32.dll which causes the // below to fail if cElements = 0. // hr = SafeArrayRedim(m_psa, &sab); CLEARERRORINFORET_ON_FAILURE(hr); // we're done. go bye-bye. // return S_OK; }