|
|
// DSColumn.cpp : Implementation of ds column routines and classes
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: DSColumn.cpp
//
// Contents: DS Column routines, classes, and static data
//
// History: 12-Mar-99 JeffJon Created
//
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "util.h"
#include "DSColumn.h"
#include "dscookie.h"
#include "dsutil.h"
BOOL ColumnExtractStringValue( OUT CString& strref, IN CDSCookie*, IN PADS_SEARCH_COLUMN pColumn, IN DWORD iValue) { if (pColumn == NULL || pColumn->dwNumValues <= iValue) { return FALSE; }
switch (pColumn->dwADsType) { case ADSTYPE_CASE_IGNORE_STRING: strref = (LPCWSTR)pColumn->pADsValues[iValue].CaseIgnoreString; break; case ADSTYPE_DN_STRING: strref = (LPCWSTR)pColumn->pADsValues[iValue].DNString; break; default: return FALSE; } return TRUE; }
BOOL ColumnExtractString( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { return ColumnExtractStringValue( strref, pCookie, pColumn, 0 ); }
BOOL ColumnExtractElementFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn, long lElement, IN DWORD iValue = 0);
BOOL ColumnExtractElementFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn, long lElement, IN DWORD iValue) { if (pColumn == NULL) { return FALSE; }
BOOL fRetval = FALSE; CString str; CComBSTR bstr; HRESULT hr = S_OK; do { // false loop
if ( !ColumnExtractStringValue( str, pCookie, pColumn, iValue ) || str.IsEmpty() ) { strref.Empty(); fRetval = TRUE; break; } CPathCracker pathCracker; hr = pathCracker.Set(const_cast<BSTR>((LPCTSTR)str), ADS_SETTYPE_DN); if ( FAILED(hr) ) break; // no need to reset this
hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY); if ( FAILED(hr) ) break; hr = pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF); if ( FAILED(hr) ) break; hr = pathCracker.GetElement(lElement, &bstr); strref = bstr; fRetval = TRUE; } while (FALSE); // false loop
return fRetval; }
BOOL ColumnExtractLeafFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { return ColumnExtractElementFromDN( strref, pCookie, pColumn, 0 ); }
BOOL ColumnExtractParentFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { return ColumnExtractElementFromDN( strref, pCookie, pColumn, 1 ); }
BOOL ColumnExtractGreatGrandparentFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { return ColumnExtractElementFromDN( strref, pCookie, pColumn, 3 ); }
BOOL ColumnExtractConnectionDisplayName( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL) { return FALSE; }
ADS_INTEGER adsint = 0; switch (pColumn->dwADsType) { case ADSTYPE_INTEGER: adsint = pColumn->pADsValues->Integer; break; default: // no value, let it stay 0
break; } if (NTDSCONN_OPT_IS_GENERATED & adsint) { strref.LoadString (IDS_CONNECTION_KCC_GENERATED); } else { strref = pCookie->GetName(); } return TRUE; }
BOOL ColumnExtractAttribute( OUT CString& strref, IN CDSCookie*, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL) { return FALSE; }
switch (pColumn->dwADsType) { case ADSTYPE_DN_STRING : strref = pColumn->pADsValues->DNString; break;
case ADSTYPE_CASE_EXACT_STRING : strref = pColumn->pADsValues->CaseExactString; break;
case ADSTYPE_CASE_IGNORE_STRING: strref = pColumn->pADsValues->CaseIgnoreString; break;
case ADSTYPE_PRINTABLE_STRING : strref = pColumn->pADsValues->PrintableString; break;
case ADSTYPE_NUMERIC_STRING : strref = pColumn->pADsValues->NumericString; break;
case ADSTYPE_OBJECT_CLASS : strref = pColumn->pADsValues->ClassName; break;
case ADSTYPE_BOOLEAN : strref = ((DWORD)pColumn->pADsValues->Boolean) ? L"TRUE" : L"FALSE"; break;
case ADSTYPE_INTEGER : strref.Format(L"%d", (DWORD) pColumn->pADsValues->Integer); break;
case ADSTYPE_OCTET_STRING : { CString sOctet = L""; BYTE b; for ( DWORD idx=0; idx<pColumn->pADsValues->OctetString.dwLength; idx++) { b = ((BYTE *)pColumn->pADsValues->OctetString.lpValue)[idx]; sOctet.Format(L"0x%02x ", b); strref += sOctet; } } break;
case ADSTYPE_UTC_TIME: { PTSTR ptszDate = NULL; int cchDate = 0; SYSTEMTIME st = {0};
if (!SystemTimeToTzSpecificLocalTime(NULL, &pColumn->pADsValues->UTCTime, &st)) { strref = L""; return TRUE; } cchDate = GetDateFormat(LOCALE_USER_DEFAULT, 0 , &st, NULL, ptszDate, 0); ptszDate = (PTSTR)malloc(sizeof(TCHAR) * cchDate); if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, ptszDate, cchDate)) { strref = ptszDate; } else { strref = L""; } free(ptszDate);
PTSTR ptszTime = NULL;
cchDate = GetTimeFormat(LOCALE_USER_DEFAULT, 0 , &st, NULL, ptszTime, 0); ptszTime = (PTSTR)malloc(sizeof(TCHAR) * cchDate); if (ptszTime != NULL) { if (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, ptszTime, cchDate)) { strref += _T(" ") + CString(ptszTime); } else { strref += _T(""); } free(ptszTime); } else { strref = _T(""); } } break;
default : ASSERT(FALSE); break; }
return TRUE; }
BOOL _ColumnCrackDN( OUT CString& strref, IN LPCTSTR lpcszDN, IN CRACK_NAME_OPR RequestedOpr) { PWSTR pwzName = NULL; HRESULT hr = CrackName(const_cast<PTSTR>(lpcszDN), &pwzName, RequestedOpr, NULL); if (SUCCEEDED(hr)) { if (GET_OBJ_CAN_NAME_EX == RequestedOpr) { LPTSTR ptzCanName = wcschr( pwzName, _T('\n') ); if (NULL != ptzCanName) strref = ptzCanName+1; else strref.Empty(); } else { strref = pwzName; } LocalFreeStringW(&pwzName); } else { strref.Empty(); } return TRUE; }
BOOL ColumnExtractNameFromSID( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN) { return _ColumnCrackDN( strref, pCookie->GetPath(), GET_OBJ_CAN_NAME ); }
BOOL ColumnExtractCanonicalNameFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL) { return FALSE; }
CString str; if ( !ColumnExtractString( str, pCookie, pColumn ) || str.IsEmpty() ) { strref.Empty(); return TRUE; }
return _ColumnCrackDN( strref, str, GET_OBJ_CAN_NAME_EX ); }
BOOL ColumnExtractDomainFromDN( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL) { return FALSE; }
CString str; if ( !ColumnExtractString( str, pCookie, pColumn ) || str.IsEmpty() ) { strref.Empty(); return TRUE; }
return _ColumnCrackDN( strref, str, GET_DNS_DOMAIN_NAME ); }
int _cdecl _qsort_CompareColumns(const void * elem1, const void * elem2) { PADSVALUE p1 = (PADSVALUE)elem1; PADSVALUE p2 = (PADSVALUE)elem2; if (!p1 || !p2 || !p1->DNString || !p2->DNString) return 0; return wcscmp( p1->DNString, p2->DNString ); }
BOOL ColumnExtractLeafList( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL) { return FALSE; }
// alphabetical order
qsort( pColumn->pADsValues, pColumn->dwNumValues, sizeof(ADSVALUE), _qsort_CompareColumns );
CString strSeparator; strSeparator.LoadString(IDS_SEPARATOR); for (DWORD iValue = 0; iValue < pColumn->dwNumValues; iValue++) { CString strTransport; if ( !ColumnExtractElementFromDN( strTransport, pCookie, pColumn, 0, iValue) ) return FALSE; if (0 < iValue) strref += strSeparator; strref += strTransport; }
return TRUE; }
BOOL _ColumnCrackFRS( OUT CString& strref, IN CDSCookie* pCookie, IN CRACK_NAME_OPR RequestedOpr) { CDSCookieInfoConnection* pExtraInfo = NULL; if ( NULL == pCookie || _wcsicmp( pCookie->GetClass(), L"nTDSConnection" ) || NULL == (pExtraInfo = (CDSCookieInfoConnection*)pCookie->GetExtraInfo()) || pExtraInfo->GetClass() != CDSCookieInfoBase::connection || pExtraInfo->m_strFRSComputerReference.IsEmpty() ) { strref.Empty(); return TRUE; }
return _ColumnCrackDN( strref, pExtraInfo->m_strFRSComputerReference, RequestedOpr ); }
BOOL ColumnExtractFRSComputer( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN) { return _ColumnCrackFRS( strref, pCookie, GET_OBJ_CAN_NAME_EX ); }
BOOL ColumnExtractFRSDomain( OUT CString& strref, IN CDSCookie* pCookie, IN PADS_SEARCH_COLUMN) { return _ColumnCrackFRS( strref, pCookie, GET_DNS_DOMAIN_NAME ); }
// JonN 10/22/01 483649
BOOL ColumnExtractReplInterval( OUT CString& strref, IN CDSCookie*, IN PADS_SEARCH_COLUMN pColumn) { if (pColumn == NULL || pColumn->dwADsType != ADSTYPE_INTEGER) { return FALSE; } DWORD dwCost = pColumn->pADsValues->Integer; if (dwCost < 15) dwCost = 15;
strref.Format(L"%d", dwCost);
return TRUE; }
ATTRIBUTE_COLUMN colName = { ATTR_COLTYPE_NAME, IDS_COLUMN_NAME, //column header
100, //col. width
NULL, //ldap attr. name
NULL }; //extract fn()
ATTRIBUTE_COLUMN colClass= { ATTR_COLTYPE_CLASS, IDS_COLUMN_TYPE, //column header
100, //col. width
NULL, //ldap attr. name
NULL }; //extract fn()
ATTRIBUTE_COLUMN colDesc = { ATTR_COLTYPE_DESC, IDS_COLUMN_DESCRIPTION, //column header
150, //col. width
NULL, //ldap attr. name
NULL }; //extract fn()
ATTRIBUTE_COLUMN colSite = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_SITE, //column header
100, //col. width
L"siteObject", //ldap attr. name
ColumnExtractLeafFromDN }; //extract fn()
ATTRIBUTE_COLUMN colLocation = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_LOCATION, //column header
150, //col. width
L"location", //ldap attr. name
NULL }; //extract fn()
ATTRIBUTE_COLUMN colDomain = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_DOMAIN, //column header
150, //col. width
L"serverReference", //ldap attr. name
ColumnExtractDomainFromDN }; //extract fn()
ATTRIBUTE_COLUMN colBridgehead = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_BRIDGEHEAD, //column header
150, //col. width
L"bridgeheadTransportList", //ldap attr. name
ColumnExtractLeafList }; //extract fn()
ATTRIBUTE_COLUMN colReplicaComputer = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_COMPUTER, //column header
100, //col. width
L"fRSComputerReference", //ldap attr. name
ColumnExtractCanonicalNameFromDN }; //extract fn()
ATTRIBUTE_COLUMN colReplicaDomain = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_DOMAIN, //column header
150, //col. width
L"fRSComputerReference", //ldap attr. name
ColumnExtractDomainFromDN }; //extract fn()
ATTRIBUTE_COLUMN colFromFRSComputer = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_FROM_COMPUTER, //column header
100, //col. width
L"fromServer", //ldap attr. name
ColumnExtractFRSComputer }; //extract fn()
ATTRIBUTE_COLUMN colFromFRSDomain = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_FROM_DOMAIN, //column header
150, //col. width
L"fromServer", //ldap attr. name
ColumnExtractFRSDomain }; //extract fn()
ATTRIBUTE_COLUMN colConnectionName={ ATTR_COLTYPE_SPECIAL, IDS_COLUMN_NAME, //column header
150, //col. width
L"options", //ldap attr. name
ColumnExtractConnectionDisplayName}; //extract fn()
ATTRIBUTE_COLUMN colFromServer={ ATTR_COLTYPE_SPECIAL, IDS_COLUMN_FROM_SERVER, //column header
100, //col. width
L"fromServer", //ldap attr. name
ColumnExtractParentFromDN }; //extract fn()
ATTRIBUTE_COLUMN colFromSite={ ATTR_COLTYPE_SPECIAL, IDS_COLUMN_FROM_SITE, //column header
100, //col. width
L"fromServer", //ldap attr. name
ColumnExtractGreatGrandparentFromDN }; //extract fn()
ATTRIBUTE_COLUMN colCost = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_COST, //column header
75, //col. width
L"cost", //ldap attr. name
ColumnExtractAttribute}; //extract fn()
ATTRIBUTE_COLUMN colReplInterval = { ATTR_COLTYPE_SPECIAL, IDS_COLUMN_REPLINTERVAL, //column header
150, //col. width
L"replInterval", //ldap attr. name
ColumnExtractReplInterval}; // JonN 10/22/01 483649
ATTRIBUTE_COLUMN colNameFromSID={ ATTR_COLTYPE_SPECIAL, IDS_COLUMN_READABLE_NAME, // column header
100, // column width
L"container", ColumnExtractNameFromSID }; // extract fn()
ATTRIBUTE_COLUMN colGenericSpecial={ ATTR_COLTYPE_SPECIAL, 0, // resource id 0 means load it from the special column array
50, NULL, ColumnExtractAttribute };
ATTRIBUTE_COLUMN colModifiedTime={ ATTR_COLTYPE_MODIFIED_TIME, 0, 50, NULL, ColumnExtractAttribute };
SPECIAL_COLUMN g_specialCols[] = { { IDS_COLUMN_BUSINESS_PHONE, L"telephoneNumber", 100 }, { IDS_COLUMN_CITY, L"l", 150 }, { IDS_COLUMN_COMPANY, L"company", 150 }, { IDS_COLUMN_COUNTRY, L"c", AUTO_WIDTH }, // Default to the width of the header string
{ IDS_COLUMN_DEPARTMENT, L"department", 150 }, { IDS_COLUMN_DISPLAY_NAME, L"displayName", 100 }, { IDS_COLUMN_SAM_ACCOUNT_NAME, L"sAMAccountName", 120 }, { IDS_COLUMN_MAIL, L"mail", 100 }, { IDS_COLUMN_ALIAS_NAME, L"mailNickname", 175 }, { IDS_COLUMN_HOME_MDB, L"homeMDB", 100 }, { IDS_COLUMN_FIRST_NAME, L"givenName", 100 }, { IDS_COLUMN_IMHOMEURL, L"msExchIMPhysicalURL", 170 }, { IDS_COLUMN_IMURL, L"msExchIMMetaPhysicalURL", 140 }, { IDS_COLUMN_LAST_NAME, L"sn", 100 }, { IDS_COLUMN_MODIFIED, L"whenChanged", 130 }, { IDS_COLUMN_OFFICE, L"physicalDeliveryOfficeName", 100 }, { IDS_COLUMN_STATE, L"st", 100 }, { IDS_COLUMN_TARGET_ADDRESS , L"targetAddress", 100 }, { IDS_COLUMN_TITLE, L"title", 100 }, { IDS_COLUMN_UPN, L"userPrincipalName", 200 }, { IDS_COLUMN_TEXTENCODEORADDRESS, L"textEncodedORAddress", 130 }, { IDS_COLUMN_ZIP_CODE, L"postalCode", 100 } };
PATTRIBUTE_COLUMN colsSubnetContainer[6] = { &colName, &colSite, &colLocation, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsSitesContainer[5] = { &colName, &colLocation, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsServersContainer[6] = { &colName, &colDomain, &colBridgehead, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsNTDSDSA[6] = { &colConnectionName, &colFromServer, &colFromSite, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsInterSiteTransport[6] = { &colName, &colClass, &colDesc, &colCost, &colReplInterval, NULL }; PATTRIBUTE_COLUMN colsFRSReplicaSet[6] = { &colName, &colReplicaComputer, &colReplicaDomain, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsFRSMember[6] = { &colConnectionName, &colFromFRSComputer, &colFromFRSDomain, &colClass, &colDesc, NULL }; PATTRIBUTE_COLUMN colsFSP[5] = { &colName, &colClass, &colDesc, &colNameFromSID, NULL }; PATTRIBUTE_COLUMN colsSpecial[26] = { &colName, &colClass, &colDesc, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colModifiedTime, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, &colGenericSpecial, NULL }; PATTRIBUTE_COLUMN colsDefault[4] = { &colName, &colClass, &colDesc, NULL };
// currently, any additional columns must be of string type
COLUMNS_FOR_CLASS g_colarray[] = { { _T("subnetContainer"), _T("subnetContainer"), 5, colsSubnetContainer }, { _T("sitesContainer"), _T("sitesContainer"), 4, colsSitesContainer}, { _T("serversContainer"), _T("serversContainer"), 5, colsServersContainer}, { _T("nTDSDSA"), _T("nTDSDSA"), 5, colsNTDSDSA }, { _T("interSiteTransport"), _T("interSiteTransport"), 5, colsInterSiteTransport}, { _T("nTFRSReplicaSet"), _T("nTFRSReplicaSet"), 5, colsFRSReplicaSet }, { _T("nTFRSMember"), _T("nTFRSMember"), 5, colsFRSMember }, { _T("ForeignSecurityPrincipals"), _T("ForeignSecurityPrincipals"), 4, colsFSP }, { SPECIAL_COLUMN_SET, SPECIAL_COLUMN_SET, 25, colsSpecial }, { NULL, DEFAULT_COLUMN_SET, 3, colsDefault } // empty one at the end; must be here
};
/*
COLUMNS_FOR_CLASS* GetColumnsForClass( LPCTSTR i_pcszLdapClassName ) { if (NULL == i_pcszLdapClassName) i_pcszLdapClassName = L""; COLUMNS_FOR_CLASS* pColsForClass; for (pColsForClass = g_colarray; NULL != pColsForClass->pcszLdapClassName; pColsForClass++) { if ( 0 == _wcsicmp(i_pcszLdapClassName, pColsForClass->pcszLdapClassName) ) { break; } } ASSERT( NULL != pColsForClass ); return pColsForClass; } */
////////////////////////////////////////////////////////////////////////////////////
// CDSColumnSet
CDSColumnSet* CDSColumnSet::CreateColumnSet(PCOLUMNS_FOR_CLASS pColsForClass, SnapinType snapinType) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Using the class name as both the column id and the class name for the column set
CDSColumnSet* pNewColumnSet = new CDSColumnSet(pColsForClass->pcszColumnID, pColsForClass->pcszLdapClassName); if (!pNewColumnSet) { TRACE(L"Unable to allocate memory for new column set\n"); ASSERT(FALSE); return 0; }
UINT nUserColCount = 0; for (int idx = 0; idx < pColsForClass->nColumns; idx ++) { CString cstrHeader; CDSColumn* pNewColumn;
if (pColsForClass->apColumns[idx]->resid == 0) { // Don't add the exchange special columns in DSSite
if (snapinType == SNAPINTYPE_SITE) continue;
cstrHeader.LoadString(g_specialCols[nUserColCount].resid); pNewColumn = new CDSColumn((LPCWSTR)cstrHeader, LVCFMT_LEFT, g_specialCols[nUserColCount].iColumnWidth, idx, FALSE, g_specialCols[nUserColCount].ptszAttribute, pColsForClass->apColumns[idx]->coltype, pColsForClass->apColumns[idx]->pfnExtract); nUserColCount++; } else { cstrHeader.LoadString(pColsForClass->apColumns[idx]->resid); pNewColumn = new CDSColumn((LPCWSTR)cstrHeader, LVCFMT_LEFT, pColsForClass->apColumns[idx]->iColumnWidth, idx, TRUE, pColsForClass->apColumns[idx]->pcszAttribute, pColsForClass->apColumns[idx]->coltype, pColsForClass->apColumns[idx]->pfnExtract); } ASSERT(pNewColumn); if (pNewColumn) { pNewColumnSet->AddColumn(pNewColumn); } } return pNewColumnSet; }
CDSColumnSet* CDSColumnSet::CreateColumnSetFromString(LPCWSTR lpszClassName, SnapinType snapinType) { COLUMNS_FOR_CLASS* pColsForClass; for (pColsForClass = g_colarray; pColsForClass->pcszLdapClassName != NULL; pColsForClass++) { if (lpszClassName != NULL && pColsForClass->pcszLdapClassName != NULL) { if (wcscmp(pColsForClass->pcszLdapClassName, lpszClassName) == 0) { break; } } } return CDSColumnSet::CreateColumnSet(pColsForClass, snapinType); }
CDSColumnSet* CDSColumnSet::CreateDescriptionColumnSet() { AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString szNameHeader; VERIFY(szNameHeader.LoadString(IDS_COLUMN_NAME)); CColumn* pNameColumn = new CColumn(szNameHeader, LVCFMT_LEFT, 100, 0, TRUE); if (pNameColumn == NULL) { return NULL; }
CString szDescriptionHeader; VERIFY(szDescriptionHeader.LoadString(IDS_COLUMN_DESCRIPTION)); CColumn* pDescColumn = new CColumn(szDescriptionHeader, LVCFMT_LEFT, 150, 1, TRUE); if (pDescColumn == NULL) { if (pNameColumn) { delete pNameColumn; } return NULL; }
CDSColumnSet* pDSColumnSet = new CDSColumnSet(L"***---Description Set---***", NULL); if (pDSColumnSet == NULL) { if (pNameColumn) { delete pNameColumn; } if (pDescColumn) { delete pDescColumn; } return NULL; }
pDSColumnSet->AddColumn(pNameColumn); pDSColumnSet->AddColumn(pDescColumn); return pDSColumnSet; }
CDSColumnSet* CDSColumnSet::CreateColumnSetFromDisplaySpecifiers(PCWSTR pszClassName, SnapinType snapinType, MyBasePathsInfo* pBasePathsInfo) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK; CDSColumnSet* pNewColumnSet = NULL; BOOL bDefaultHardcodedSet = FALSE;
//
// Using the class name as both the column id and the class name for the column set
//
pNewColumnSet = new CDSColumnSet(pszClassName, pszClassName); if (pNewColumnSet != NULL) { //
// Start with the hardcoded columns
//
COLUMNS_FOR_CLASS* pColsForClass; for (pColsForClass = g_colarray; pColsForClass->pcszLdapClassName != NULL; pColsForClass++) { if (pszClassName != NULL && pColsForClass->pcszLdapClassName != NULL) { if (wcscmp(pColsForClass->pcszLdapClassName, pszClassName) == 0) { break; } } }
if (pColsForClass != NULL) { if (wcscmp(pColsForClass->pcszColumnID, DEFAULT_COLUMN_SET) == 0) { bDefaultHardcodedSet = TRUE; }
UINT nUserColCount = 0; for (int idx = 0; idx < pColsForClass->nColumns; idx ++) { CString cstrHeader; CDSColumn* pNewColumn;
if (pColsForClass->apColumns[idx]->resid == 0) { // Don't add the exchange special columns in DSSite
if (snapinType == SNAPINTYPE_SITE) continue;
cstrHeader.LoadString(g_specialCols[nUserColCount].resid); pNewColumn = new CDSColumn((LPCWSTR)cstrHeader, LVCFMT_LEFT, g_specialCols[nUserColCount].iColumnWidth, idx, FALSE, g_specialCols[nUserColCount].ptszAttribute, pColsForClass->apColumns[idx]->coltype, pColsForClass->apColumns[idx]->pfnExtract); nUserColCount++; } else { cstrHeader.LoadString(pColsForClass->apColumns[idx]->resid); pNewColumn = new CDSColumn((LPCWSTR)cstrHeader, LVCFMT_LEFT, pColsForClass->apColumns[idx]->iColumnWidth, idx, TRUE, pColsForClass->apColumns[idx]->pcszAttribute, pColsForClass->apColumns[idx]->coltype, pColsForClass->apColumns[idx]->pfnExtract); } pNewColumnSet->AddColumn(pNewColumn); } }
//
// Now add the DS extraColumns
//
CStringList strListColumns; hr = GetDisplaySpecifierProperty(pszClassName, L"extraColumns", pBasePathsInfo, strListColumns); if (FAILED(hr)) { hr = GetDisplaySpecifierProperty(pszClassName, L"extraColumns", pBasePathsInfo, strListColumns, true); }
if (SUCCEEDED(hr)) { UINT nColCount = static_cast<UINT>(pNewColumnSet->GetCount()); POSITION pos = strListColumns.GetHeadPosition(); while (pos != NULL) { CDSColumn* pNewColumn = NULL;
CString szExtraColumn = strListColumns.GetNext(pos); if (!szExtraColumn.IsEmpty()) { //
// Parse the 5-tuple to get the elements to make the column
//
CString szAttributeName; CString szColHeader; BOOL bVisible = TRUE; int iColumnWidth = 0; GUID guidCallbackInterface; // unused. Reserved for future callback interface
PWSTR pszTemp = new WCHAR[szExtraColumn.GetLength() + 1]; if (pszTemp != NULL) { wcscpy(pszTemp, (LPCWSTR)szExtraColumn);
PWSTR pszVisible = NULL; PWSTR pszColumnWidth = NULL; PWSTR pszGuidCallback = NULL;
PWSTR pszNextTuple = pszTemp;
pszNextTuple = wcstok(pszTemp, L","); if (pszNextTuple != NULL) { szAttributeName = pszNextTuple; }
pszNextTuple = wcstok(NULL, L","); if (pszNextTuple != NULL) { szColHeader = pszNextTuple; }
pszNextTuple = wcstok(NULL, L","); if (pszNextTuple != NULL) { pszVisible = pszNextTuple; int i = _wtoi(pszVisible); if (i == 0) { bVisible = FALSE; } else { bVisible = TRUE; } }
pszNextTuple = wcstok(NULL, L","); if (pszNextTuple != NULL) { pszColumnWidth = pszNextTuple; iColumnWidth = _wtoi(pszColumnWidth); }
pszNextTuple = wcstok(NULL, L","); if (pszNextTuple != NULL) { pszGuidCallback = pszNextTuple; HRESULT hr2 = ::CLSIDFromString(pszGuidCallback, &guidCallbackInterface); if (FAILED(hr2)) { memset(&guidCallbackInterface, 0, sizeof(GUID)); } }
// NTRAID#NTBUG9-702278-2002/09/11-artm
// Need to intelligently get the type of the column's data.
// If the type of the attribute is UTC time, we need to
// pass the time column type to make sure the correct sorting
// method is used.
ATTRIBUTE_COLUMN_TYPE columnType = ATTR_COLTYPE_SPECIAL;
ADSTYPE attributeType = ADSTYPE_INVALID; hr = pBasePathsInfo->GetAttributeADsType(szAttributeName, attributeType); if (SUCCEEDED(hr) && attributeType == ADSTYPE_UTC_TIME) { columnType = ATTR_COLTYPE_MODIFIED_TIME; }
//
// Create the column with the retrieved data
//
pNewColumn = new CDSColumn((PCWSTR)szColHeader, LVCFMT_LEFT, iColumnWidth, nColCount++, bVisible, (PCWSTR)szAttributeName, columnType, ColumnExtractAttribute); // this will be changed to the interface when that is implemented
}
delete[] pszTemp; } if (pNewColumn != NULL) { pNewColumnSet->AddColumn(pNewColumn); } } } }
//
// If we failed to retrieve columns from the display specifier
// and we hit the default hardcoded set but we were not asking
// for the default hardcoded set and the snapin isn't the sites snapin
// Then we delete the column set and we will pickup the actual default
// column set since we are returning NULL
//
if (FAILED(hr) && bDefaultHardcodedSet && _wcsicmp(pszClassName, DEFAULT_COLUMN_SET) != 0 && snapinType != SNAPINTYPE_SITE) { delete pNewColumnSet; pNewColumnSet = NULL; } return pNewColumnSet; }
HRESULT CColumnSet::Save(IStream* pStm) { // save the column set ID
HRESULT hr = SaveStringHelper(GetColumnID(), pStm); if (FAILED(hr)) return hr; // save the # of visible columns and
// the indexes of the visible columns
// NOTICE: we use MMC's MMC_VISIBLE_COLUMNS format to be consitent
// and to be able to read back easily
INT nTotalCols = GetNumCols();
// allocate a bit more than needed (i.e. total # of columns)
MMC_VISIBLE_COLUMNS* pVisibleColumns = (MMC_VISIBLE_COLUMNS*)new BYTE[sizeof(MMC_VISIBLE_COLUMNS) + (sizeof(INT)*(nTotalCols-1))];
if (!pVisibleColumns) { return E_OUTOFMEMORY; } pVisibleColumns->nVisibleColumns = 0; int iIndex = 0; for (POSITION pos = GetHeadPosition(); (pos != NULL); ) { CColumn* pCol = GetNext(pos); if (pCol->IsVisible()) { pVisibleColumns->rgVisibleCols[pVisibleColumns->nVisibleColumns] = iIndex; (pVisibleColumns->nVisibleColumns)++; } iIndex++; }
// save the right length of the struct
ULONG nByteCount = sizeof(MMC_VISIBLE_COLUMNS) + (sizeof(INT)*(pVisibleColumns->nVisibleColumns-1)); ULONG nBytesWritten; hr = pStm->Write((void*)pVisibleColumns, nByteCount, &nBytesWritten); if (SUCCEEDED(hr)) { if (nBytesWritten < nByteCount) { hr = STG_E_CANTSAVE; } }
delete[] pVisibleColumns; pVisibleColumns = 0; return hr; }
HRESULT CColumnSet::Load(IStream* pStm) { // NOTICE: we already loaded the column set ID and
// got a columns set that matches this
// read the # of visible columns
DWORD dwColCount = 0; INT nCountMax = GetNumCols(); HRESULT hr = LoadDWordHelper(pStm, &dwColCount); if (FAILED(hr) || ((INT)dwColCount > nCountMax)) return E_FAIL;
// allocate some space for the array past the struct
MMC_VISIBLE_COLUMNS* pVisibleColumns = (MMC_VISIBLE_COLUMNS*)new BYTE[sizeof(MMC_VISIBLE_COLUMNS) + (sizeof(INT)*(dwColCount-1))]; if (!pVisibleColumns) { return E_OUTOFMEMORY; } pVisibleColumns->nVisibleColumns = (INT)dwColCount;
// load the array of indexes of visible columns
ULONG nBytesRead;
ULONG nByteCount = sizeof(DWORD)*dwColCount; INT* pArr = pVisibleColumns->rgVisibleCols; hr = pStm->Read(pArr, nByteCount, &nBytesRead); if (SUCCEEDED(hr)) { if (nBytesRead < nByteCount) { hr = E_FAIL; } else { // update columns
AddVisibleColumns(pVisibleColumns); } } delete[] pVisibleColumns; pVisibleColumns = 0; return S_OK; }
/////////////////////////////////////////////////////////////////////////////////////////
// CColumnSetList
void CColumnSetList::Initialize(SnapinType snapinType, MyBasePathsInfo* pBasePathsInfo) { m_pBasePathsInfo = pBasePathsInfo; m_snapinType = snapinType; }
//
// Find the column set given a column set ID
//
CColumnSet* CColumnSetList::FindColumnSet(LPCWSTR lpszColumnID) { POSITION pos = GetHeadPosition(); while (pos != NULL) { CColumnSet* pTempSet = GetNext(pos); ASSERT(pTempSet != NULL);
LPCWSTR lpszTempNodeID = pTempSet->GetColumnID();
if (wcscmp(lpszTempNodeID, lpszColumnID) == 0) { return pTempSet; } } CColumnSet* pNewColSet = CDSColumnSet::CreateColumnSetFromDisplaySpecifiers(lpszColumnID, m_snapinType, m_pBasePathsInfo); if (pNewColSet != NULL) { AddTail(pNewColSet); return pNewColSet; } return GetSpecialColumnSet(); }
CColumnSet* CColumnSetList::GetDefaultColumnSet() { if (m_pDefaultColumnSet == NULL) { m_pDefaultColumnSet = CDSColumnSet::CreateColumnSetFromDisplaySpecifiers(DEFAULT_COLUMN_SET, m_snapinType, m_pBasePathsInfo); } return m_pDefaultColumnSet; }
CColumnSet* CColumnSetList::GetSpecialColumnSet() { if (m_pSpecialColumnSet == NULL) { m_pSpecialColumnSet = CDSColumnSet::CreateColumnSetFromString(SPECIAL_COLUMN_SET, m_snapinType); }
ASSERT(m_pSpecialColumnSet);
return m_pSpecialColumnSet; }
HRESULT CColumnSetList::Save(IStream* pStm) { // save # of items in the list
DWORD dwCount = (DWORD)GetCount(); // list count plus default column set
if (m_pDefaultColumnSet) { ++dwCount; }
// And special column set
if (m_pSpecialColumnSet) { ++dwCount; }
HRESULT hr = SaveDWordHelper(pStm, dwCount); if (FAILED(hr)) return hr;
// save columnset list
for (POSITION pos = GetHeadPosition(); pos != NULL; ) { CColumnSet* pTempSet = GetNext(pos);
if (pTempSet == NULL) { ASSERT(pTempSet != NULL); continue; }
hr = pTempSet->Save(pStm); if (FAILED(hr)) return hr; }
// save default column set
if (m_pDefaultColumnSet != NULL) { hr = m_pDefaultColumnSet->Save(pStm); }
// save the special column set
if (m_pSpecialColumnSet) { hr = m_pSpecialColumnSet->Save(pStm); } return hr; }
HRESULT CColumnSetList::Load(IStream* pStm) { // load # of items in the list
DWORD dwLoadCount; HRESULT hr = LoadDWordHelper(pStm, &dwLoadCount); if (FAILED(hr)) return hr;
// load column list
CString szColumnID; for (DWORD iColSet = 0; iColSet< dwLoadCount; iColSet++) { // load the string with the name of the column set
hr = LoadStringHelper(szColumnID, pStm); if (FAILED(hr)) return hr; ASSERT(!szColumnID.IsEmpty());
CColumnSet* pColumnSet = 0; if (szColumnID.CompareNoCase(DEFAULT_COLUMN_SET) == 0) { pColumnSet = GetDefaultColumnSet(); } else if (szColumnID.CompareNoCase(SPECIAL_COLUMN_SET) == 0) { pColumnSet = GetSpecialColumnSet(); } else { pColumnSet = FindColumnSet(szColumnID); }
if (pColumnSet != NULL) { hr = pColumnSet->Load(pStm); if (FAILED(hr)) { return hr; } } }
return S_OK; }
|