// SSRMemberShip.cpp : Implementation of CSsrMembership #include "stdafx.h" #include "global.h" #include "SSRTE.h" #include "SSRMemberShip.h" #include "SSRLog.h" #include "MemberAccess.h" ///////////////////////////////////////////////////////////////////////////// // CSsrMembership /* Routine Description: Name: CSsrMembership::CSsrMembership Functionality: constructor. This constructor also builds the member list. Virtual: no. Arguments: none. Return Value: none. Notes: */ CSsrMembership::CSsrMembership() { } /* Routine Description: Name: CSsrMembership::~CSsrMembership Functionality: destructor Virtual: yes. Arguments: none. Return Value: none. Notes: */ CSsrMembership::~CSsrMembership() { map >::iterator it = m_ssrMemberAccessMap.begin(); map >::iterator itEnd = m_ssrMemberAccessMap.end(); while(it != itEnd) { CSsrMemberAccess * pMA = (*it).second; pMA->Release(); it++; } m_ssrMemberAccessMap.clear(); } HRESULT CSsrMembership::LoadAllMember () /*++ Routine Description: Name: CSsrMembership::LoadAllMember Functionality: Will try to load all information about all the members that are registered with SSR. Virtual: no. Arguments: None. Return Value: Success: various success code. Failure: various error codes. However, we may tolerate that and only load those that we can load successfully. So, don't blindly quit. Notes: --*/ { // // We should never load more than once. // if (m_ssrMemberAccessMap.size() > 0) { return S_OK; // we let you call it if you have already call it before } // // Let's enumerate through the Members directory's .xml files. They will // all be considered as member registration files. // WCHAR wcsXmlFiles[MAX_PATH + 2]; _snwprintf(wcsXmlFiles, MAX_PATH + 1, L"%s\\Members\\*.xml", g_wszSsrRoot); wcsXmlFiles[MAX_PATH + 1] = L'\0'; long lDirLen = wcslen(wcsXmlFiles); if (lDirLen > MAX_PATH) { return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); } lDirLen -= 5; WIN32_FIND_DATA wfd; DWORD dwErr; HRESULT hr; HANDLE hFindFiles = FindFirstFile( wcsXmlFiles, // file name &wfd // information buffer ); if (INVALID_HANDLE_VALUE == hFindFiles) { hr = S_FALSE; g_fblog.LogError(hr, L"There is no member to load", wcsXmlFiles ); return hr; } HRESULT hrFirstError = S_OK; long lFileNameLength; while (INVALID_HANDLE_VALUE != hFindFiles) { // // make sure that we won't load anything other then a perfect .xml extension // file. I found that this Find will return such files: adc.xml-xxx // lFileNameLength = wcslen(wfd.cFileName); if (_wcsicmp(wfd.cFileName + lFileNameLength - 4, L".xml") == 0) { // // Get the file name and then load that member // wcsncpy(wcsXmlFiles + lDirLen, wfd.cFileName, lFileNameLength + 1); hr = LoadMember(wcsXmlFiles); if (FAILED(hr)) { g_fblog.LogError(hr, L"CSsrMembership loading member failed", wcsXmlFiles ); if (SUCCEEDED(hr)) { hrFirstError = hr; } } } if (!FindNextFile (hFindFiles, &wfd)) { dwErr = GetLastError(); if (ERROR_NO_MORE_FILES != dwErr) { // // log it // g_fblog.LogError(HRESULT_FROM_WIN32(dwErr), L"CSsrMembership", L"FindNextFile" ); } break; } } FindClose(hFindFiles); return hrFirstError; } /* Routine Description: Name: CSsrMembership::LoadMember Functionality: By given a valid member name, this function will load all the detailed information from the registry. Virtual: no. Arguments: wszMemberFilePath - The XML registration file path for a particular member. Return Value: Success: S_OK. Failure: various error codes Notes: */ HRESULT CSsrMembership::LoadMember ( IN LPCWSTR wszMemberFilePath ) { HRESULT hr = S_OK; CComObject * pMA = NULL; hr = CComObject::CreateInstance(&pMA); if (SUCCEEDED(hr)) { // // holding on to the object. When the member access // map cleans up, remember to let go the objects // pMA->AddRef(); hr = pMA->Load(wszMemberFilePath); if (S_OK == hr) { // // Everything is fine and we loaded the member. // Add it to our map. The map owns the object from this point on. // m_ssrMemberAccessMap.insert( map >::value_type(pMA->GetName(), pMA) ); } else { // // let go the object // pMA->Release(); g_fblog.LogError(hr, wszMemberFilePath, NULL); } } else { g_fblog.LogError(hr, wszMemberFilePath, NULL); } return hr; } /* Routine Description: Name: CSsrMembership::GetAllMembers Functionality: Retrieve all members currently registered on the system. Virtual: yes. Arguments: pvarArrayMembers - Receives names of the members Return Value: ?. Notes: */ STDMETHODIMP CSsrMembership::GetAllMembers ( OUT VARIANT * pvarArrayMembers // [out, retval] ) { if (pvarArrayMembers == NULL) { return E_INVALIDARG; } // // have a clean output parameter, no matter what // ::VariantInit(pvarArrayMembers); // // prepare the safearray // SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = m_ssrMemberAccessMap.size(); SAFEARRAY * psa = ::SafeArrayCreate(VT_VARIANT , 1, rgsabound); HRESULT hr = S_OK; if (psa == NULL) { hr = E_OUTOFMEMORY; } else { map >::iterator it = m_ssrMemberAccessMap.begin(); map >::iterator itEnd = m_ssrMemberAccessMap.end(); // // we only add one name at a time // long indecies[1] = {0}; while(it != itEnd) { CSsrMemberAccess * pMA = (*it).second; VARIANT varName; varName.vt = VT_BSTR; // // don't clean up varName! CSsrMemberAccess::GetName returns // a const BSTR which simplies points to the cached variable! // varName.bstrVal = pMA->GetName(); hr = ::SafeArrayPutElement(psa, indecies, &varName); if (FAILED(hr)) { break; } indecies[0]++; ++it; } if (SUCCEEDED(hr)) { pvarArrayMembers->vt = VT_ARRAY | VT_VARIANT; pvarArrayMembers->parray = psa; } else { ::SafeArrayDestroy(psa); } } return hr; } /* Routine Description: Name: CSsrMembership::GetMember Functionality: Retrieve one member of the given name. Virtual: yes. Arguments: pvarMember - Receives ISsrMemberAccess object of the named member. Return Value: Success: S_OK; Failure: various error codes. Notes: */ STDMETHODIMP CSsrMembership::GetMember ( IN BSTR bstrMemberName, OUT VARIANT * pvarMember //[out, retval] ) { if (bstrMemberName == NULL || *bstrMemberName == L'\0' || pvarMember == NULL) { return E_INVALIDARG; } ::VariantInit(pvarMember); CSsrMemberAccess * pMA = GetMemberByName(bstrMemberName); HRESULT hr = S_OK; if (pMA != NULL) { pvarMember->vt = VT_DISPATCH; hr = pMA->QueryInterface(IID_ISsrMemberAccess, (LPVOID*)&(pvarMember->pdispVal) ); if (hr != S_OK) { pvarMember->vt = VT_EMPTY; hr = E_SSR_MEMBER_NOT_FOUND; } } else { hr = E_SSR_MEMBER_NOT_FOUND; } return hr; } /* Routine Description: Name: CSsrMembership::GetMemberByName Functionality: Will find the CSsrMemberAccess object based the name. Virtual: No. Arguments: bstrMemberName - The member's name Return Value: None NULL if the object is found. Otherwise, it returns NULL. Notes: Since this is a helper function, we don't call AddRef to the returned object! */ CSsrMemberAccess* CSsrMembership::GetMemberByName ( IN BSTR bstrMemberName ) { map >::iterator it = m_ssrMemberAccessMap.find(bstrMemberName); if (it != m_ssrMemberAccessMap.end()) { CSsrMemberAccess * pMA = (*it).second; return pMA; } return NULL; }