//+------------------------------------------------------------ // // Copyright (C) 1998, Microsoft Corporation // // File: icatitemattr.cpp // // Contents: Implementation of CICategorizerItemAttributesIMP // // Classes: // CLdapResultWrap // CICategorizerItemAttributesIMP // // Functions: // // History: // jstamerj 1998/07/01 13:48:15: Created. // //------------------------------------------------------------- #include "precomp.h" #include "icatitemattr.h" //+------------------------------------------------------------ // // Function: CLdapResultWrap::CLdapResultWrap // // Synopsis: Refcount an LDAP Message, call ldap_msg_free when all // references have been released // // Arguments: // pCPLDAPWrap: PLDAP to refcount // pMessage: the LDAPMessage to refcount // // Returns: NOTHING // // History: // jstamerj 1998/10/05 13:12:15: Created. // //------------------------------------------------------------- CLdapResultWrap::CLdapResultWrap( ISMTPServerEx *pISMTPServerEx, CPLDAPWrap *pCPLDAPWrap, PLDAPMessage pMessage) { _ASSERT(pCPLDAPWrap); _ASSERT(pMessage); m_pCPLDAPWrap = pCPLDAPWrap; m_pCPLDAPWrap->AddRef(); m_pLDAPMessage = pMessage; m_lRefCount = 0; m_pISMTPServerEx = pISMTPServerEx; if(m_pISMTPServerEx) m_pISMTPServerEx->AddRef(); } //+------------------------------------------------------------ // // Function: CLdapResultWrap::AddRef // // Synopsis: Increment the ref count of this object // // Arguments: NONE // // Returns: new refcount // // History: // jstamerj 1998/10/05 13:14:59: Created. // //------------------------------------------------------------- LONG CLdapResultWrap::AddRef() { return InterlockedIncrement(&m_lRefCount); } //+------------------------------------------------------------ // // Function: CLdapResultWrap::Release // // Synopsis: Decrement the ref count. Free the object when the // refcount hits zero // // Arguments: NONE // // Returns: New refcount // // History: // jstamerj 1998/10/05 13:26:47: Created. // //------------------------------------------------------------- LONG CLdapResultWrap::Release() { LONG lNewRefCount; lNewRefCount = InterlockedDecrement(&m_lRefCount); if(lNewRefCount == 0) { // // Release this ldapmessage // delete this; return 0; } else { return lNewRefCount; } } //+------------------------------------------------------------ // // Function: CLdapResultWrap::~CLdapResultWrap // // Synopsis: Release the ldap message result // // Arguments: NONE // // Returns: NOTHING // // History: // jstamerj 1998/10/05 13:31:39: Created. // //------------------------------------------------------------- CLdapResultWrap::~CLdapResultWrap() { m_pCPLDAPWrap->Release(); ldap_msgfree(m_pLDAPMessage); if(m_pISMTPServerEx) m_pISMTPServerEx->Release(); } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::CICategorizerItemAttributesIMP // // Synopsis: Initializes member data // // Arguments: // pldap: PLDAP to use // pldapmessage: PLDAPMessage to serve out // // Returns: NOTHING // // History: // jstamerj 1998/07/02 12:35:15: Created. // //------------------------------------------------------------- CICategorizerItemAttributesIMP::CICategorizerItemAttributesIMP( PLDAP pldap, PLDAPMessage pldapmessage, CLdapResultWrap *pResultWrap) { m_dwSignature = CICATEGORIZERITEMATTRIBUTESIMP_SIGNATURE; _ASSERT(pldap); _ASSERT(pldapmessage); _ASSERT(pResultWrap); m_pldap = pldap; m_pldapmessage = pldapmessage; m_cRef = 0; m_pResultWrap = pResultWrap; m_pResultWrap->AddRef(); } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::~CICategorizerItemAttributesIMP // // Synopsis: Checks to make sure signature is valid and then resets signature // // Arguments: NONE // // Returns: NOTHING // // History: // jstamerj 1998/07/02 12:39:45: Created. // //------------------------------------------------------------- CICategorizerItemAttributesIMP::~CICategorizerItemAttributesIMP() { m_pResultWrap->Release(); _ASSERT(m_dwSignature == CICATEGORIZERITEMATTRIBUTESIMP_SIGNATURE); m_dwSignature = CICATEGORIZERITEMATTRIBUTESIMP_SIGNATURE_INVALID; } //+------------------------------------------------------------ // // Function: QueryInterface // // Synopsis: Returns pointer to this object for IUnknown and ICategorizerItemAttributes // // Arguments: // iid -- interface ID // ppv -- pvoid* to fill in with pointer to interface // // Returns: // S_OK: Success // E_NOINTERFACE: Don't support that interface // // History: // jstamerj 980612 14:07:57: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::QueryInterface( REFIID iid, LPVOID *ppv) { *ppv = NULL; if(iid == IID_IUnknown) { *ppv = (LPVOID) this; } else if (iid == IID_ICategorizerItemAttributes) { *ppv = (LPVOID) ((ICategorizerItemAttributes *) this); } else if (iid == IID_ICategorizerItemRawAttributes) { *ppv = (LPVOID) ((ICategorizerItemRawAttributes *) this); } else if (iid == IID_ICategorizerUTF8Attributes) { *ppv = (LPVOID) ((ICategorizerUTF8Attributes *) this); } else { return E_NOINTERFACE; } AddRef(); return S_OK; } //+------------------------------------------------------------ // // Function: AddRef // // Synopsis: adds a reference to this object // // Arguments: NONE // // Returns: New reference count // // History: // jstamerj 980611 20:07:14: Created. // //------------------------------------------------------------- ULONG CICategorizerItemAttributesIMP::AddRef() { return InterlockedIncrement((PLONG)&m_cRef); } //+------------------------------------------------------------ // // Function: Release // // Synopsis: releases a reference, deletes this object when the // refcount hits zero. // // Arguments: NONE // // Returns: New reference count // // History: // jstamerj 980611 20:07:33: Created. // //------------------------------------------------------------- ULONG CICategorizerItemAttributesIMP::Release() { LONG lNewRefCount; lNewRefCount = InterlockedDecrement((PLONG)&m_cRef); if(lNewRefCount == 0) { delete this; return 0; } else { return lNewRefCount; } } //+------------------------------------------------------------ // // Function: BeginAttributeEnumeration // // Synopsis: Prepare to enumerate through attribute values for a specific attribute // // Arguments: // pszAttributeName: Name of attribute to enumerate through // penumerator: Uninitialized Enumerator structure to use // // Returns: // S_OK: Success // CAT_E_PROPNOTFOUND: No attributes values exist // // History: // jstamerj 1998/07/02 10:54:00: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::BeginAttributeEnumeration( IN LPCSTR pszAttributeName, IN PATTRIBUTE_ENUMERATOR penumerator) { CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::BeginAttributeEnumeration"); _ASSERT(pszAttributeName); _ASSERT(penumerator); penumerator->pvBase = penumerator->pvCurrent = ldap_get_values( m_pldap, m_pldapmessage, (LPSTR)pszAttributeName); if(penumerator->pvBase == NULL) { ErrorTrace((LPARAM)this, "Requested attribute %s not found", pszAttributeName); CatFunctLeaveEx((LPARAM)this); return CAT_E_PROPNOTFOUND; } CatFunctLeaveEx((LPARAM)this); return S_OK; } //+------------------------------------------------------------ // // Function: GetNextAttributeValue // // Synopsis: Get the next attribute in an enumeration // // Arguments: // penumerator: enumerator sturcture initialized in BeginAttributeEnumeration // ppszAttributeValue: Ptr to Ptr to recieve Ptr to string of attribute value // // Returns: // S_OK: Success // HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) // // History: // jstamerj 1998/07/02 11:14:54: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::GetNextAttributeValue( IN PATTRIBUTE_ENUMERATOR penumerator, OUT LPSTR *ppszAttributeValue) { _ASSERT(penumerator); _ASSERT(ppszAttributeValue); *ppszAttributeValue = *((LPSTR *)penumerator->pvCurrent); if(*ppszAttributeValue) { // // Advance enumerator to next value // penumerator->pvCurrent = (PVOID) (((LPSTR *)penumerator->pvCurrent)+1); return S_OK; } else { // // This is the last value // return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); } } //+------------------------------------------------------------ // // Function: RewindAttributeEnumeration // // Synopsis: Rewind enumerator to beginning of attribute value list // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/07/06 11:22:23: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::RewindAttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { penumerator->pvCurrent = penumerator->pvBase; return S_OK; } //+------------------------------------------------------------ // // Function: EndAttributeEnumeration // // Synopsis: Free memory associated with an attribute enumeration // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/07/02 12:24:44: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::EndAttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { _ASSERT(penumerator); ldap_value_free((LPSTR *)penumerator->pvBase); return S_OK; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::BeginAttributeNameEnumeration // // Synopsis: Enumerate through the attributes returned from LDAP // // Arguments: // penumerator: Caller allocated enumerator structure to be // initialized by this call // // Returns: // S_OK: Success // // History: // jstamerj 1998/09/18 10:49:56: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::BeginAttributeNameEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { _ASSERT(penumerator); penumerator->pvBase = penumerator->pvCurrent = NULL; return S_OK; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::GetNextAttributeName // // Synopsis: enumerate through the attribute names returned // // Arguments: // penumerator: enumerator strucutre initialized in BeginAttributeNameEnumeration // ppszAttributeValue: out parameter for an attribute name // // Returns: // S_OK: Success // HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) // // History: // jstamerj 1998/09/18 10:53:15: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::GetNextAttributeName( IN PATTRIBUTE_ENUMERATOR penumerator, OUT LPSTR *ppszAttributeName) { _ASSERT(penumerator); _ASSERT(ppszAttributeName); if(penumerator->pvCurrent == NULL) { *ppszAttributeName = ldap_first_attribute( m_pldap, m_pldapmessage, (BerElement **) &(penumerator->pvCurrent)); } else { *ppszAttributeName = ldap_next_attribute( m_pldap, m_pldapmessage, (BerElement *) (penumerator->pvCurrent)); } if(*ppszAttributeName == NULL) { // // Assume we've reached the end of the attribute name // enumeration // return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); } else { return S_OK; } } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributeIMP::EndAttributeNameEnumeration // // Synopsis: Free all data held for this enumeration // // Arguments: // penumerator: enumerator strucutre initialized in BeginAttributeNameEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/09/18 11:04:37: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::EndAttributeNameEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { // // Ldap uses only buffers in the connection block for this, so we // don't need to explicitly free anything // return S_OK; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::AggregateAttributes // // Synopsis: Normally, accept and ICategorizerItemAttributes for aggregation // // Arguments: // pICatItemAttributes: attributes to aggregate // // Returns: // E_NOTIMPL // // History: // jstamerj 1998/07/16 14:42:16: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::AggregateAttributes( IN ICategorizerItemAttributes *pICatItemAttributes) { return E_NOTIMPL; } //+------------------------------------------------------------ // // Function: BeginRawAttributeEnumeration // // Synopsis: Prepare to enumerate through attribute values for a specific attribute // // Arguments: // pszAttributeName: Name of attribute to enumerate through // penumerator: Uninitialized Enumerator structure to use // // Returns: // S_OK: Success // CAT_E_PROPNOTFOUND: No attributes values exist // // History: // jstamerj 1998/12/09 12:44:15: Created // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::BeginRawAttributeEnumeration( IN LPCSTR pszAttributeName, IN PATTRIBUTE_ENUMERATOR penumerator) { CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::BeginRawAttributeEnumeration"); _ASSERT(pszAttributeName); _ASSERT(penumerator); penumerator->pvBase = penumerator->pvCurrent = ldap_get_values_len( m_pldap, m_pldapmessage, (LPSTR)pszAttributeName); if(penumerator->pvBase == NULL) { ErrorTrace((LPARAM)this, "Requested attribute %s not found", pszAttributeName); CatFunctLeaveEx((LPARAM)this); return CAT_E_PROPNOTFOUND; } CatFunctLeaveEx((LPARAM)this); return S_OK; } //+------------------------------------------------------------ // // Function: GetNextRawAttributeValue // // Synopsis: Get the next attribute in an enumeration // // Arguments: // penumerator: enumerator sturcture initialized in BeginAttributeEnumeration // pdwcb: dword to set to the # of bytes in the pvValue buffer // pvValue: Ptr to recieve Ptr to raw attribute value // // Returns: // S_OK: Success // HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) // // History: // jstamerj 1998/12/09 12:49:27: Created // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::GetNextRawAttributeValue( IN PATTRIBUTE_ENUMERATOR penumerator, OUT PDWORD pdwcb, OUT LPVOID *pvValue) { _ASSERT(penumerator); _ASSERT(pdwcb); _ASSERT(pvValue); if( (*((PLDAP_BERVAL *)penumerator->pvCurrent)) != NULL) { *pdwcb = (* ((PLDAP_BERVAL *)penumerator->pvCurrent))->bv_len; *pvValue = (* ((PLDAP_BERVAL *)penumerator->pvCurrent))->bv_val; // // Advance enumerator to next value // penumerator->pvCurrent = (PVOID) (((PLDAP_BERVAL *)penumerator->pvCurrent)+1); return S_OK; } else { // // This is the last value // *pdwcb = 0; *pvValue = NULL; return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); } } //+------------------------------------------------------------ // // Function: RewindRawAttributeEnumeration // // Synopsis: Rewind enumerator to beginning of attribute value list // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/12/09 12:49:23: Created // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::RewindRawAttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { return RewindAttributeEnumeration(penumerator); } //+------------------------------------------------------------ // // Function: EndRawAttributeEnumeration // // Synopsis: Free memory associated with an attribute enumeration // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/12/09 12:50:02: Created // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::EndRawAttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { _ASSERT(penumerator); ldap_value_free_len((struct berval **)penumerator->pvBase); return S_OK; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::GetAllAttributeValues // // Synopsis: Retrieve all values for a particular attribute at once. // This may not be optimal for attributes with a large number of // values (enumerating through the values may be better performace wise). // // Arguments: // pszAttributeName: The name of the attribute you want // penumerator: A user allocated ATTRIBUTE_ENUMERATOR structure for // use by the ICategorizerItemAttributes implementor // prgpszAttributeValues: Where to return the pointer to the // attribute string array. This will be a NULL terminated array of // pointers to strings. // // Returns: // S_OK: Success // CAT_E_PROPNOTFOUND: None of those attributes exist // // History: // jstamerj 1998/12/10 18:55:38: Created. // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::GetAllAttributeValues( LPCSTR pszAttributeName, PATTRIBUTE_ENUMERATOR penumerator, LPSTR **prgpszAttributeValues) { HRESULT hr; CatFunctEnter("CICategorizerItemAttributesIMP::GetAllAttributeValues"); // // piggy back on BeginAttributeEnumeration // hr = BeginAttributeEnumeration( pszAttributeName, penumerator); if(SUCCEEDED(hr)) { // // return the array // *prgpszAttributeValues = (LPSTR *) penumerator->pvBase; } DebugTrace(NULL, "returning hr %08lx", hr); CatFunctLeave(); return hr; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::ReleaseAllAttributes // // Synopsis: Release the attributes allocated from GetAllAttributeValues // // Arguments: // penumerator: the enumerator passed into GetAllAttributeValues // // Returns: // S_OK: Success // // History: // jstamerj 1998/12/10 19:38:57: Created. // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::ReleaseAllAttributeValues( PATTRIBUTE_ENUMERATOR penumerator) { HRESULT hr; CatFunctEnter("CICategorizerItemAttributesIMP::ReleaseAllAttributes"); // // piggy back off of endattributeenumeration // hr = EndAttributeEnumeration( penumerator); DebugTrace(NULL, "returning hr %08lx", hr); CatFunctLeave(); return hr; } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::CountAttributeValues // // Synopsis: Return a count of the number of attribute values associated // with this enumerator // // Arguments: // penumerator: describes the attribute in question // pdwCount: Out parameter for the count // // Returns: // S_OK: Success // // History: // jstamerj 1999/03/25 14:36:58: Created. // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::CountAttributeValues( IN PATTRIBUTE_ENUMERATOR penumerator, OUT DWORD *pdwCount) { CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::CountAttributeValues"); _ASSERT(pdwCount); *pdwCount = ldap_count_values((PCHAR *) penumerator->pvBase); CatFunctLeaveEx((LPARAM)this); return S_OK; } // CICategorizerItemAttributesIMP::CountAttributeValues //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::CountRawAttributeValues // // Synopsis: Return a count of the number of attribute values associated // with this enumerator // // Arguments: // penumerator: describes the attribute in question // pdwCount: Out parameter for the count // // Returns: // S_OK: Success // // History: // jstamerj 1999/03/25 14:39:54: Created // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::CountRawAttributeValues( IN PATTRIBUTE_ENUMERATOR penumerator, OUT DWORD *pdwCount) { CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::CountRawAttributeValues"); _ASSERT(pdwCount); *pdwCount = ldap_count_values_len((struct berval **) penumerator->pvBase); CatFunctLeaveEx((LPARAM)this); return S_OK; } // CICategorizerItemAttributesIMP::CountRawAttributeValues //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::BeginUTF8AttributeEnumeration // // Synopsis: Begin UTF8 attribute enumeration // // Arguments: // pszAttributeName: Name of attribute to enumerate through // penumerator: Uninitialized Enumerator structure to use // // Returns: // S_OK: Success // CAT_E_PROPNOTFOUND: No attributes values exist // // Returns: // S_OK: Success // // History: // jstamerj 1999/12/10 11:14:35: Created. // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::BeginUTF8AttributeEnumeration( IN LPCSTR pszAttributeName, IN PATTRIBUTE_ENUMERATOR penumerator) { HRESULT hr; CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::BeginUTF8AttributeEnumeration"); // // Piggy back raw attribute enumeration and use the pvContext // member of penumerator. // hr = BeginRawAttributeEnumeration( pszAttributeName, penumerator); penumerator->pvContext = NULL; DebugTrace((LPARAM)this, "returning hr %08lx", hr); CatFunctLeaveEx((LPARAM)this); return hr; } //+------------------------------------------------------------ // // Function: GetNextAttributeValue // // Synopsis: Get the next attribute in an enumeration // // Arguments: // penumerator: enumerator sturcture initialized in BeginAttributeEnumeration // ppszAttributeValue: Ptr to Ptr to recieve Ptr to string of attribute value // // Returns: // S_OK: Success // HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) // // History: // jstamerj 1998/07/02 11:14:54: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::GetNextUTF8AttributeValue( IN PATTRIBUTE_ENUMERATOR penumerator, OUT LPSTR *ppszAttributeValue) { HRESULT hr = S_OK; DWORD dwcb = 0; LPVOID pvAttributeValue = NULL; LPSTR psz = NULL; CatFunctEnterEx((LPARAM)this, "CICategorizerItemAttributesIMP::GetNextUTF8AttributeValue"); if(penumerator->pvContext) { delete [] (LPSTR) penumerator->pvContext; penumerator->pvContext = NULL; } hr = GetNextRawAttributeValue( penumerator, &dwcb, &pvAttributeValue); if(FAILED(hr)) return hr; // // Convert to termianted UTF8 string // psz = new CHAR[dwcb + 1]; if(psz == NULL) { ERROR_LOG("new CHAR[]"); return E_OUTOFMEMORY; } CopyMemory(psz, pvAttributeValue, dwcb); psz[dwcb] = '\0'; *ppszAttributeValue = psz; penumerator->pvContext = psz; CatFunctLeaveEx((LPARAM)this); return hr; } //+------------------------------------------------------------ // // Function: RewindAttributeEnumeration // // Synopsis: Rewind enumerator to beginning of attribute value list // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/07/06 11:22:23: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::RewindUTF8AttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { return RewindRawAttributeEnumeration( penumerator); } //+------------------------------------------------------------ // // Function: EndAttributeEnumeration // // Synopsis: Free memory associated with an attribute enumeration // // Arguments: // penumerator: attribute enumerator initialized by BeginAttributeEnumeration // // Returns: // S_OK: Success // // History: // jstamerj 1998/07/02 12:24:44: Created. // //------------------------------------------------------------- STDMETHODIMP CICategorizerItemAttributesIMP::EndUTF8AttributeEnumeration( IN PATTRIBUTE_ENUMERATOR penumerator) { if(penumerator->pvContext) { delete [] (LPSTR) penumerator->pvContext; penumerator->pvContext = NULL; } return EndRawAttributeEnumeration(penumerator); } //+------------------------------------------------------------ // // Function: CICategorizerItemAttributesIMP::CountUTF8AttributeValues // // Synopsis: Return a count of the number of attribute values associated // with this enumerator // // Arguments: // penumerator: describes the attribute in question // pdwCount: Out parameter for the count // // Returns: // S_OK: Success // // History: // jstamerj 1999/03/25 14:39:54: Created // //------------------------------------------------------------- HRESULT CICategorizerItemAttributesIMP::CountUTF8AttributeValues( IN PATTRIBUTE_ENUMERATOR penumerator, OUT DWORD *pdwCount) { return CountRawAttributeValues( penumerator, pdwCount); } // CICategorizerItemAttributesIMP::CountRawAttributeValues