2025-11-28 00:35:46 +09:00

975 lines
20 KiB
C++

//----------------------------------------------------------------------------
//
// Microsoft Active Directory 2.5 Sample Code
//
// Copyright (C) Microsoft Corporation, 1996 - 2000
//
// File: DirectorySearch.cpp
//
// Contents: IDirectorySearch usage
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "ADQI.h"
#include "DirectorySearch.h"
#include "ads.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDlgIDirectorySearch dialog
CDlgIDirectorySearch::CDlgIDirectorySearch(LPUNKNOWN pUnk, CWnd* pParent /*=NULL*/)
: CDialog(CDlgIDirectorySearch::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlgIDirectorySearch)
m_sFilter = _T("");
m_bEnableFilter = FALSE;
m_nTimeOut = 0;
m_bCacheResult = FALSE;
m_nPageSize = 0;
m_sSortOn = _T("");
m_nTimeLimit = 0;
m_nSizeLimit = 0;
m_bAsynch = FALSE;
m_bAttrib = FALSE;
m_nDeref = -1;
//}}AFX_DATA_INIT
HRESULT hr;
m_pSearch = NULL;
hr = pUnk->QueryInterface( IID_IDirectorySearch, (void **) &m_pSearch );
if ( !SUCCEEDED(hr) )
{
AfxMessageBox(_T("Fatal Error! QI for IDirectorySearch failed"));
return;
}
pUnk->Release();
}
CDlgIDirectorySearch::~CDlgIDirectorySearch()
{
if ( m_pSearch )
{
m_pSearch->Release();
}
}
void CDlgIDirectorySearch::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgIDirectorySearch)
DDX_Control(pDX, IDC_ATTRIBUTE, m_cAttrList);
DDX_Control(pDX, IDC_LISTVIEW, m_cListView);
DDX_Control(pDX, IDC_CHASEREFERRAL, m_cChaseReferrals);
DDX_Control(pDX, IDC_CACHERESULTS, m_cCacheResult);
DDX_Control(pDX, IDC_SEARCHSCOPE, m_CADsSearchScope);
DDX_Control(pDX, IDC_ENABLED, m_cEnableFilter);
DDX_Control(pDX, IDC_EXECUTE, m_cExecute);
DDX_Control(pDX, IDC_FILTER, m_cFilter);
DDX_Text(pDX, IDC_FILTER, m_sFilter);
DDX_Check(pDX, IDC_ENABLED, m_bEnableFilter);
DDX_Text(pDX, IDC_TIMEOUT, m_nTimeOut);
DDX_Check(pDX, IDC_CACHERESULTS, m_bCacheResult);
DDX_Text(pDX, IDC_PAGESIZE, m_nPageSize);
DDX_Text(pDX, IDC_SORTON, m_sSortOn);
DDX_Text(pDX, IDC_TIMELIMIT, m_nTimeLimit);
DDX_Text(pDX, IDC_SIZELIMIT, m_nSizeLimit);
DDX_Check(pDX, IDC_ASYNCH, m_bAsynch);
DDX_Check(pDX, IDC_ATTRIBONLY, m_bAttrib);
DDX_CBIndex(pDX, IDC_DEREF, m_nDeref);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgIDirectorySearch, CDialog)
//{{AFX_MSG_MAP(CDlgIDirectorySearch)
ON_BN_CLICKED(IDC_EXECUTE, OnExecute)
ON_EN_CHANGE(IDC_FILTER, OnChangeFilter)
ON_BN_CLICKED(IDC_ENABLED, OnEnabled)
ON_NOTIFY(NM_DBLCLK, IDC_LISTVIEW, OnDblClickListView)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgIDirectorySearch message handlers
//
////////////////////////////////////////////
// OnExecute
// Demonstrate:
// IDirectorySearch::ExecuteSearch
// IDirectorySearch::GetNextRow
// IDirectorySearch::GetColumn
// IDirectorySearch::SetSearchPreference
//
/////////////////////////////////////////////
void CDlgIDirectorySearch::OnExecute()
{
ASSERT( m_pSearch );
CWaitCursor wait;
UpdateData(TRUE); // Get data from the Dialog Box
HRESULT hr;
ADS_SEARCH_HANDLE hSearch;
ADS_SEARCH_COLUMN col;
CString s;
int idx=0;
int nCount;
LPWSTR *pszAttr=NULL;
POSITION pos;
USES_CONVERSION;
/////////////////////////////////
// Reset the Total Number
//////////////////////////////////
SetDlgItemText( IDC_TOTAL, _T(""));
/////////////////////////////////////////////
// Get the attribute list, and preparing..
///////////////////////////////////////////
CStringList sAttrList;
m_cListView.DeleteAllItems(); // Reset the UI
while( m_cListView.DeleteColumn(0))
{
;
}
//////////////////////////////////////////////////
// Preparing for attribute list
// and columns to display
CString sTemp;
m_cAttrList.GetWindowText(s);
// we need to add adspath, so that we can refer to this object later when user dblclk the item
if ( !s.IsEmpty() )
{
sTemp = s;
sTemp.MakeLower();
if ( s.Find(_T("adspath"),0) == -1 )
{
s += _T(",ADsPath");
}
}
// convert to string list for easy manipulation
StringToStringList( s, sAttrList );
nCount = sAttrList.GetCount();
idx=0;
if ( nCount )
{
pszAttr = (LPWSTR*) AllocADsMem( nCount * sizeof(LPWSTR));
pos = sAttrList.GetHeadPosition();
while ( pos != NULL )
{
s = sAttrList.GetAt(pos);
pszAttr[idx] = T2OLE(s);
sAttrList.GetNext(pos );
idx++;
}
}
else
{
nCount = -1;
}
/////////////////////////////////////////
// BEGIN Set the preferences
///////////////////////////////////////
DWORD dwCountPref = 0;
ADS_SEARCHPREF_INFO prefInfo[ MAX_SEARCH_PREF ];
ADS_SORTKEY *pSortKey = NULL;
if ( m_bEnableFilter == FALSE )
{
// Reset the preference
m_pSearch->SetSearchPreference( prefInfo, dwCountPref );
}
else // Preferences are specified
{
////////////////////////
// Timeout Pref
////////////////////////////
if ( m_nTimeOut != 0 )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_TIMEOUT;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;
prefInfo[dwCountPref].vValue.Integer = m_nTimeOut;
dwCountPref++;
}
//////////////////////////////
// Search Scope
/////////////////////////////
idx = m_CADsSearchScope.GetCurSel();
if ( idx != CB_ERR )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;
prefInfo[dwCountPref].vValue.Integer = idx;
dwCountPref++;
}
///////////////////////////////////////////////////
// Cache Result. The default is to cache the result
/////////////////////////////////////////////////
if ( !m_bCacheResult )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_BOOLEAN;
prefInfo[dwCountPref].vValue.Boolean = FALSE;
dwCountPref++;
}
//////////////////////////////////////////////////
// Page Size
///////////////////////////////////////////////////
if ( m_nPageSize > 0 )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;;
prefInfo[dwCountPref].vValue.Integer = m_nPageSize;
dwCountPref++;
}
////////////////////////////////////////////////
// Chase Referrals
///////////////////////////////////////////////
idx = m_cChaseReferrals.GetCurSel();
if ( idx != CB_ERR )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;
switch( idx )
{
case 0:
prefInfo[dwCountPref].vValue.Integer = ADS_CHASE_REFERRALS_NEVER;
break;
case 1:
prefInfo[dwCountPref].vValue.Integer = ADS_CHASE_REFERRALS_SUBORDINATE;
break;
case 2:
prefInfo[dwCountPref].vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
break;
default:
prefInfo[dwCountPref].vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
}
dwCountPref++;
}
///////////////////////////////////////////////
// Sort On
////////////////////////////////////////////////
if ( !m_sSortOn.IsEmpty() )
{
CStringList sList;
UINT nCount;
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_SORT_ON;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_PROV_SPECIFIC;
StringToStringList( m_sSortOn, sList );
nCount = sList.GetCount();
if ( nCount > 0 )
{
POSITION pos;
pos= sList.GetHeadPosition();
pSortKey = (ADS_SORTKEY *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sizeof(ADS_SORTKEY) * nCount );
idx = 0;
while( pos != NULL )
{
pSortKey[idx].pszAttrType = T2OLE(sList.GetAt(pos));
pSortKey[idx].pszReserved = NULL;
pSortKey[idx].fReverseorder =0;
// Next
idx++;
sList.GetNext( pos );
}
prefInfo[dwCountPref].vValue.ProviderSpecific.dwLength = sizeof(ADS_SORTKEY) * nCount;
prefInfo[dwCountPref].vValue.ProviderSpecific.lpValue = (LPBYTE) pSortKey;
dwCountPref++;
}
}
//////////////////////////////////////////////
// Size Limit
//////////////////////////////////////////////
if ( m_nSizeLimit > 0 )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_SIZE_LIMIT;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;
prefInfo[dwCountPref].vValue.Integer = m_nSizeLimit;
dwCountPref++;
}
//////////////////////////////////////////////////
// A Synchronous
///////////////////////////////////////////////////
if ( m_bAsynch )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_BOOLEAN;
prefInfo[dwCountPref].vValue.Integer = TRUE;
dwCountPref++;
}
/////////////////////////////////////////////////////
// Attribute Type Only
//////////////////////////////////////////////////////
if ( m_bAttrib )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_ATTRIBTYPES_ONLY;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_BOOLEAN;
prefInfo[dwCountPref].vValue.Integer = TRUE;
dwCountPref++;
}
/////////////////////////////////////////////////////
// Derefence Alias
//////////////////////////////////////////////////////
if ( m_nDeref != CB_ERR )
{
prefInfo[dwCountPref].dwSearchPref = ADS_SEARCHPREF_DEREF_ALIASES;
prefInfo[dwCountPref].vValue.dwType = ADSTYPE_INTEGER;
prefInfo[dwCountPref].vValue.Integer = m_nDeref;
dwCountPref++;
}
///////////////////////////////////////////////
// Now Set the selected preferences
//////////////////////////////////////////////
hr = m_pSearch->SetSearchPreference( prefInfo, dwCountPref );
}
/////////////////////////////////////////
// END Set the preferences
///////////////////////////////////////
////////////////////////////////////////
// Execute the Search
//////////////////////////////////////
DWORD dwCount=0;
hr = m_pSearch->ExecuteSearch(T2OLE(m_sFilter), pszAttr, nCount, &hSearch );
////////////////////////////////
//// cleanup
////////////////////////////////
if ( pszAttr )
{
FreeADsMem( pszAttr );
}
if ( pSortKey )
{
LocalFree( pSortKey );
}
if ( !SUCCEEDED(hr) )
{
AfxMessageBox(GetErrorMessage(hr));
return;
}
////////////////////////////////////////////////////////
// Enumerate the rows
////////////////////////////////////////////////////////
sAttrList.RemoveAll();
/////////////////////////////////////////////////////////
// Retrieve the column names returned from the server
///////////////////////////////////////////////////////////
LPWSTR pszColumn;
hr = m_pSearch->GetFirstRow( hSearch );
if ( !SUCCEEDED(hr) )
{
return;
}
idx=0;
while( (hr=m_pSearch->GetNextColumnName( hSearch, &pszColumn )) != S_ADS_NOMORE_COLUMNS )
{
s = OLE2T( pszColumn );
m_cListView.InsertColumn(idx, s, LVCFMT_LEFT, 150 ); // adding columns to the UI
sAttrList.AddTail(s);
FreeADsMem( pszColumn );
idx++;
}
/////////////////////////////////////////////
// Start iterating the result set
////////////////////////////////////////////
int nCol;
CStringList sValueList;
do
{
nCol=0;
pos = sAttrList.GetHeadPosition();
while( pos != NULL )
{
s = sAttrList.GetAt(pos); //column name
// Get the Name and display it in the list
hr = m_pSearch->GetColumn( hSearch, T2OLE(s), &col );
if ( SUCCEEDED(hr) )
{
s =_T("");
if ( col.dwADsType != ADSTYPE_INVALID ) // if we request for attrib only, no value will be returned
{
ADsToStringList(col.pADsValues, col.dwNumValues, sValueList );
StringListToString( sValueList, s );
}
if ( nCol )
{
m_cListView.SetItemText(0,nCol, s);
}
else
{
m_cListView.InsertItem(0, s);
}
m_pSearch->FreeColumn( &col );
}
nCol++;
sAttrList.GetNext(pos);
}
dwCount++;
/////////////////////////////
//Display the total so far
////////////////////////////////
s.Format("%ld object(s)", dwCount );
SetDlgItemText( IDC_TOTAL, s );
}
while( (hr=m_pSearch->GetNextRow( hSearch)) != S_ADS_NOMORE_ROWS );
m_pSearch->CloseSearchHandle( hSearch );
}
void CDlgIDirectorySearch::OnChangeFilter()
{
BOOL bExecEnabled;
bExecEnabled = m_cFilter.GetWindowTextLength() > 0 ? TRUE :FALSE;
m_cExecute.EnableWindow( bExecEnabled );
}
BOOL CDlgIDirectorySearch::OnInitDialog()
{
CDialog::OnInitDialog();
// Initialize to a default search
m_cFilter.SetWindowText(_T("(objectClass=*)"));
m_cAttrList.SetWindowText(_T("cn"));
OnChangeFilter();
OnEnabled();
m_cCacheResult.SetCheck( 1 );
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CDlgIDirectorySearch::OnEnabled()
{
UpdateData(TRUE);
// Enable/Disable Edit Boxes
GetDlgItem( IDC_TIMEOUT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SEARCHSCOPE )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_PAGESIZE )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SORTON )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_CHASEREFERRAL )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_TIMELIMIT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SIZELIMIT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_ASYNCH )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_CACHERESULTS )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_ATTRIBONLY )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_DEREF )->EnableWindow(m_bEnableFilter);
// Enabled/Disabled Texts
GetDlgItem( IDC_TIMEOUT_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SEARCHSCOPE_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_PAGESIZE_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SORTON_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_CHASEREFERRAL_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_TIMELIMIT_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_SIZELIMIT_TXT )->EnableWindow(m_bEnableFilter);
GetDlgItem( IDC_DEREF_TXT )->EnableWindow(m_bEnableFilter);
}
void CDlgIDirectorySearch::OnOK()
{
CDialog::OnOK();
}
void CDlgIDirectorySearch::OnDblClickListView(NMHDR* pNMHDR, LRESULT* pResult)
{
int idx;
*pResult = 0;
idx = m_cListView.GetNextItem(-1, LVNI_SELECTED);
if ( idx == -1 )
{
return;
}
CHeaderCtrl *pHeader;
int nCount;
pHeader = m_cListView.GetHeaderCtrl();
if ( !pHeader )
{
return;
}
nCount = pHeader->GetItemCount();
// Get the text
CString s;
s = m_cListView.GetItemText( idx, nCount-1 );
if ( !s.GetLength() )
{
return;
}
USES_CONVERSION;
HRESULT hr;
IUnknown *pUnk=NULL;
CString sUserName;
hr = App->ADsOpenObject( T2OLE( s ), IID_IUnknown, (void**) &pUnk );
/////////////////////////////////////
// Bring up the IADs Dialog
///////////////////////////////////////
if ( SUCCEEDED(hr) )
{
pUnk->AddRef();
CDlgIADs dlg( pUnk );
dlg.DoModal();
pUnk->Release();
}
else
{
AfxMessageBox(GetErrorMessage(hr));
}
}
////////////////////////////////////////////////////////////////////
//
// CADsSearch
// This is a convient C++ wrapper for IDirectorySearch
//
/////////////////////////////////////////////////////////////////////
CADsSearch::CADsSearch( IADs *pADs )
{
CADsSearch();
SetInterface( pADs );
}
CADsSearch::CADsSearch()
{
m_pSearch = NULL;
m_hSearch = NULL;
m_dwPrefCount = 0;
}
HRESULT CADsSearch::SetInterface( IUnknown *pUnk )
{
if ( pUnk != NULL )
{
HRESULT hr;
//////////////////////////////////////////
// Remove the current search if any
////////////////////////////////////////
if ( m_pSearch )
{
if ( m_hSearch )
{
m_pSearch->CloseSearchHandle( m_hSearch );
}
m_pSearch->Release();
}
m_pSearch = NULL;
m_hSearch = NULL;
m_dwPrefCount = 0;
hr = pUnk->QueryInterface( IID_IDirectorySearch, (LPVOID*) &m_pSearch );
pUnk->Release();
return hr;
}
return E_UNEXPECTED;
}
CADsSearch::~CADsSearch()
{
if ( m_pSearch )
{
if ( m_hSearch )
{
m_pSearch->CloseSearchHandle( m_hSearch );
}
m_pSearch->Release();
}
}
HRESULT CADsSearch::GetNextRow()
{
HRESULT hr;
if ( !m_pSearch || !m_hSearch)
{
return E_UNEXPECTED;
}
hr = m_pSearch->GetNextRow( m_hSearch );
return hr;
}
void CADsSearch::AddColumn( LPCTSTR pszColumn )
{
ASSERT( pszColumn );
m_sColumnList.AddTail( pszColumn );
}
HRESULT CADsSearch::SetScope( ADS_SCOPEENUM flag )
{
if ( !m_pSearch )
{
return E_UNEXPECTED;
}
ADS_SEARCHPREF_INFO info;
info.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
info.vValue.dwType = ADSTYPE_INTEGER;
info.vValue.Integer = flag;
return AddSearchPref( &info );
}
HRESULT CADsSearch::SetAttribOnly( BOOL bAttribOnly )
{
ADS_SEARCHPREF_INFO info;
info.dwSearchPref = ADS_SEARCHPREF_ATTRIBTYPES_ONLY;
info.vValue.dwType = ADSTYPE_BOOLEAN;
info.vValue.Integer = bAttribOnly;
return AddSearchPref( &info );
}
HRESULT CADsSearch::SetPageSize( UINT nPageSize )
{
ADS_SEARCHPREF_INFO info;
info.dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
info.vValue.dwType = ADSTYPE_INTEGER;
info.vValue.Integer = nPageSize;
return AddSearchPref( &info );
}
// TODO: More Options...
HRESULT CADsSearch::AddSearchPref( PADS_SEARCHPREF_INFO pSearchPrefs, DWORD dwNumPref )
{
PADS_SEARCHPREF_INFO pInfo;
for( UINT idx=0; idx < dwNumPref; idx++ )
{
pInfo = FindSearchPrefence( pSearchPrefs->dwSearchPref );
if ( pInfo )
{
*(pInfo) = *(pSearchPrefs);
}
else
{
if ( m_dwPrefCount == MAX_SEARCH_PREF )
{
return E_FAIL;
}
m_srchInfo[m_dwPrefCount] = *(pSearchPrefs);
m_dwPrefCount++;
}
pSearchPrefs++;
}
return S_OK;
}
PADS_SEARCHPREF_INFO CADsSearch::FindSearchPrefence( ADS_SEARCHPREF pref )
{
for(UINT idx=0; idx < MAX_SEARCH_PREF; idx++ )
{
if( m_srchInfo[idx].dwSearchPref == pref )
{
return &m_srchInfo[idx];
}
}
return NULL;
}
HRESULT CADsSearch::Execute( LPCTSTR pszFilter )
{
USES_CONVERSION;
HRESULT hr;
if ( !m_pSearch )
{
return E_UNEXPECTED;
}
m_hSearch = NULL;
//////////////////////////////////////////////
// Set the search preference if any
///////////////////////////////////////////////
if ( m_dwPrefCount )
{
hr = m_pSearch->SetSearchPreference( m_srchInfo, m_dwPrefCount);
if ( !SUCCEEDED(hr) )
{
return hr;
}
}
if ( m_sColumnList.IsEmpty() )
{
hr = m_pSearch->ExecuteSearch( T2OLE(pszFilter), NULL, -1, &m_hSearch );
}
else // Columns is specified
{
unsigned int count, xx;
LPWSTR *pColumns = NULL;
POSITION pos;
CString s;
count = m_sColumnList.GetCount();
pColumns = (LPWSTR*)AllocADsMem( sizeof(LPWSTR)*count);
pos = m_sColumnList.GetHeadPosition();
for(xx=0; xx < count; xx++)
{
s = m_sColumnList.GetAt(pos);
pColumns[xx] = T2OLE(s);
m_sColumnList.GetNext(pos);
}
hr = m_pSearch->ExecuteSearch( T2OLE(pszFilter), pColumns, count, &m_hSearch );
if ( pColumns )
{
FreeADsMem( pColumns );
}
}
return hr;
}
HRESULT CADsSearch::GetColumn( UINT nIndex, CStringList &sList )
{
CString s;
if ( m_sColumnList.IsEmpty() )
{
return E_FAIL;
}
POSITION pos;
pos = m_sColumnList.FindIndex( nIndex );
if ( pos == NULL )
{
return E_FAIL;
}
s = m_sColumnList.GetAt(pos);
return GetColumn( s, sList );
}
HRESULT CADsSearch::GetColumn( LPCTSTR pszCol, PADS_SEARCH_COLUMN pCol )
{
LPWSTR pszAttrName;
USES_CONVERSION;
pszAttrName = T2OLE(pszCol);
return m_pSearch->GetColumn( m_hSearch, pszAttrName, pCol );
}
HRESULT CADsSearch::FreeColumn( PADS_SEARCH_COLUMN pCol )
{
return m_pSearch->FreeColumn( pCol );
}
HRESULT CADsSearch::GetColumn(CString &sCol, CStringList &sList )
{
LPWSTR pszAttrName;
ADS_SEARCH_COLUMN col;
HRESULT hr;
USES_CONVERSION;
CString s;
pszAttrName = T2OLE(sCol);
hr = m_pSearch->GetColumn( m_hSearch, pszAttrName, &col );
if ( !SUCCEEDED(hr) )
{
return hr;
}
hr = FormatColumn( &col, sList );
m_pSearch->FreeColumn( &col );
return hr;
}
HRESULT CADsSearch::FormatColumn(PADS_SEARCH_COLUMN pColumn, CStringList &sList)
{
ADsToStringList( pColumn->pADsValues, pColumn->dwNumValues, sList );
return S_OK;
}