windows-nt/Source/XPSP1/NT/net/mmc/mprsnap/rrasqry.cpp
2020-09-26 16:20:57 +08:00

709 lines
19 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: rrasqry.cpp
//
//--------------------------------------------------------------------------
// rrasqry.cpp : implementation file
//
#include "stdafx.h"
#include "qryfrm.h"
#include "rrasqry.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static UINT g_cfDsObjectNames = 0;
static UINT g_cfDsQueryParams = 0;
static UINT g_cfDsQueryScope = 0;
#define DIR_SEARCH_PAGE_SIZE 256
#define DIR_SEARCH_PAGE_TIME_LIMIT 30
#define CFSTR_DSQUERYSCOPE TEXT("DsQueryScope")
HRESULT RRASDelRouterIdObj(
/*[in]*/LPCWSTR pwszMachineName // DN of the computer object in DS
)
{
HRESULT hr = S_OK;
CComPtr<IADsContainer> spContainer;
CString machineName;
if(!pwszMachineName || *pwszMachineName == 0) // this machine
machineName = GetLocalMachineName();
else
machineName = pwszMachineName;
ASSERT(machineName.GetLength());
if(machineName.GetLength() == 0) return S_FALSE;
// prepare fileter,
// in format
// (&(objectClass=RRASAdministrationConnectionPoint)(distinguishedName=CN=RouterIdentity,CN=*)
CString filter = FILTER_PREFIX;
filter += _T("&");
filter += FILTER_PREFIX;
#if 1 /// use computer to query
filter += ATTR_NAME_OBJECTCLASS;
filter += _T("=");
filter += ATTR_CLASS_COMPUTER;
filter += FILTER_POSTFIX;
filter += FILTER_PREFIX;
filter += ATTR_NAME_CN;
filter += _T("=");
filter += machineName;
#else // user router id of the computer object for query, not found
filter += ATTR_NAME_OBJECTCLASS;
filter += _T("=");
filter += ATTR_CLASS_RRASID;
filter += FILTER_POSTFIX;
filter += FILTER_PREFIX;
filter += ATTR_NAME_DN;
filter += _T("=");
filter += DNPREFIX_ROUTERID;
filter += machineName;
filter += _T(",*");
#endif
filter += FILTER_POSTFIX;
filter += FILTER_POSTFIX;
// end of filter
// Query the routerId Object
// Search Routers under configuration
CComPtr<IADs> spIADs;
CComPtr<IDirectorySearch> spISearch;
CString RIdPath;
BSTR RRASPath = NULL;
CString RRASDNSName;
CComPtr<IADs> spIADsRId;
CComPtr<IADsContainer> spIADsContainerRRAS;
VARIANT var;
CString strSearchScope;
ADS_SEARCH_HANDLE hSrch = NULL;
ADS_SEARCH_COLUMN colDN;
VariantInit(&var);
// retieve the list of EAPTypes in the DS
// get ROOTDSE
// if no scope is specified, search the entire enterprise
CHECK_HR(hr = ADsGetObject(L"LDAP://RootDSE", IID_IADs, (void**)&spIADs));
ASSERT(spIADs.p);
CHECK_HR(hr = spIADs->Get(L"rootDomainNamingContext", &var));
ASSERT(V_BSTR(&var));
strSearchScope = _T("LDAP://");
strSearchScope += V_BSTR(&var);
spIADs.Release();
// Get the scope object
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)strSearchScope), IID_IDirectorySearch, (void**)&spISearch));
ASSERT(spISearch.p);
{
ADS_SEARCHPREF_INFO s_aSearchPrefs[3];
s_aSearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_PAGED_TIME_LIMIT;
s_aSearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
s_aSearchPrefs[0].vValue.Integer = DIR_SEARCH_PAGE_TIME_LIMIT;
s_aSearchPrefs[0].dwStatus = ADS_STATUS_S_OK;
s_aSearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
s_aSearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
s_aSearchPrefs[1].vValue.Integer = ADS_SCOPE_SUBTREE;
s_aSearchPrefs[1].dwStatus = ADS_STATUS_S_OK;
s_aSearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
s_aSearchPrefs[2].vValue.dwType = ADSTYPE_BOOLEAN;
s_aSearchPrefs[2].vValue.Boolean = (ADS_BOOLEAN) -1;
s_aSearchPrefs[2].dwStatus = ADS_STATUS_S_OK;
PWSTR s_apwzAttrs[] = { L"distinguishedName" };
CHECK_HR(hr = spISearch->SetSearchPreference(s_aSearchPrefs, ARRAYSIZE(s_aSearchPrefs)));
// do the search
CHECK_HR(hr = spISearch->ExecuteSearch(T2W((LPTSTR)(LPCTSTR)filter),
s_apwzAttrs, ARRAYSIZE(s_apwzAttrs), &hSrch));
ASSERT(hSrch);
do
{
//
// Get the columns for each of the properties we are interested in, if
// we failed to get any of the base properties for the object then lets
// just skip this entry as we cannot build a valid IDLIST for it. The
// properties that we request should be present on all objects.
//
CHECK_HR(hr = spISearch->GetNextRow(hSrch));
if(hr == S_OK) // it might equal to S_ADS_NOMORE_ROWS otherwise
{
CHECK_HR(hr = spISearch->GetColumn(hSrch, s_apwzAttrs[0], &colDN));
RIdPath = _T("LDAP://");
RIdPath += colDN.pADsValues->CaseIgnoreString;
#if 1 //uses computer to query
spIADsContainerRRAS.Release();
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)RIdPath), IID_IADsContainer, (void**)&spIADsContainerRRAS));
ASSERT(spIADsContainerRRAS.p);
#else // uses routerID to query -- this mothed can not find the object, so changed
spIADsRId.Release();
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)RIdPath), IID_IADs, (void**)&spIADsRId));
ASSERT(spIADsRId.p);
CHECK_HR(hr = spIADsRId->get_Parent(&RRASPath));
spIADsContainerRRAS.Release();
CHECK_HR(hr = ADsGetObject(RRASPath, IID_IADsContainer, (void**)&spIADsContainerRRAS));
ASSERT(spIADsContainerRRAS.p);
SysFreeString(RRASPath);
RRASPath = NULL;
#endif
VariantClear(&var);
CHECK_HR(hr = spIADsContainerRRAS->Delete(ATTR_CLASS_RRASID, CN_ROUTERID));
}
} while( !FAILED(hr) && hr != S_ADS_NOMORE_ROWS);
}
//
// If there is more than one computer found, ( should not ) and give use a chance to delete one.
L_ERR:
return S_OK;
}
HRESULT RRASOpenQryDlg(
/*[in]*/ CWnd* pParent,
/*[in, out]*/ RRASQryData& QryData
)
{
CDlgSvr dlg(QryData, pParent);
HRESULT hr = S_OK;
if(dlg.DoModal() == IDOK)
{
if(QryData.dwCatFlag == RRAS_QRY_CAT_NT5LDAP)
hr = RRASDSQueryDlg(pParent, QryData);
}
else
hr = S_FALSE;
return hr;
}
HRESULT RRASDSQueryDlg(
/*[in]*/ CWnd* pParent,
/*[in, out]*/ RRASQryData& QryData
)
{
HRESULT hr = S_OK;
CComPtr<ICommonQuery> spCommonQuery;
CComPtr<IDataObject> spDataObject;
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM medium = { TYMED_NULL, NULL, NULL };
DSQUERYINITPARAMS dqip;
OPENQUERYWINDOW oqw;
CHECK_HR(hr = CoInitialize(NULL));
CHECK_HR(hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_ICommonQuery, (LPVOID*)&spCommonQuery));
dqip.cbStruct = sizeof(dqip);
dqip.dwFlags = 0;
dqip.pDefaultScope = NULL;
oqw.cbStruct = sizeof(oqw);
oqw.dwFlags = 0;
oqw.clsidHandler = CLSID_DsQuery;
oqw.pHandlerParameters = &dqip;
oqw.clsidDefaultForm = CLSID_RRASQueryForm;
oqw.dwFlags |= OQWF_OKCANCEL;
dqip.dwFlags |= DSQPF_NOSAVE;
oqw.dwFlags |= OQWF_REMOVEFORMS;
oqw.dwFlags |= OQWF_DEFAULTFORM;
oqw.dwFlags |= OQWF_HIDEMENUS;
oqw.dwFlags |= OQWF_HIDESEARCHUI;
// Now display the dialog, and if we succeeded and get an IDataObject then
// slurp the results into our list view.
hr = spCommonQuery->OpenQueryWindow(pParent->GetSafeHwnd(), &oqw, &spDataObject);
if ( SUCCEEDED(hr) && spDataObject.p )
{
// now get the DSQUERYPARAMS and lets get the filter string
if ( !g_cfDsQueryScope )
g_cfDsQueryScope = RegisterClipboardFormat(CFSTR_DSQUERYSCOPE);
fmte.cfFormat = (CLIPFORMAT) g_cfDsQueryScope;
if ( SUCCEEDED(spDataObject->GetData(&fmte, &medium)) )
{
LPWSTR pScopeStr = (LPWSTR)medium.hGlobal;
QryData.strScope = pScopeStr;
ReleaseStgMedium(&medium);
}
else
QryData.strScope = _T("");
if ( !g_cfDsQueryParams )
g_cfDsQueryParams = RegisterClipboardFormat(CFSTR_DSQUERYPARAMS);
fmte.cfFormat = (CLIPFORMAT) g_cfDsQueryParams;
if ( SUCCEEDED(spDataObject->GetData(&fmte, &medium)) )
{
LPDSQUERYPARAMS pDsQueryParams = (LPDSQUERYPARAMS)medium.hGlobal;
LPWSTR pFilter = (LPTSTR)ByteOffset(pDsQueryParams, pDsQueryParams->offsetQuery);
QryData.strFilter = pFilter;
ReleaseStgMedium(&medium);
}
else
QryData.strFilter = _T("");
}
L_ERR:
CoUninitialize();
return hr;
}
//
// S_OK -- User select OK
// S_FALSE -- User select Cancel
// ERROR:
// DS error, search activeDs.dll
// Win32 erroe
// LDAP error
// General error -- memory, invalid argument ...
HRESULT RRASExecQry(
/*[in]*/ RRASQryData& QryData,
/*[out]*/ DWORD& dwFlags,
/*[out]*/ CStringArray& RRASs
)
{
USES_CONVERSION;
HRESULT hr = S_OK;
switch(QryData.dwCatFlag)
{
case RRAS_QRY_CAT_THIS:
{
CString machine;
RRASs.Add(machine);
break;
}
case RRAS_QRY_CAT_MACHINE:
RRASs.Add(QryData.strFilter);
break;
// NT4 Domain
case RRAS_QRY_CAT_NT4DOMAIN:
{
LPWSTR pDomainName;
SERVER_INFO_100* pServerInfo100 = NULL;
SERVER_INFO_101* pServerInfo101 = NULL;
DWORD dwRead;
DWORD dwTotal;
NET_API_STATUS netret;
dwFlags = RRAS_QRY_RESULT_HOSTNAME;
if(QryData.strScope.IsEmpty())
return E_INVALIDARG;
// Although the API excepts TCHAR it is exclusively UNICODE
if (QryData.strScope.Left(2) != _T("\\\\"))
pDomainName = T2W((LPTSTR)(LPCTSTR)QryData.strScope);
else
pDomainName = T2W((LPTSTR)(LPCTSTR)QryData.strScope + 2);
do
{
CWaitCursor wCursor;
netret = ::NetServerEnum(NULL, 101, (LPBYTE*)&pServerInfo101,
0xffffffff, &dwRead, &dwTotal, SV_TYPE_DIALIN_SERVER,
pDomainName, NULL);
if(pServerInfo101 && netret == NERR_Success || netret == ERROR_MORE_DATA)
{
PSERVER_INFO_101 pSvInfo101_t = pServerInfo101;
CString serverName;
for (;dwRead > 0; dwRead--, pSvInfo101_t++)
{
// this option should addin all the server in the NT4 domain, not the NT4 servers in the domain
// if(pSvInfo101_t->sv101_version_major == 4)
{
serverName = (LPWSTR)pSvInfo101_t->sv101_name;
RRASs.Add(serverName);
}
}
NetApiBufferFree(pServerInfo101);
}
} while (netret == ERROR_MORE_DATA);
if(netret == NERR_Success)
hr = S_OK;
else
hr = HRESULT_FROM_WIN32(netret);
}
break;
// NT5 LADP Query
case RRAS_QRY_CAT_NT5LDAP:
{
// Search Routers under configuration
CComPtr<IADs> spIADs;
CComPtr<IDirectorySearch> spISearch;
CString RIdPath;
BSTR RRASPath = NULL;
CString RRASDNSName;
CComPtr<IADs> spIADsRId;
CComPtr<IADs> spIADsRRAS;
VARIANT var;
CString strSearchScope;
ADS_SEARCH_HANDLE hSrch = NULL;
ADS_SEARCH_COLUMN colDN;
CWaitCursor cw;
// dwFlags = RRAS_QRY_RESULT_DNSNAME;
dwFlags = RRAS_QRY_RESULT_HOSTNAME;
VariantInit(&var);
// retieve the list of EAPTypes in the DS
// get ROOTDSE
// if no scope is specified, search the entire enterprise
if(QryData.strScope.IsEmpty())
{
CHECK_HR(hr = ADsGetObject(L"LDAP://RootDSE", IID_IADs, (void**)&spIADs));
ASSERT(spIADs.p);
CHECK_HR(hr = spIADs->Get(L"rootDomainNamingContext", &var));
ASSERT(V_BSTR(&var));
strSearchScope = _T("LDAP://");
strSearchScope += V_BSTR(&var);
spIADs.Release();
}
else
strSearchScope = QryData.strScope;
// Get the scope object
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)strSearchScope), IID_IDirectorySearch, (void**)&spISearch));
ASSERT(spISearch.p);
{
ADS_SEARCHPREF_INFO s_aSearchPrefs[3];
s_aSearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_PAGED_TIME_LIMIT;
s_aSearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
s_aSearchPrefs[0].vValue.Integer = DIR_SEARCH_PAGE_TIME_LIMIT;
s_aSearchPrefs[0].dwStatus = ADS_STATUS_S_OK;
s_aSearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
s_aSearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
s_aSearchPrefs[1].vValue.Integer = ADS_SCOPE_SUBTREE;
s_aSearchPrefs[1].dwStatus = ADS_STATUS_S_OK;
s_aSearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
s_aSearchPrefs[2].vValue.dwType = ADSTYPE_BOOLEAN;
s_aSearchPrefs[2].vValue.Boolean = (ADS_BOOLEAN) -1;
s_aSearchPrefs[2].dwStatus = ADS_STATUS_S_OK;
PWSTR s_apwzAttrs[] = { L"distinguishedName" };
CHECK_HR(hr = spISearch->SetSearchPreference(s_aSearchPrefs, ARRAYSIZE(s_aSearchPrefs)));
// do the search
CHECK_HR(hr = spISearch->ExecuteSearch(T2W((LPTSTR)(LPCTSTR)QryData.strFilter),
s_apwzAttrs, ARRAYSIZE(s_apwzAttrs), &hSrch));
ASSERT(hSrch);
do
{
//
// Get the columns for each of the properties we are interested in, if
// we failed to get any of the base properties for the object then lets
// just skip this entry as we cannot build a valid IDLIST for it. The
// properties that we request should be present on all objects.
//
CHECK_HR(hr = spISearch->GetNextRow(hSrch));
if(hr == S_OK) // it might equal to S_ADS_NOMORE_ROWS otherwise
{
CHECK_HR(hr = spISearch->GetColumn(hSrch, s_apwzAttrs[0], &colDN));
RIdPath = _T("LDAP://");
RIdPath += colDN.pADsValues->CaseIgnoreString;
spIADsRId.Release();
CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)RIdPath), IID_IADs, (void**)&spIADsRId));
ASSERT(spIADsRId.p);
CHECK_HR(hr = spIADsRId->get_Parent(&RRASPath));
spIADsRRAS.Release();
CHECK_HR(hr = ADsGetObject(RRASPath, IID_IADs, (void**)&spIADsRRAS));
ASSERT(spIADsRRAS.p);
SysFreeString(RRASPath);
RRASPath = NULL;
VariantClear(&var);
// build 1750, this is empty, changed to "name"
// CHECK_HR(hr = spIADsRRAS->Get(L"dNSHostName", &var));
CHECK_HR(hr = spIADsRRAS->Get(L"name", &var));
RRASDNSName = V_BSTR(&var);
if(!RRASDNSName.IsEmpty())
RRASs.Add(RRASDNSName);
}
} while( !FAILED(hr) && hr != S_ADS_NOMORE_ROWS);
}
L_ERR:
if(hSrch)
CHECK_HR(hr = spISearch->CloseSearchHandle(hSrch));
VariantClear(&var);
SysFreeString(RRASPath);
}
break;
default:
hr = E_INVALIDARG;
}
if (FAILED(hr))
DisplayErrorMessage(NULL, hr);
return hr;
}
// S_OK -- User select OK
// ERROR:
// DS error, search activeDs.dll
// Win32 erroe
// LDAP error
// General error -- memory, invalid argument ...
/////////////////////////////////////////////////////////////////////////////
// CDlgSvr dialog
RRASQryData __staticQueryData;
CDlgSvr::CDlgSvr(CWnd* pParent /*=NULL*/)
: m_QueryData(__staticQueryData), CBaseDialog(CDlgSvr::IDD, pParent)
{
Init();
}
CDlgSvr::CDlgSvr(RRASQryData& QueryData, CWnd* pParent /*=NULL*/)
: m_QueryData(QueryData), CBaseDialog(CDlgSvr::IDD, pParent)
{
Init();
}
void CDlgSvr::Init()
{
//{{AFX_DATA_INIT(CDlgSvr)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CDlgSvr::DoDataExchange(CDataExchange* pDX)
{
CBaseDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgSvr)
DDX_Control(pDX, IDC_QRY_EDIT_MACHINE, m_editMachine);
DDX_Control(pDX, IDC_QRY_EDIT_DOMAIN, m_editDomain);
DDX_Control(pDX, IDOK, m_btnNext);
DDX_Radio(pDX, IDC_QRY_RADIO_THIS, m_nRadio);
DDX_Text(pDX, IDC_QRY_EDIT_DOMAIN, m_strDomain);
DDV_MaxChars(pDX, m_strDomain, 256);
if(m_nRadio == 2)
DDV_MinChars(pDX, m_strDomain, 1);
DDX_Text(pDX, IDC_QRY_EDIT_MACHINE, m_strMachine);
DDV_MaxChars(pDX, m_strMachine, 256);
if(m_nRadio == 1)
DDV_MinChars(pDX, m_strMachine, 1);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDlgSvr, CBaseDialog)
//{{AFX_MSG_MAP(CDlgSvr)
ON_BN_CLICKED(IDC_QRY_RADIO_ANOTHER, OnRadioAnother)
ON_BN_CLICKED(IDC_QRY_RADIO_NT4, OnRadioNt4)
ON_BN_CLICKED(IDC_QRY_RADIO_NT5, OnRadioNt5)
ON_BN_CLICKED(IDC_QRY_RADIO_THIS, OnRadioThis)
ON_BN_CLICKED(IDOK, OnButtonNext)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDlgSvr message handlers
void CDlgSvr::OnRadioAnother()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString str;
str.LoadString(IDS_OK);
m_editMachine.EnableWindow(TRUE);
m_editDomain.EnableWindow(FALSE);
m_btnNext.SetWindowText(str);
}
void CDlgSvr::OnRadioNt4()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString str;
str.LoadString(IDS_OK);
m_editMachine.EnableWindow(FALSE);
m_editDomain.EnableWindow(TRUE);
m_btnNext.SetWindowText(str);
}
void CDlgSvr::OnRadioNt5()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString str;
str.LoadString(IDS_NEXT);
m_editMachine.EnableWindow(FALSE);
m_editDomain.EnableWindow(FALSE);
m_btnNext.SetWindowText(str);
}
void CDlgSvr::OnRadioThis()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString str;
str.LoadString(IDS_OK);
m_editMachine.EnableWindow(FALSE);
m_editDomain.EnableWindow(FALSE);
m_btnNext.SetWindowText(str);
}
void CDlgSvr::OnButtonNext()
{
if(UpdateData(TRUE) == 0) return;
switch(m_nRadio)
{
case 0:
m_QueryData.dwCatFlag = RRAS_QRY_CAT_THIS;
break;
case 1:
m_QueryData.dwCatFlag = RRAS_QRY_CAT_MACHINE;
m_QueryData.strFilter = m_strMachine;
break;
case 2:
m_QueryData.dwCatFlag = RRAS_QRY_CAT_NT4DOMAIN;
m_QueryData.strScope = m_strDomain;
break;
case 3:
m_QueryData.dwCatFlag = RRAS_QRY_CAT_NT5LDAP;
break;
default:
ASSERT(0); // this should not happen
break;
}
EndDialog(IDOK);
}
/////////////////////////////////////////////////////////////////////////////
// CDlgSrv message handlers
/////////////////////////////////////////////////////////////////////////////
// CDlgSvr1 message handlers
BOOL CDlgSvr::OnInitDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
BOOL bEnableMachine = FALSE, bEnableDomain = FALSE;
UINT okIDS = IDS_OK;
switch(m_QueryData.dwCatFlag)
{
case RRAS_QRY_CAT_THIS:
m_nRadio = 0;
break;
case RRAS_QRY_CAT_MACHINE:
bEnableMachine = TRUE;
m_strMachine = m_QueryData.strFilter;
m_nRadio = 1;
break;
case RRAS_QRY_CAT_NT4DOMAIN:
bEnableDomain = TRUE;
m_strDomain = m_QueryData.strScope;
m_nRadio = 2;
break;
case RRAS_QRY_CAT_NT5LDAP:
m_nRadio = 3;
okIDS = IDS_NEXT;
break;
default:
m_nRadio = 0;
break;
}
CBaseDialog::OnInitDialog();
CString str;
str.LoadString(okIDS);
m_editMachine.EnableWindow(bEnableMachine);
m_editDomain.EnableWindow(bEnableDomain);
m_btnNext.SetWindowText(str);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}