|
|
//+----------------------------------------------------------------------------
//
// Windows NT Directory Service Property Pages
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: propbase.cxx
//
// Contents: CDsPropPageBase, the base class for property page classes.
//
// History: 31-March-97 EricB created
//
//-----------------------------------------------------------------------------
#include "pch.h"
#include "proppage.h"
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::~CADsApplyErrors
//
//-----------------------------------------------------------------------------
CADsApplyErrors::~CADsApplyErrors() { if (m_pszTitle != NULL) { delete[] m_pszTitle; }
Clear(); }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::SetError
//
//-----------------------------------------------------------------------------
void CADsApplyErrors::SetError(PADSPROPERROR pError) { if (m_nCount == m_nArraySize) { PAPPLY_ERROR_ENTRY pNewTable = new APPLY_ERROR_ENTRY[m_nCount + m_nIncAmount]; m_nArraySize = m_nCount + m_nIncAmount;
if (pNewTable != NULL) { memset(pNewTable, 0, sizeof(APPLY_ERROR_ENTRY) * (m_nCount + m_nIncAmount));
if (m_pErrorTable != NULL) { for (UINT nIdx = 0; nIdx < m_nCount; nIdx++) { pNewTable[nIdx].pszPath = m_pErrorTable[nIdx].pszPath; pNewTable[nIdx].pszClass = m_pErrorTable[nIdx].pszClass; pNewTable[nIdx].hr = m_pErrorTable[nIdx].hr; pNewTable[nIdx].pszStringError = m_pErrorTable[nIdx].pszStringError; } delete[] m_pErrorTable; } m_pErrorTable = pNewTable; } }
//
// Copy the path to the object
//
if (pError->pszObjPath != NULL) { m_pErrorTable[m_nCount].pszPath = new WCHAR[wcslen(pError->pszObjPath) + 1]; dspAssert(m_pErrorTable[m_nCount].pszPath != NULL); if (m_pErrorTable[m_nCount].pszPath != NULL) { wcscpy(m_pErrorTable[m_nCount].pszPath, pError->pszObjPath); } }
//
// Copy the class to the object
//
if (pError->pszObjClass != NULL) { // Note: this memory is freed in the Clear() method which is called from
// the class destructor
m_pErrorTable[m_nCount].pszClass = new WCHAR[wcslen(pError->pszObjClass) + 1]; dspAssert(m_pErrorTable[m_nCount].pszClass != NULL); if (m_pErrorTable[m_nCount].pszClass != NULL) { wcscpy(m_pErrorTable[m_nCount].pszClass, pError->pszObjClass); } }
//
// Copy the error
//
if (pError->hr != S_OK) { m_pErrorTable[m_nCount].hr = pError->hr; } else { if (pError->pszError != NULL) { m_pErrorTable[m_nCount].pszStringError = new WCHAR[wcslen(pError->pszError) + 1]; dspAssert(m_pErrorTable[m_nCount].pszStringError != NULL); if (m_pErrorTable[m_nCount].pszStringError != NULL) { wcscpy(m_pErrorTable[m_nCount].pszStringError, pError->pszError); } } }
//
// Copy the page title
//
if (pError->pszPageTitle != NULL) { m_pszTitle = new WCHAR[wcslen(pError->pszPageTitle) + 1]; if (m_pszTitle != NULL) { wcscpy(m_pszTitle, pError->pszPageTitle); } }
m_nCount++; }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::GetError
//
//-----------------------------------------------------------------------------
HRESULT CADsApplyErrors::GetError(UINT nIndex) { dspAssert(nIndex < m_nCount); if (nIndex < m_nCount) { return m_pErrorTable[nIndex].hr; } return S_FALSE; }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::GetStringError
//
//-----------------------------------------------------------------------------
PWSTR CADsApplyErrors::GetStringError(UINT nIndex) { dspAssert(nIndex < m_nCount); if (nIndex < m_nCount) { return m_pErrorTable[nIndex].pszStringError; } return NULL; }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::Clear
//
//-----------------------------------------------------------------------------
void CADsApplyErrors::Clear() { if (m_pErrorTable != NULL) { for (UINT idx = 0; idx < m_nCount; idx++) { if (m_pErrorTable[idx].pszPath != NULL) { delete[] m_pErrorTable[idx].pszPath; m_pErrorTable[idx].pszPath = NULL; } if (m_pErrorTable[idx].pszClass != NULL) { delete[] m_pErrorTable[idx].pszClass; m_pErrorTable[idx].pszClass = NULL; } if (m_pErrorTable[idx].pszStringError != NULL) { delete[] m_pErrorTable[idx].pszStringError; m_pErrorTable[idx].pszStringError = NULL; } } delete[] m_pErrorTable; m_pErrorTable = NULL; }
m_nCount = 0; m_nArraySize = 0; }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::GetName
//
//-----------------------------------------------------------------------------
PWSTR CADsApplyErrors::GetName(UINT nIndex) { dspAssert(nIndex < m_nCount); if (nIndex < m_nCount) { return m_pErrorTable[nIndex].pszPath; } return NULL; }
//+----------------------------------------------------------------------------
//
// Member: CADsApplyErrors::GetClass
//
//-----------------------------------------------------------------------------
PWSTR CADsApplyErrors::GetClass(UINT nIndex) { dspAssert(nIndex < m_nCount); if (nIndex < m_nCount) { return m_pErrorTable[nIndex].pszClass; } return NULL; }
//+----------------------------------------------------------------------------
//
// Member: CDsPropPageBase::CDsPropPageBase
//
//-----------------------------------------------------------------------------
CDsPropPageBase::CDsPropPageBase(PDSPAGE pDsPage, LPDATAOBJECT pDataObj, HWND hNotifyObj, DWORD dwFlags) : m_hPage(NULL), m_fInInit(FALSE), m_fPageDirty(FALSE), m_fReadOnly(FALSE), m_fMultiselectPage(FALSE), m_pDataObj(pDataObj), m_pWPTDataObj(NULL), m_pDataObjStrm(NULL), m_pDsObj(NULL), m_nPageTitle(pDsPage->nPageTitle), m_nDlgTemplate(pDsPage->nDlgTemplate), m_cAttrs(pDsPage->cAttrs), m_rgpAttrMap(pDsPage->rgpAttrMap), m_pwszObjPathName(NULL), m_pwszObjClass(NULL), m_pwszRDName(NULL), m_pDispSpec(NULL), m_pObjSel(NULL), m_fObjSelInited(FALSE), m_rgAttrData(NULL), m_uRefs(1), m_hNotifyObj(hNotifyObj), m_pWritableAttrs(NULL), m_hrInit(S_OK) { TRACE2(CDsPropPageBase,CDsPropPageBase); //
// Get the read-only state.
//
if (dwFlags & DSOBJECT_READONLYPAGES) { m_fReadOnly = TRUE; } }
//+----------------------------------------------------------------------------
//
// Member: CDsPropPageBase::~CDsPropPageBase
//
//-----------------------------------------------------------------------------
CDsPropPageBase::~CDsPropPageBase() { TRACE2(CDsPropPageBase,~CDsPropPageBase); if (m_pwszObjPathName) { delete m_pwszObjPathName; } if (m_pwszObjClass) { delete m_pwszObjClass; } if (m_pwszRDName) { delete m_pwszRDName; } if (m_rgAttrData) { delete [] m_rgAttrData; } if (m_pObjSel) { m_pObjSel->Release(); } if (m_pDispSpec) { m_pDispSpec->Release(); } if (m_pDataObjStrm) { m_pDataObjStrm->Release(); } }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::Init
//
// Synopsis: Initialize the page object. This is the second part of a two
// phase creation where operations that could fail are located.
// Failures here are recorded in m_hrInit and then an error page
// is substituted in CreatePage.
//
//-----------------------------------------------------------------------------
void CDsPropPageBase::Init(PWSTR pwzADsPath, LPWSTR pwzClass, const CDSSmartBasePathsInfo& basePathsInfo) { TRACE(CDsPropPageBase,Init); CWaitCursor cWait; ADSPROPINITPARAMS InitParams = {0}; InitParams.dwSize = sizeof(ADSPROPINITPARAMS);
ADsPropGetInitInfo(m_hNotifyObj, &InitParams);
if (FAILED(InitParams.hr)) { m_hrInit = InitParams.hr; return; }
m_basePathsInfo = basePathsInfo;
if (!AllocWStr(pwzADsPath, &m_pwszObjPathName) || !AllocWStr(InitParams.pwzCN, &m_pwszRDName) || !AllocWStr(pwzClass, &m_pwszObjClass)) { m_hrInit = E_OUTOFMEMORY; return; }
dspAssert(InitParams.pDsObj);
m_pDsObj = InitParams.pDsObj; DBG_OUT("+++++++++++++++++++++++++++addrefing object"); m_pDsObj->AddRef();
m_pWritableAttrs = InitParams.pWritableAttrs;
//
// Allocate memory for the attribute data.
//
m_rgAttrData = new ATTR_DATA[m_cAttrs]; CHECK_NULL(m_rgAttrData, m_hrInit = E_OUTOFMEMORY; return);
memset(m_rgAttrData, 0, m_cAttrs * sizeof(ATTR_DATA));
//
// Marshall the data object pointer for passing to the window proc thread.
//
HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, m_pDataObj, &m_pDataObjStrm); m_pDataObj = NULL; // to make sure no one calls here
CHECK_HRESULT(hr, m_hrInit = hr; return);
}
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::CreatePage
//
// Synopsis: Create the prop page
//
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::CreatePage(HPROPSHEETPAGE * phPage) { TCHAR szTitle[MAX_PATH]; if (!LoadStringReport(m_nPageTitle, szTitle, MAX_PATH, NULL)) { return HRESULT_FROM_WIN32(GetLastError()); }
PROPSHEETPAGE psp;
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USECALLBACK | PSP_USETITLE; psp.pszTemplate = MAKEINTRESOURCE((SUCCEEDED(m_hrInit)) ? m_nDlgTemplate : IDD_ERROR_PAGE); psp.pfnDlgProc = StaticDlgProc; psp.pfnCallback = PageCallback; psp.pcRefParent = NULL; // do not set PSP_USEREFPARENT
psp.lParam = (LPARAM) this; psp.hInstance = g_hInstance; psp.pszTitle = szTitle;
*phPage = CreatePropertySheetPage(&psp);
if (*phPage == NULL) { return HRESULT_FROM_WIN32(GetLastError()); }
return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::StaticDlgProc
//
// Synopsis: static dialog proc
//
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CDsPropPageBase::StaticDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CDsPropPageBase * pPage = (CDsPropPageBase *)GetWindowLongPtr(hDlg, DWLP_USER);
if (uMsg == WM_INITDIALOG) { LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
pPage = (CDsPropPageBase *) ppsp->lParam; pPage->m_hPage = hDlg;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPage);
if (pPage->m_pDataObjStrm) { // Unmarshall the Data Object pointer.
//
HRESULT hr; hr = CoGetInterfaceAndReleaseStream(pPage->m_pDataObjStrm, IID_IDataObject, reinterpret_cast<void**>(&pPage->m_pWPTDataObj)); CHECK_HRESULT_REPORT(hr, hDlg, return FALSE);
// The stream should have been released above so set the
// pointer to NULL so that we don't try to release again
pPage->m_pDataObjStrm = 0; } return pPage->DlgProc(hDlg, uMsg, wParam, lParam); }
if (pPage != NULL && (SUCCEEDED(pPage->m_hrInit))) { if (uMsg == WM_ADSPROP_PAGE_GET_NOTIFY) { HWND* pHWnd = (HWND*)wParam; *pHWnd = pPage->m_hNotifyObj; return TRUE; } return pPage->DlgProc(hDlg, uMsg, wParam, lParam); }
return FALSE; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::InitDlg
//
// Synopsis: Handles dialog initialization for error cases. Passes non-
// error initialization to subclass' OnInitDialog.
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::InitDlg(LPARAM lParam) { m_fInInit = TRUE;
if (FAILED(m_hrInit)) { // Bind to the object failed, display an error page with the error
// message string.
//
PTSTR ptz = NULL; BOOL fSpecialCaseErr = TRUE;
switch (HRESULT_CODE(m_hrInit)) { case ERROR_DS_NO_ATTRIBUTE_OR_VALUE: LoadStringToTchar(IDS_ERROR_VIEW_PERMISSIONS, &ptz); break;
case ERROR_DS_REFERRAL: LoadStringToTchar(IDS_ERRMSG_NO_DC_RESPONSE, &ptz); break;
case ERROR_DS_NO_SUCH_OBJECT: LoadStringToTchar(IDS_ERRMSG_NO_LONGER_EXISTS, &ptz); break;
default: fSpecialCaseErr = FALSE; break; }
if (fSpecialCaseErr && ptz) { SetWindowText(GetDlgItem(m_hPage, IDC_ERROR_MSG), ptz); delete ptz; } else { int cch;
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_hrInit, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PTSTR)&ptz, 0, NULL); if (!cch) { // Try ADSI errors.
//
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(TEXT("activeds.dll")), m_hrInit, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PTSTR)&ptz, 0, NULL); }
if (cch) { SetWindowText(GetDlgItem(m_hPage, IDC_ERROR_MSG), ptz); LocalFree(ptz); } } m_fInInit = FALSE; return S_OK; }
HRESULT hResult = OnInitDialog(lParam);
m_fInInit = FALSE; return hResult; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnNotify
//
// Synopsis: Handles notification messages
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnNotify(WPARAM, LPARAM lParam) { LRESULT lResult; BOOL fPageDirty;
switch (((LPNMHDR)lParam)->code) { case PSN_APPLY: if (FAILED(m_hrInit)) { return PSNRET_NOERROR; } lResult = PSNRET_NOERROR; //
// The member var m_fPageDirty gets cleared in OnApply, so save a local
// copy for passing as the wParam of the WM_ADSPROP_NOTIFY_APPLY msg.
//
fPageDirty = m_fPageDirty;
if (m_fPageDirty) { // Call the virtual function OnApply()
lResult = OnApply(); } // Store the result into the dialog
SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, (LONG_PTR)lResult); if (lResult == PSNRET_NOERROR) { m_fPageDirty = FALSE; //
// Signal the change notification. Note that the notify-apply
// message must be sent even if the page is not dirty so that the
// notify ref-counting will properly decrement.
//
SendMessage(m_hNotifyObj, WM_ADSPROP_NOTIFY_APPLY, fPageDirty, (LPARAM)m_hPage); } else { EnableWindow(GetDlgItem(GetParent(m_hPage), IDCANCEL), TRUE); } return lResult;
case PSN_RESET: OnCancel(); return FALSE; // allow the property sheet to be destroyed.
case PSN_SETACTIVE: return OnPSNSetActive(lParam);
case PSN_KILLACTIVE: return OnPSNKillActive(lParam); }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnCommand
//
// Synopsis: Handles the WM_COMMAND message
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnCommand(int id, HWND hwndCtl, UINT codeNotify) { dspDebugOut((DEB_USER3, "CDsPropPageBase::OnCommand - id: %d, code: %x\n", id, codeNotify));
if ((codeNotify == EN_CHANGE) && !m_fInInit) { SetDirty(); } if ((codeNotify == BN_CLICKED) && (id == IDCANCEL)) { //
// Pressing ESC in a multi-line edit control results in this
// WM_COMMAND being sent. Pass it on to the parent (the sheet proc) to
// close the sheet.
//
PostMessage(GetParent(m_hPage), WM_COMMAND, MAKEWPARAM(id, codeNotify), (LPARAM)hwndCtl); } return 0; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::CheckIfPageAttrsWritable
//
// Synopsis: See which attributes are writable by checking if they are in
// the allowedAttributesEffective array.
//
// Notes: The m_rgAttrData array is 1 to 1 with the m_rgpAttrMap array.
//-----------------------------------------------------------------------------
void CDsPropPageBase::CheckIfPageAttrsWritable(void) { DWORD iAllowed;
if (m_fReadOnly || !m_pWritableAttrs) { return; }
for (DWORD iAttrs = 0; iAttrs < m_cAttrs; iAttrs++) { if (m_rgpAttrMap[iAttrs]->AttrInfo.pszAttrName) { for (iAllowed = 0; iAllowed < m_pWritableAttrs->dwNumValues; iAllowed++) { if (_wcsicmp(m_rgpAttrMap[iAttrs]->AttrInfo.pszAttrName, m_pWritableAttrs->pADsValues[iAllowed].CaseIgnoreString) == 0) { ATTR_DATA_SET_WRITABLE(m_rgAttrData[iAttrs]); break; } } } } return; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::CheckIfWritable
//
// Synopsis: See if the attribute is writable by checking if it is in
// the allowedAttributesEffective array.
//
//-----------------------------------------------------------------------------
BOOL CDsPropPageBase::CheckIfWritable(const PWSTR & wzAttr) { BOOL fWritable = FALSE;
if (m_fReadOnly || !m_pWritableAttrs) { return FALSE; }
for (DWORD i = 0; i < m_pWritableAttrs->dwNumValues; i++) { if (_wcsicmp(m_pWritableAttrs->pADsValues[i].CaseIgnoreString, wzAttr) == 0) { fWritable = TRUE; break; } } return fWritable; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnCancel
//
// Synopsis:
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnCancel(void) { return FALSE; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnSetFocus
//
// Synopsis:
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnSetFocus(HWND) { // An application should return zero if it processes this message.
return 1; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnPSNSetActive
//
// Synopsis: Page activation event.
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnPSNSetActive(LPARAM) { SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0); return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnPSNKillActive
//
// Synopsis: Page deactivation event (when other pages cover this one).
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnPSNKillActive(LPARAM) { SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0); return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnDestroy
//
// Synopsis: Exit cleanup
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnDestroy(void) { return 1; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnShowWindow
//
// Synopsis: On dialog window show operations, resizes the view window.
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnShowWindow(void) { return 0; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::GetIDispSpec
//
// Synopsis: If needed, create the interface instance and return the pointer.
//
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::GetIDispSpec(IDsDisplaySpecifier ** ppDispSpec) { HRESULT hr; TRACE2(CDsPropPageBase, GetIDispSpec); if (!m_pDispSpec) { hr = CoCreateInstance(CLSID_DsDisplaySpecifier, NULL, CLSCTX_INPROC_SERVER, IID_IDsDisplaySpecifier, (PVOID *)&m_pDispSpec);
CHECK_HRESULT(hr, return hr);
CStrW strDC;
CComPtr<IDirectoryObject> spDsObj; if (m_pDsObj == NULL) { //
// For the retrieval of the DS Object names
//
FORMATETC fmte = {g_cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM objMedium; hr = m_pWPTDataObj->GetData(&fmte, &objMedium); CHECK_HRESULT(hr, return hr);
LPDSOBJECTNAMES pDsObjectNames = (LPDSOBJECTNAMES)objMedium.hGlobal;
//
// Get the objects path
//
LPWSTR pwzObjADsPath = (PWSTR)ByteOffset(pDsObjectNames, pDsObjectNames->aObjects[0].offsetName);
//
// Bind to the object
//
hr = DSAdminOpenObject(pwzObjADsPath, IID_IDirectoryObject, (PVOID*)&spDsObj);
ReleaseStgMedium(&objMedium);
CHECK_HRESULT(hr, return hr); } else { spDsObj = m_pDsObj; } hr = GetLdapServerName(spDsObj, strDC);
CHECK_HRESULT(hr, return hr);
hr = m_pDispSpec->SetServer(strDC, NULL, NULL, 0);
CHECK_HRESULT(hr, return hr); } if (ppDispSpec) { *ppDispSpec = m_pDispSpec; } return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::GetADsPathname
//
// Synopsis: If needed, create the interface instance and return the pointer.
//
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::GetADsPathname(CComPtr<IADsPathname>& refADsPath) { HRESULT hr;
if (!m_pADsPath) { hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&m_pADsPath);
CHECK_HRESULT(hr, return hr); } refADsPath = m_pADsPath;
return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::SkipPrefix
//
// Synopsis: Given an object name, returns a buffer containing the same
// name without the provider/server prefix. The buffer must be
// freed using delete.
//
// Notes: The fX500 parameter defaults to true and applies whenever the
// input path uses the LDAP provider prefix. The path cracker
// interface can be used to strip the prefix in this case. However,
// if the provider is WINNT, then the path cracker doesn't give the
// desired results so simple string manipulation is used instead.
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::SkipPrefix(PWSTR pwzObj, PWSTR * ppResult, BOOL fX500) { if (fX500) { // Strip of the "LDAP://" prefix using the path cracker.
//
CComPtr<IADsPathname> spPathname; HRESULT hr = GetADsPathname(spPathname);
CHECK_HRESULT(hr, return hr);
hr = spPathname->Set(CComBSTR(pwzObj), ADS_SETTYPE_FULL);
CHECK_HRESULT(hr, return hr);
BSTR bstr;
hr = spPathname->Retrieve(ADS_FORMAT_X500_DN, &bstr);
CHECK_HRESULT(hr, return hr);
if (!AllocWStr(bstr, ppResult)) { SysFreeString(bstr); return E_OUTOFMEMORY; }
SysFreeString(bstr); } else { // Strip off the "WINNT://" prefix.
//
if (wcslen(pwzObj) < 9 || pwzObj[7] != L'/') { // Can't be a valid WINNT name if not at least "WINNT://x"
//
return E_INVALIDARG; } if (!AllocWStr(&pwzObj[8], ppResult)) { return E_OUTOFMEMORY; } }
return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::AddLdapPrefix
//
// Synopsis: Given an object name, returns same name with the LDAP provider
// prefix. The server name is also added by default.
//
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::AddLDAPPrefix(PWSTR pwzObj, CStrW &pstrResult, BOOL fServer) { return ::AddLDAPPrefix(this, pwzObj, pstrResult, fServer); }
//
// Non-class member version.
//
HRESULT AddLDAPPrefix(CDsPropPageBase * pPage, PWSTR pwzObj, CStrW &strResult, BOOL fServer) { HRESULT hr; CComPtr<IADsPathname> spPathCracker; strResult.Empty();
if (pPage) { hr = pPage->GetADsPathname(spPathCracker);
CHECK_HRESULT(hr, return hr); } else { hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&spPathCracker);
CHECK_HRESULT(hr, return hr); }
hr = spPathCracker->Set(CComBSTR(L"LDAP"), ADS_SETTYPE_PROVIDER);
CHECK_HRESULT(hr, return hr);
if (pPage) { CStrW strDC;
CComPtr<IDirectoryObject> spDsObj; if (pPage->m_pDsObj == NULL) { //
// For the retrieval of the DS Object names
//
FORMATETC fmte = {g_cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM objMedium; hr = pPage->m_pWPTDataObj->GetData(&fmte, &objMedium); CHECK_HRESULT(hr, return hr);
LPDSOBJECTNAMES pDsObjectNames = (LPDSOBJECTNAMES)objMedium.hGlobal;
//
// Get the objects path
//
LPWSTR pwzObjADsPath = (PWSTR)ByteOffset(pDsObjectNames, pDsObjectNames->aObjects[0].offsetName);
//
// Bind to the object
//
hr = DSAdminOpenObject(pwzObjADsPath, IID_IDirectoryObject, (PVOID*)&spDsObj);
ReleaseStgMedium(&objMedium);
CHECK_HRESULT(hr, return hr); } else { spDsObj = pPage->m_pDsObj; } hr = GetLdapServerName(spDsObj, strDC);
CHECK_HRESULT(hr, return hr);
hr = spPathCracker->Set(CComBSTR(strDC), ADS_SETTYPE_SERVER);
CHECK_HRESULT(hr, return hr); }
hr = spPathCracker->Set(CComBSTR(pwzObj), ADS_SETTYPE_DN);
CHECK_HRESULT(hr, return hr);
CComBSTR bstr;
hr = spPathCracker->Retrieve((fServer) ? ADS_FORMAT_X500 : ADS_FORMAT_X500_NO_SERVER, &bstr);
CHECK_HRESULT(hr, return hr);
strResult = bstr;
return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::GetObjSel
//
// Synopsis: CoCreates the object picker if needed, returns the pointer.
//
//-----------------------------------------------------------------------------
HRESULT CDsPropPageBase::GetObjSel(IDsObjectPicker ** ppObjSel, PBOOL pfIsInited) { HRESULT hr; TRACE2(CDsPropPageBase,GetObjSel);
if (!m_pObjSel) { hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (PVOID *)&m_pObjSel); if (FAILED(hr)) { REPORT_ERROR(hr, m_hPage); return hr; } }
*ppObjSel = m_pObjSel;
if (pfIsInited) { *pfIsInited = m_fObjSelInited; }
return S_OK; }
#ifdef DO_HELP
#include "helpids.h"
#endif
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::OnHelp
//
// Synopsis: Put up popup help for the control.
//
//-----------------------------------------------------------------------------
LRESULT CDsPropPageBase::OnHelp(LPHELPINFO pHelpInfo) { dspDebugOut((DEB_ITRACE, "WM_HELP: CtrlId = %d, ContextId = 0x%x\n", pHelpInfo->iCtrlId, pHelpInfo->dwContextId)); if (pHelpInfo->iCtrlId < 1 || IDH_NO_HELP == pHelpInfo->dwContextId) { return 0; } WinHelp(m_hPage, DSPROP_HELP_FILE_NAME, HELP_CONTEXTPOPUP, pHelpInfo->dwContextId); #ifdef DONT_DO_THIS
WinHelp((HWND)pHelpInfo->hItemHandle, DSPROP_HELP_FILE_NAME, HELP_WM_HELP, (DWORD)g_aHelpIDs); #endif
return 0; }
//+----------------------------------------------------------------------------
//
// Method: CDsPropPageBase::PageCallback
//
// Synopsis: Callback used to free the CDsPropPageBase object when the
// property sheet has been destroyed.
//
//-----------------------------------------------------------------------------
UINT CALLBACK CDsPropPageBase::PageCallback(HWND hDlg, UINT uMsg, LPPROPSHEETPAGE ppsp) { TRACE_FUNCTION(CDsPropPageBase::PageCallback);
if (uMsg == PSPCB_RELEASE) { //
// Determine instance that invoked this static function
//
CDsPropPageBase * pPage = (CDsPropPageBase *) ppsp->lParam;
//
// Call all function pointers so that they can do any needed cleanup.
//
if (SUCCEEDED(pPage->m_hrInit)) { for (DWORD i = 0; i < pPage->m_cAttrs; i++) { if (pPage->m_rgpAttrMap[i]->pAttrFcn) { (*pPage->m_rgpAttrMap[i]->pAttrFcn)(pPage, pPage->m_rgpAttrMap[i], NULL, 0, &pPage->m_rgAttrData[i], fOnCallbackRelease); } } }
if (IsWindow(pPage->m_hNotifyObj)) { SendMessage(pPage->m_hNotifyObj, WM_ADSPROP_NOTIFY_EXIT, 0, 0); }
// Release on same thread on which created.
//
DO_RELEASE(pPage->m_pWPTDataObj);
//DBG_OUT("-----------------------releasing object in page callback.");
DO_RELEASE(pPage->m_pDsObj);
dspDebugOut((DEB_ITRACE, "Deleting CDsPropPageBase instance 0x%x\n", pPage));
pPage->Release();
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL); }
return TRUE; }
//+----------------------------------------------------------------------------
//
// Member: CDsPropPageBase::IUnknown::QueryInterface
//
// Synopsis: Returns requested interface pointer
//
//-----------------------------------------------------------------------------
STDMETHODIMP CDsPropPageBase::QueryInterface(REFIID riid, void ** ppvObject) { TRACE2(CDsPropPageBase,QueryInterface); if (IID_IUnknown == riid) { *ppvObject = (IUnknown *)this; } else { *ppvObject = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; }
//+----------------------------------------------------------------------------
//
// Member: CDsPropPageBase::IUnknown::AddRef
//
// Synopsis: increments reference count
//
// Returns: the reference count
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDsPropPageBase::AddRef(void) { dspDebugOut((DEB_USER2, "CDsPropPageBase::AddRef refcount going in %d\n", m_uRefs)); return InterlockedIncrement((long *)&m_uRefs); }
//+----------------------------------------------------------------------------
//
// Member: CDsPropPageBase::IUnknown::Release
//
// Synopsis: Decrements the object's reference count and frees it when
// no longer referenced.
//
// Returns: zero if the reference count is zero or non-zero otherwise
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDsPropPageBase::Release(void) { dspDebugOut((DEB_USER2, "CDsPropPageBase::Release ref count going in %d\n", m_uRefs)); unsigned long uTmp; if ((uTmp = InterlockedDecrement((long *)&m_uRefs)) == 0) { delete this; } return uTmp; }
//+----------------------------------------------------------------------------
//
// Function: GetLdapServerName
//
// Synopsis: Given an IDirectoryObject* that supports IADsObjectOptions, it
// returns the server name ADSI is bound to.
//
//-----------------------------------------------------------------------------
HRESULT GetLdapServerName(IUnknown * pDsObj, CStrW& strServer) { HRESULT hr;
strServer.Empty();
CComPtr<IADsObjectOptions> spIADsObjectOptions;
hr = pDsObj->QueryInterface(IID_IADsObjectOptions, (void**)&spIADsObjectOptions);
CHECK_HRESULT(hr, return hr);
CComVariant var; hr = spIADsObjectOptions->GetOption(ADS_OPTION_SERVERNAME, &var);
CHECK_HRESULT(hr, return hr);
dspAssert(var.vt == VT_BSTR); strServer = V_BSTR(&var);
return hr; }
//+----------------------------------------------------------------------------
//
// Function: BindToGCcopyOfObj
//
// Synopsis: Bind to the GC copy of the object.
//
//-----------------------------------------------------------------------------
HRESULT BindToGCcopyOfObj(CDsPropPageBase * pPage, PWSTR pwzObjADsPath, IDirectoryObject ** ppDsObj) { CSmartWStr cswzCleanObj; PWSTR pwzDnsDom; PDOMAIN_CONTROLLER_INFOW pDCInfo; HRESULT hr = pPage->SkipPrefix(pwzObjADsPath, &cswzCleanObj);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
// To bind to a GC, you need to supply the tree root domain name rather
// than the server path because the current DC/domain may not be hosting a
// GC.
//
hr = CrackName(cswzCleanObj, &pwzDnsDom, GET_DNS_DOMAIN_NAME, pPage->GetHWnd());
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
DWORD dwErr = DsGetDcNameW(NULL, pwzDnsDom, NULL,NULL, DS_DIRECTORY_SERVICE_REQUIRED, &pDCInfo); LocalFreeStringW(&pwzDnsDom); hr = HRESULT_FROM_WIN32(dwErr); CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
CComPtr<IADsPathname> spADsPath; long lEscapeMode;
hr = pPage->GetADsPathname(spADsPath);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
spADsPath->get_EscapedMode(&lEscapeMode);
hr = spADsPath->Set(CComBSTR(L"GC"), ADS_SETTYPE_PROVIDER);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
hr = spADsPath->Set(CComBSTR(pDCInfo->DnsForestName), ADS_SETTYPE_SERVER);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
NetApiBufferFree(pDCInfo);
hr = spADsPath->Set(CComBSTR((PCWSTR)cswzCleanObj), ADS_SETTYPE_DN);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
spADsPath->put_EscapedMode(ADS_ESCAPEDMODE_ON);
CComBSTR bstrEscapedPath;
hr = spADsPath->Retrieve(ADS_FORMAT_X500, &bstrEscapedPath);
// restore defaults
spADsPath->Set(CComBSTR(L"LDAP"), ADS_SETTYPE_PROVIDER); spADsPath->put_EscapedMode(lEscapeMode);
CHECK_HRESULT_REPORT(hr, pPage->GetHWnd(), return hr);
dspDebugOut((DEB_ITRACE, "Binding to object at %ws\n", bstrEscapedPath));
hr = DSAdminOpenObject(bstrEscapedPath, IID_IDirectoryObject, (PVOID*)ppDsObj); return hr; }
|