#include "pch.h" #pragma hdrstop #include "atlbase.h" extern CComModule _Module; #include "atlcom.h" #include /*----------------------------------------------------------------------------- / Local functions / data /----------------------------------------------------------------------------*/ static WCHAR c_szQueryPrefix[] = L"(objectClass=nTDSDSA)"; static LPWSTR c_szClassList[] = { L"nTDSDSA", }; static COLUMNINFO columns[] = { 0, 0, IDS_SERVERNAME, 0, L"ADsPath,{2C875213-FCE5-11d1-A0B0-00C04FA31A86}", 0, 0, IDS_SITE, 0, L"ADsPath,{25be9228-00af-11d2-bf87-00c04fd8d5b0}", 0, DEFAULT_WIDTH_DESCRIPTION, IDS_DOMAIN, 0, L"hasMasterNCs,{1cedc5da-3614-11d2-bf96-00c04fd8d5b0}", }; // // Help ID mappings // static DWORD const aFormHelpIDs[] = { 0, 0 }; /*----------------------------------------------------------------------------- / PageProc_DomainController / ------------------------- / PageProc for handling the messages for this object. / / In: / pPage -> instance data for this form / hwnd = window handle for the form dialog / uMsg, wParam, lParam = message parameters / / Out: / HRESULT (E_NOTIMPL) if not handled /----------------------------------------------------------------------------*/ HRESULT CALLBACK PageProc_DomainController(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HRESULT hr = S_OK; LPWSTR pQuery = NULL; TraceEnter(TRACE_FORMS, "PageProc_DomainController"); switch (uMsg) { case CQPM_INITIALIZE: case CQPM_RELEASE: break; case CQPM_ENABLE: EnablePageControls(hwnd, NULL, 0, (BOOL)wParam); break; case CQPM_GETPARAMETERS: { hr = GetQueryString(&pQuery, c_szQueryPrefix, hwnd, NULL, 0); if (SUCCEEDED(hr)) { hr = QueryParamsAlloc((LPDSQUERYPARAMS*)lParam, pQuery, GLOBAL_HINSTANCE, ARRAYSIZE(columns), columns); LocalFreeStringW(&pQuery); } FailGracefully(hr, "Failed to build DS argument block"); break; } case CQPM_CLEARFORM: ResetPageControls(hwnd, NULL, 0); break; case CQPM_PERSIST: { BOOL fRead = (BOOL)wParam; IPersistQuery* pPersistQuery = (IPersistQuery*)lParam; hr = PersistQuery(pPersistQuery, fRead, c_szMsDomainControllers, hwnd, NULL, 0); FailGracefully(hr, "Failed to persist page"); break; } case CQPM_HELP: { LPHELPINFO pHelpInfo = (LPHELPINFO)lParam; WinHelp((HWND)pHelpInfo->hItemHandle, DSQUERY_HELPFILE, HELP_WM_HELP, (DWORD_PTR)aFormHelpIDs); break; } case DSQPM_GETCLASSLIST: { hr = ClassListAlloc((LPDSQUERYCLASSLIST*)lParam, c_szClassList, ARRAYSIZE(c_szClassList)); FailGracefully(hr, "Failed to allocate class list"); break; } case DSQPM_HELPTOPICS: { HWND hwndFrame = (HWND)lParam; HtmlHelp(hwndFrame, TEXT("omc.chm::/adfind_dc.htm"), HH_HELP_FINDER, 0); break; } default: hr = E_NOTIMPL; break; } exit_gracefully: TraceLeaveResult(hr); } /*----------------------------------------------------------------------------- / DlgProc_DomainController / ------------ / Handle dialog specific message for the Domain Controllers page. / / In: / hwnd, uMsg, wParam, lParam = standard parameters / / Out: / INT_PTR /----------------------------------------------------------------------------*/ INT_PTR CALLBACK DlgProc_DomainController(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR fResult = 0; LPCQPAGE pQueryPage; if (uMsg == WM_INITDIALOG) { pQueryPage = (LPCQPAGE)lParam; SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pQueryPage); } return fResult; } /*----------------------------------------------------------------------------- / CDomainCH / ------------------- / Column handler which converts the given property and value into a / string the user can understand. /----------------------------------------------------------------------------*/ class CDomainCH : public IDsQueryColumnHandler { private: LONG _cRef; CComPtr m_spPathCracker; HRESULT m_hrPathCrackerLoadError; long m_lElement; BOOL m_fFindDN; HRESULT GetTextFromADSVALUE(const PADSVALUE pADsValue, LPWSTR pBuffer, INT cchBuffer); public: CDomainCH(REFCLSID rCLSID); ~CDomainCH(); // IUnkown STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObject); // IDsQueryColumnHandler STDMETHOD(Initialize)(THIS_ DWORD dwFlags, LPCWSTR pszServer, LPCWSTR pszUserName, LPCWSTR pszPassword); STDMETHOD(GetText)(THIS_ ADS_SEARCH_COLUMN* pSearchColumn, LPWSTR pBuffer, INT cchBuffer); }; ULONG CDomainCH::AddRef() { return InterlockedIncrement(&_cRef); } ULONG CDomainCH::Release() { if (InterlockedDecrement(&_cRef)) return _cRef; delete this; return 0; } HRESULT CDomainCH::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CDomainCH, IDsQueryColumnHandler), // IID_IDsQueryColumnHandler {0, 0 }, }; return QISearch(this, qit, riid, ppv); } // // construction // CDomainCH::CDomainCH(REFCLSID rCLSID) : m_hrPathCrackerLoadError(0), m_lElement (1), m_fFindDN(FALSE), _cRef(1) { if (IsEqualCLSID(rCLSID, CLSID_PathElement1CH)) { } else if (IsEqualCLSID(rCLSID, CLSID_PathElement3CH)) { m_lElement = 3; } else if (IsEqualCLSID(rCLSID, CLSID_PathElementDomainCH)) { m_lElement = 0; m_fFindDN = true; } DllAddRef(); } CDomainCH::~CDomainCH() { DllRelease(); } // // handle class factory stuff // STDAPI CDomainCH_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { CDomainCH *pdch = new CDomainCH(*poi->pclsid); if (!pdch) return E_OUTOFMEMORY; HRESULT hres = pdch->QueryInterface(IID_IUnknown, (void **)ppunk); pdch->Release(); return hres; } // IDsQueryColumnHandler STDMETHODIMP CDomainCH::Initialize(THIS_ DWORD dwFlags, LPCWSTR pszServer, LPCWSTR pszUserName, LPCWSTR pszPassword) { return S_OK; } STDMETHODIMP CDomainCH::GetText(ADS_SEARCH_COLUMN* pSearchColumn, LPWSTR pBuffer, INT cchBuffer) { HRESULT hr = S_OK; DWORD iValue = 0; TraceEnter(TRACE_FORMS, "CDomainCH::GetText"); if (!pSearchColumn || !pBuffer) ExitGracefully(hr, E_UNEXPECTED, "DSQUERY.DLL: Bad parameters passed to handler"); if (pSearchColumn->dwNumValues < 1 || NULL == pSearchColumn->pADsValues ) ExitGracefully(hr, S_OK, "DSQUERY.DLL: no values in handler"); if (m_fFindDN) { // // This section handles CLSID_CH_PathElementDomainCH // PADSVALUE pADsValue = NULL; LPWSTR pwzResultName = NULL; PDS_NAME_RESULTW pDsNameResult = NULL; for (iValue = 0; iValue < pSearchColumn->dwNumValues; iValue++) { pADsValue = &(pSearchColumn->pADsValues[iValue]); if (NULL == pADsValue || (pADsValue->dwType != ADSTYPE_CASE_IGNORE_STRING && pADsValue->dwType != ADSTYPE_DN_STRING) ) ExitGracefully(hr, S_OK, "DSQUERY.DLL: not a DN value in handler"); if (0 == StrCmpNW(L"DC=",pADsValue->CaseIgnoreString,3)) break; } if (iValue >= pSearchColumn->dwNumValues) { // no value found StrCpyNW(pBuffer, L"", cchBuffer); ExitGracefully(hr, S_OK, "DSQUERY.DLL: no domain values in handler"); } // // We found the value, now try DsCrackNames to convert it to // a DNS name. If this fails, fall back to path element 0. // TraceAssert(pADsValue); DWORD dwErr = ::DsCrackNamesW( (HANDLE)-1, DS_NAME_FLAG_SYNTACTICAL_ONLY, DS_FQDN_1779_NAME, DS_CANONICAL_NAME, 1, &(pADsValue->CaseIgnoreString), &pDsNameResult); hr = HRESULT_FROM_WIN32(dwErr); if (SUCCEEDED(hr)) { TraceAssert(pDsNameResult); TraceAssert(1 == pDsNameResult->cItems); if (DS_NAME_NO_ERROR == pDsNameResult->rItems->status) { TraceAssert(pDsNameResult->rItems->pDomain); StrCpyNW(pBuffer, pDsNameResult->rItems->pDomain, cchBuffer); DsFreeNameResultW(pDsNameResult); goto exit_gracefully; } } // // This is the fallback scenario if DsCrackNames fails. // If the domain is "CN=jonndom,CN=nttest,CN=microsoft,CN=com", // the name displayed will be "jonndom". // } hr = GetTextFromADSVALUE( &(pSearchColumn->pADsValues[iValue]), pBuffer, cchBuffer); exit_gracefully: TraceLeaveResult(hr); } HRESULT CDomainCH::GetTextFromADSVALUE(const PADSVALUE pADsValue, LPWSTR pBuffer, INT cchBuffer) { HRESULT hr = S_OK; CComBSTR sbstr; TraceEnter(TRACE_FORMS, "CDomainCH::GetTextFromADSVALUE"); if (NULL == pADsValue || (pADsValue->dwType != ADSTYPE_CASE_IGNORE_STRING && pADsValue->dwType != ADSTYPE_DN_STRING) || !(pADsValue->CaseIgnoreString) ) ExitGracefully(hr, S_OK, "DSQUERY.DLL: not a DN value in handler"); if (!m_spPathCracker) { FailGracefully(m_hrPathCrackerLoadError, "DSQUERY.DLL: Subsequent failure to load Path Cracker"); m_hrPathCrackerLoadError = CoCreateInstance( CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&m_spPathCracker); FailGracefully(m_hrPathCrackerLoadError, "DSQUERY.DLL: First failure to load Path Cracker"); if (!m_spPathCracker) { m_hrPathCrackerLoadError = E_UNEXPECTED; FailGracefully(m_hrPathCrackerLoadError, "DSQUERY.DLL: CreateInstance did not load"); } m_hrPathCrackerLoadError = m_spPathCracker->SetDisplayType( ADS_DISPLAY_VALUE_ONLY); FailGracefully(m_hrPathCrackerLoadError, "DSQUERY.DLL: SetDisplayType failed"); } // ADsPath starts with "LDAP://" but hasMasterNCs doesn't hr = m_spPathCracker->Set(pADsValue->CaseIgnoreString, (m_fFindDN) ? ADS_SETTYPE_DN : ADS_SETTYPE_FULL); FailGracefully(hr, "DSQUERY.DLL: Set() failed"); hr = m_spPathCracker->GetElement(m_lElement, &sbstr); FailGracefully(hr, "DSQUERY.DLL: GetElement() failed"); StrCpyNW(pBuffer, sbstr, cchBuffer); exit_gracefully: TraceLeaveResult(hr); }