|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 2002
//
// File: dlgcreat.cpp
//
//--------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////
// dlgcreat.cpp
//
// Implementation of dialogs that create new ADs objects.
//
// DIALOGS SUPPORTED
// CCreateNewObjectCnDlg - Dialog asking for "cn" attribute.
// CCreateNewVolumeDlg - Create a new volume "shared folder" object
// CCreateNewComputerDlg - Create a new computer object.
// CCreateNewSiteLinkDlg - Create a new Site Link.
// CCreateNewSiteLinkBridgeDlg - Create a new Site Link Bridge.
//
// DIALOGS NOT YET IMPLEMENTED
// site (validation only)
// organizationalUnit
// localPolicy
// auditingPolicy
//
// HISTORY
// 24-Aug-97 Dan Morin Creation.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "dsutil.h"
#include "uiutil.h"
#include <windowsx.h>
#include <lmaccess.h>
#include <dnsapi.h> // DnsValidateName_W
#include "winsprlp.h" //PublishPrinter
#include "newobj.h" // CNewADsObjectCreateInfo
#include "dlgcreat.h"
extern "C" { #include "lmerr.h" // NET_API_STATUS
#include "icanon.h" // I_NetPathType
}
static const PWSTR g_pszDefaultSecurityDescriptor = L"defaultSecurityDescriptor";
///////////////////////////////////////////////////////////////////////////
// CHPropSheetPageArr
CHPropSheetPageArr::CHPropSheetPageArr() { m_nCount = 0; m_nSize = 4; ULONG nBytes = sizeof(HPROPSHEETPAGE)*m_nSize; m_pArr = (HPROPSHEETPAGE*)malloc(nBytes); if (m_pArr != NULL) { ZeroMemory(m_pArr, nBytes); } }
void CHPropSheetPageArr::AddHPage(HPROPSHEETPAGE hPage) { // see if there is space in the array
if (m_nCount == m_nSize) { // grow the array
int nAlloc = m_nSize*2; HPROPSHEETPAGE* temp = (HPROPSHEETPAGE*)realloc(m_pArr, sizeof(HPROPSHEETPAGE)*nAlloc); if (temp) { m_pArr = temp; ::ZeroMemory(&m_pArr[m_nSize], sizeof(HPROPSHEETPAGE)*m_nSize); m_nSize = nAlloc; } else { m_nSize = 0; } } m_pArr[m_nCount] = hPage; m_nCount++; }
///////////////////////////////////////////////////////////////////////////
// CDsAdminNewObjSiteImpl
BOOL CDsAdminNewObjSiteImpl::_IsPrimarySite() { return (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() == m_pSite); }
STDMETHODIMP CDsAdminNewObjSiteImpl::SetButtons(ULONG nCurrIndex, BOOL bValid) { CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz(); return pWiz->SetWizardButtons(m_pSite, nCurrIndex, bValid); }
STDMETHODIMP CDsAdminNewObjSiteImpl::GetPageCounts(/*OUT*/ LONG* pnTotal, /*OUT*/ LONG* pnStartIndex) { if ( (pnTotal == NULL) || (pnStartIndex == NULL) ) return E_INVALIDARG;
m_pSite->GetSiteManager()->GetWiz()->GetPageCounts(m_pSite, pnTotal,pnStartIndex); return S_OK; }
STDMETHODIMP CDsAdminNewObjSiteImpl::CreateNew(LPCWSTR pszName) { if (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() != m_pSite) { // cannot do if not a primary extension
return E_FAIL; }
CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz(); return pWiz->CreateNewFromPrimaryExtension(pszName); }
STDMETHODIMP CDsAdminNewObjSiteImpl::Commit() { if (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() != m_pSite) { // cannot do if not a primary extension
return E_FAIL; }
if (m_pSite->GetHPageArr()->GetCount() > 1) { // valid only if the primary extension has one page only
return E_FAIL; }
CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz(); if (pWiz->HasFinishPage()) { // if we have the finish page, the finish page must handle it
return E_FAIL; }
// trigger the finish code
return (pWiz->OnFinish() ? S_OK : E_FAIL); }
///////////////////////////////////////////////////////////////////////////
// CWizExtensionSite
// static function
BOOL CALLBACK FAR CWizExtensionSite::_OnAddPage(HPROPSHEETPAGE hsheetpage, LPARAM lParam) { TRACE(L"CWizExtensionSite::_OnAddPage(HPROPSHEETPAGE = 0x%x, lParam = 0x%x)\n", hsheetpage, lParam); CWizExtensionSite* pThis = (CWizExtensionSite*)lParam; pThis->m_pageArray.AddHPage(hsheetpage); return TRUE; }
HRESULT CWizExtensionSite::InitializeExtension(GUID* pGuid) { ASSERT(m_pSiteImplComObject == NULL); ASSERT(pGuid != NULL);
WCHAR szBuf[256]; StringFromGUID2(*(pGuid), szBuf, 256);
TRACE(L"CWizExtensionSite::InitializeExtension( Guid = %s,\n", szBuf);
// create extension COM object
HRESULT hr = ::CoCreateInstance(*pGuid, NULL, CLSCTX_INPROC_SERVER, IID_IDsAdminNewObjExt, (void**)(&m_spIDsAdminNewObjExt)); if (FAILED(hr)) { TRACE(L"CoCreateInstance() failed, hr = 0x%x\n", hr); return hr; }
// create a CDsAdminNewObjSiteImpl COM object
ASSERT(m_pSiteImplComObject == NULL); CComObject<CDsAdminNewObjSiteImpl>::CreateInstance(&m_pSiteImplComObject); if (m_pSiteImplComObject == NULL) { TRACE(L"CComObject<CDsAdminNewObjSiteImpl>::CreateInstance() failed\n"); return E_OUTOFMEMORY; }
// fully construct the object
hr = m_pSiteImplComObject->FinalConstruct(); if (FAILED(hr)) { TRACE(L"CComObject<CDsAdminNewObjSiteImpl>::FinalConstruct failed hr = 0x%x\n", hr);
// ref counting not yet into play, just use operator delete
delete m_pSiteImplComObject; m_pSiteImplComObject = NULL; return hr; } // object has ref count == 0, need to add ref
// no smart pointer, ref counting on m_pSiteImplComObject
IDsAdminNewObj* pDsAdminNewObj = NULL; m_pSiteImplComObject->QueryInterface(IID_IDsAdminNewObj, (void**)&pDsAdminNewObj); ASSERT(pDsAdminNewObj != NULL);
// now ref count == 1
// set back pointer to ourselves
m_pSiteImplComObject->Init(this);
// initialize the object
CCreateNewObjectWizardBase* pWiz = GetSiteManager()->GetWiz(); ASSERT(pWiz != NULL);
CNewADsObjectCreateInfo* pInfo = pWiz->GetInfo(); ASSERT(pInfo != NULL);
// create a temporary struct on the stack
DSA_NEWOBJ_DISPINFO dispinfo; ZeroMemory(&dispinfo, sizeof(DSA_NEWOBJ_DISPINFO));
dispinfo.dwSize = sizeof(DSA_NEWOBJ_DISPINFO); dispinfo.hObjClassIcon = pWiz->GetClassIcon(); dispinfo.lpszWizTitle = const_cast<LPTSTR>(pWiz->GetCaption()); dispinfo.lpszContDisplayName = const_cast<LPTSTR>(pWiz->GetInfo()->GetContainerCanonicalName());
TRACE(_T("dispinfo.dwSize = %d\n"), dispinfo.dwSize); TRACE(_T("dispinfo.hObjClassIcon = 0x%x\n"), dispinfo.hObjClassIcon); TRACE(_T("dispinfo.lpszWizTitle = <%s>\n"), dispinfo.lpszWizTitle); TRACE(_T("dispinfo.lpszContDisplayName = <%s>\n"), dispinfo.lpszContDisplayName);
TRACE(L"\ncalling m_spIDsAdminWizExt->Initialize()\n");
hr = m_spIDsAdminNewObjExt->Initialize( pInfo->m_pIADsContainer, pInfo->GetCopyFromObject(), pInfo->m_pszObjectClass, pDsAdminNewObj, &dispinfo ); if (FAILED(hr)) { TRACE(L"m_spIDsAdminNewObjExt->Initialize() failed hr = 0x%x\n", hr); return hr; }
// collect property pages
return m_spIDsAdminNewObjExt->AddPages(_OnAddPage, (LPARAM)this); }
BOOL CWizExtensionSite::GetSummaryInfo(CString& s) { CComBSTR bstr; HRESULT hr = GetNewObjExt()->GetSummaryInfo(&bstr); if (SUCCEEDED(hr) && bstr != NULL) { s += bstr; s += L"\n"; return TRUE; } return FALSE; }
///////////////////////////////////////////////////////////////////////////
// CWizExtensionSiteManager
HRESULT CWizExtensionSiteManager::CreatePrimaryExtension(GUID* pGuid, IADsContainer*, LPCWSTR) { ASSERT(m_pPrimaryExtensionSite == NULL); m_pPrimaryExtensionSite = new CWizExtensionSite(this); if (m_pPrimaryExtensionSite == NULL) return E_OUTOFMEMORY;
// initialize COM object
HRESULT hr = m_pPrimaryExtensionSite->InitializeExtension(pGuid);
if (FAILED(hr)) { delete m_pPrimaryExtensionSite; m_pPrimaryExtensionSite = NULL; return hr; } // make sure it provided at least a page
if (m_pPrimaryExtensionSite->GetHPageArr()->GetCount() == 0) { hr = E_INVALIDARG; delete m_pPrimaryExtensionSite; m_pPrimaryExtensionSite = NULL; } return hr; }
HRESULT CWizExtensionSiteManager::CreateExtensions(GUID* aCreateWizExtGUIDArr, ULONG nCount, IADsContainer*, LPCWSTR lpszClassName) { HRESULT hr; TRACE(L"CWizExtensionSiteManager::CreateExtensions(_, nCount = %d, _ , lpszClassName = %s\n", nCount,lpszClassName);
for (ULONG i=0; i<nCount; i++) { CWizExtensionSite* pSite = new CWizExtensionSite(this); if (pSite == NULL) { hr = E_OUTOFMEMORY; break; } hr = pSite->InitializeExtension(&(aCreateWizExtGUIDArr[i])); if (FAILED(hr)) { TRACE(L"pSite->InitializeExtension() failed hr = 0x%x", hr); delete pSite; } else { m_extensionSiteList.AddTail(pSite); } } TRACE(L"m_extensionSiteList.GetCount() returned %d\n", m_extensionSiteList.GetCount()); return S_OK; }
UINT CWizExtensionSiteManager::GetTotalHPageCount() { UINT nCount = 0; for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos); nCount += pSite->GetHPageArr()->GetCount(); } // for
return nCount; }
void CWizExtensionSiteManager::SetObject(IADs* pADsObj) { CWizExtensionSite* pPrimarySite = GetPrimaryExtensionSite(); if (pPrimarySite != NULL) { pPrimarySite->GetNewObjExt()->SetObject(pADsObj); }
for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos); HRESULT hr = pSite->GetNewObjExt()->SetObject(pADsObj); ASSERT(SUCCEEDED(hr)); } }
HRESULT CWizExtensionSiteManager::WriteExtensionData(HWND hWnd, ULONG uContext) { for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos); HRESULT hr = pSite->GetNewObjExt()->WriteData(hWnd, uContext); if (FAILED(hr)) return hr; } // for
return S_OK; }
HRESULT CWizExtensionSiteManager::NotifyExtensionsOnError(HWND hWnd, HRESULT hr, ULONG uContext) { for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos); pSite->GetNewObjExt()->OnError(hWnd, hr, uContext); } // for
return S_OK; }
void CWizExtensionSiteManager::GetExtensionsSummaryInfo(CString& s) { // just go through regular extensions
for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos); pSite->GetSummaryInfo(s); } // for
}
/////////////////////////////////////////////////////////////////////
// CCreateNewObjectWizardBase
HWND g_hWndHack = NULL;
int CALLBACK CCreateNewObjectWizardBase::PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM) { if (uMsg == PSCB_INITIALIZED) { ASSERT(::IsWindow(hwndDlg)); g_hWndHack = hwndDlg; DWORD dwStyle = GetWindowLong (hwndDlg, GWL_EXSTYLE); dwStyle &= ~WS_EX_CONTEXTHELP; SetWindowLong (hwndDlg, GWL_EXSTYLE, dwStyle); } return 0; }
CCreateNewObjectWizardBase::CCreateNewObjectWizardBase(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : m_siteManager(this) { memset(&m_psh, 0x0, sizeof(PROPSHEETHEADER)); m_psh.dwSize = sizeof( m_psh ); m_psh.dwFlags = PSH_WIZARD | PSH_PROPTITLE | PSH_USECALLBACK; m_psh.hInstance = _Module.GetModuleInstance(); m_psh.pszCaption = NULL; // will set later on per page
ASSERT(pNewADsObjectCreateInfo != NULL); m_pNewADsObjectCreateInfo = pNewADsObjectCreateInfo;
m_psh.hwndParent = m_pNewADsObjectCreateInfo->GetParentHwnd(); m_psh.pfnCallback = PropSheetProc;
m_hWnd = NULL; m_pFinishPage = NULL; m_hrReturnValue = S_FALSE; // default is cancel
m_hClassIcon = NULL; }
CCreateNewObjectWizardBase::~CCreateNewObjectWizardBase() { if (m_pFinishPage != NULL) delete m_pFinishPage;
if (m_hClassIcon) { DestroyIcon(m_hClassIcon); } }
HRESULT CCreateNewObjectWizardBase::DoModal() { TRACE(L"CCreateNewObjectWizardBase::DoModal()\n"); ASSERT(m_pNewADsObjectCreateInfo != NULL); // load the sheet caption
LoadCaptions();
CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
// load the extensions, if any
HRESULT hr = m_siteManager.CreateExtensions( m_pNewADsObjectCreateInfo->GetCreateInfo()->aWizardExtensions, m_pNewADsObjectCreateInfo->GetCreateInfo()->cWizardExtensions, m_pNewADsObjectCreateInfo->m_pIADsContainer, m_pNewADsObjectCreateInfo->m_pszObjectClass); if (FAILED(hr)) return (hr);
// get the # of primary property pages (excluding the Finish Page)
UINT nBasePagesCount = 0; if (pPrimarySite != NULL) { nBasePagesCount += pPrimarySite->GetHPageArr()->GetCount(); } else { nBasePagesCount += (UINT)m_pages.GetSize(); }
ASSERT(nBasePagesCount > 0);
// get the handle count for the extensions (total for extension property pages)
UINT nExtensionHPagesCount = m_siteManager.GetTotalHPageCount();
// if we have more than one page, add the finish page
UINT nTotalPageCount = nBasePagesCount + nExtensionHPagesCount;
if ( (nBasePagesCount + nExtensionHPagesCount) > 1) { m_pFinishPage = new CCreateNewObjectFinishPage; AddPage(m_pFinishPage); nTotalPageCount++; } // need to allocate a contiguous chunk of memory to pack
// all the property sheet handles
m_psh.nPages = nTotalPageCount; m_psh.phpage = new HPROPSHEETPAGE[nTotalPageCount]; if (m_psh.phpage) { UINT nOffset = 0; // offset where to write to
// add the primary pages first
if (pPrimarySite != NULL) { ASSERT(nBasePagesCount > 0); memcpy(&(m_psh.phpage[nOffset]), pPrimarySite->GetHPageArr()->GetArr(), sizeof(HPROPSHEETPAGE)*nBasePagesCount); nOffset += nBasePagesCount; } else { for (UINT i = 0; i < nBasePagesCount; i++) { CCreateNewObjectPageBase* pPage = m_pages[i]; m_psh.phpage[nOffset] = ::MyCreatePropertySheetPage(&(pPage->m_psp)); nOffset++; } // for
}
// add the extension pages
CWizExtensionSiteList* pSiteList = m_siteManager.GetExtensionSiteList(); for (POSITION pos = pSiteList->GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pSite = pSiteList->GetNext(pos); UINT nCurrCount = pSite->GetHPageArr()->GetCount(); if (nCurrCount > 0) { memcpy(&(m_psh.phpage[nOffset]), pSite->GetHPageArr()->GetArr(), sizeof(HPROPSHEETPAGE)*nCurrCount); nOffset += nCurrCount; } // if
} // for
// add the finish page last, if any
if (m_pFinishPage != NULL) { ASSERT( nOffset == (nTotalPageCount-1) ); m_psh.phpage[nOffset] = ::MyCreatePropertySheetPage(&(m_pFinishPage->m_psp)); }
// finally, invoke the modal sheet
TRACE(L"::PropertySheet(&m_psh) called with m_psh.nPages = %d\n", m_psh.nPages);
::PropertySheet(&m_psh);
delete[] m_psh.phpage; m_psh.phpage = 0; } return m_hrReturnValue; }
void CCreateNewObjectWizardBase::GetPageCounts(CWizExtensionSite* pSite, /*OUT*/ LONG* pnTotal, /*OUT*/ LONG* pnStartIndex) { CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
*pnTotal = 0; // get the # of primary property pages (excluding the Finish Page)
UINT nBasePagesCount = 0; if (pPrimarySite != NULL) { nBasePagesCount += pPrimarySite->GetHPageArr()->GetCount(); } else { nBasePagesCount += (UINT)(m_pages.GetSize()-1); // -1 because we exclude finish page
}
*pnTotal = nBasePagesCount + m_siteManager.GetTotalHPageCount();
if (m_pFinishPage != NULL) { (*pnTotal)++; }
if (pPrimarySite == pSite) { *pnStartIndex = 0; } else { // which site is it?
*pnStartIndex = nBasePagesCount; CWizExtensionSiteList* pSiteList = m_siteManager.GetExtensionSiteList(); for (POSITION pos = pSiteList->GetHeadPosition(); pos != NULL; ) { CWizExtensionSite* pCurrSite = pSiteList->GetNext(pos); if (pCurrSite == pSite) break; // got it, we are done
// keep adding the previous counts
UINT nCurrCount = pCurrSite->GetHPageArr()->GetCount(); (*pnStartIndex) += nCurrCount; } // for
} // else
}
HWND CCreateNewObjectWizardBase::GetWnd() { if (m_hWnd == NULL) { for (int i = 0; i < m_pages.GetSize(); i++) { CCreateNewObjectPageBase* pPage = m_pages[i]; if (pPage->m_hWnd != NULL) { m_hWnd = ::GetParent(pPage->m_hWnd); break; } } // for
} // if
if (m_hWnd == NULL) { m_hWnd = g_hWndHack; g_hWndHack = NULL; }
ASSERT(m_hWnd != NULL); ASSERT(::IsWindow(m_hWnd)); return m_hWnd; }
void CCreateNewObjectWizardBase::AddPage(CCreateNewObjectPageBase* pPage) { m_pages.Add(pPage); pPage->m_pWiz = this; }
HRESULT CCreateNewObjectWizardBase::CreateNewFromPrimaryExtension(LPCWSTR pszName) { // NOTICE: we call with bAllowCopy = FALSE because
// primary extensions will have to handle the copy semantics
// by themselves
// NOTICE: we pass bSilentError = TRUE because
// primary extensions will have to handle the message for
// creation failure
HRESULT hr = GetInfo()->HrCreateNew(pszName, TRUE /* bSilentError */, FALSE /* bAllowCopy */);
GetInfo()->PGetIADsPtr(); m_siteManager.SetObject(GetInfo()->PGetIADsPtr()); return hr; }
void CCreateNewObjectWizardBase::SetWizardButtons( CCreateNewObjectPageBase* pPage, BOOL bValid) { ASSERT(pPage != NULL); if (m_pFinishPage != NULL) { ASSERT(m_pages.GetSize() >= 1); // at least finish page
if (pPage == (CCreateNewObjectPageBase*)m_pFinishPage) { SetWizardButtonsLast(bValid); } else { if (m_pages[0] == pPage) SetWizardButtonsFirst(bValid); else SetWizardButtonsMiddle(bValid); } } else { // single page wizard
ASSERT(m_pages.GetSize() == 1); SetWizardOKCancel(); EnableOKButton(bValid); } }
HRESULT CCreateNewObjectWizardBase::SetWizardButtons(CWizExtensionSite* pSite, ULONG nCurrIndex, BOOL bValid) { UINT nSitePagesCount = pSite->GetHPageArr()->GetCount(); if (nSitePagesCount == 0) { // cannot call from UI less extension
return E_INVALIDARG; } if (nCurrIndex >= nSitePagesCount) { // out of range
return E_INVALIDARG; }
// get the handle count for the secondary extensions (total for extension property pages)
UINT nExtensionHPagesCount = m_siteManager.GetTotalHPageCount();
if (m_siteManager.GetPrimaryExtensionSite() == pSite) { // called from the primary extension
if ((nSitePagesCount == 1) && (nExtensionHPagesCount == 0)) { // single page, so we have the OK/Cancel buttons
SetWizardOKCancel(); EnableOKButton(bValid); } else { // multiple pages
if (nCurrIndex == 0) SetWizardButtonsFirst(bValid); else SetWizardButtonsMiddle(bValid); } } else { // called from a secondary extension, we must have the finish page and
// some primary extension or primary page(s), so we are always in the middle
ASSERT(m_pFinishPage != NULL); SetWizardButtonsMiddle(bValid); } return S_OK; }
void CCreateNewObjectWizardBase::SetObjectForExtensions(CCreateNewObjectPageBase* pPage) { ASSERT(pPage != NULL); ASSERT(pPage != m_pFinishPage); UINT nPages = (UINT)m_pages.GetSize();
if (m_pFinishPage != NULL) { ASSERT(nPages > 1); // at least 1 page + finish
if (pPage == m_pages[nPages-2]) { // this is the last primary page
// give the ADSI object pointer to all the extensions
m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr()); } } else { // this is the case of a single primary page, but at least one
// UI-less extension (i.e. no finish page)
ASSERT(nPages == 1); // just this page, no finish page
if (pPage == m_pages[0]) { // this is the only primary page
// give the ADSI object pointer to all the extensions
m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr()); } } // if
}
HRESULT CCreateNewObjectWizardBase::WriteData(ULONG uContext) { HRESULT hr = S_OK; CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite(); if (uContext == DSA_NEWOBJ_CTX_POSTCOMMIT) { // call the post commit on all the data primary pages
if (pPrimarySite != NULL) { hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), uContext); if (FAILED(hr)) hr = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, uContext); } else { for (int i = 0; i < m_pages.GetSize(); i++) { CCreateNewObjectPageBase* pPage = m_pages[i]; if (pPage != m_pFinishPage) { CCreateNewObjectDataPage* pDataPage = dynamic_cast<CCreateNewObjectDataPage*>(pPage); ASSERT(pDataPage != NULL); hr = pDataPage->OnPostCommit(); if (FAILED(hr)) { m_siteManager.NotifyExtensionsOnError(GetWnd(), hr, uContext); break; } } } // for
} // if
} // if
if (uContext == DSA_NEWOBJ_CTX_PRECOMMIT) { // call the pre commit on all the data primary pages
// (As per Exchange request)
if (pPrimarySite != NULL) { hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), uContext); if (FAILED(hr)) hr = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, uContext); } }
if (SUCCEEDED(hr)) { // call the extensions to write data
hr = m_siteManager.WriteExtensionData(GetWnd(), uContext); if (FAILED(hr)) { if (pPrimarySite != NULL) { pPrimarySite->GetNewObjExt()->OnError(GetWnd(),hr, uContext); } m_siteManager.NotifyExtensionsOnError(GetWnd(), hr, uContext); } } return hr; }
void CCreateNewObjectWizardBase::GetSummaryInfoHeader(CString& s) { // by default, add just the name of object
CString szFmt; szFmt.LoadString(IDS_s_CREATE_NEW_SUMMARY_NAME); CString szBuffer; szBuffer.Format((LPCWSTR)szFmt, GetInfo()->GetName()); s += szBuffer; }
void CCreateNewObjectWizardBase::GetSummaryInfo(CString& s) { // if we have a primary site, tell it to do it all
CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite(); if (pPrimarySite != NULL) { // the primary extension has a chance to override
// the default behavior
if (!pPrimarySite->GetSummaryInfo(s)) { // failed, we put up the default header
GetSummaryInfoHeader(s); } } else { GetSummaryInfoHeader(s);
// go first through our pages
for (int i = 0; i < m_pages.GetSize(); i++) { CCreateNewObjectPageBase* pPage = m_pages[i]; if (pPage != m_pFinishPage) { CString szTemp; pPage->GetSummaryInfo(szTemp); if (!szTemp.IsEmpty()) { s += L"\n"; s += szTemp; } } } // for
s += L"\n";
} // if
// go through the extension pages
m_siteManager.GetExtensionsSummaryInfo(s); }
HRESULT CCreateNewObjectWizardBase::RecreateObject() { CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
// remove object from backend
HRESULT hr = m_pNewADsObjectCreateInfo->HrDeleteFromBackend(); if (FAILED(hr)) { ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() != NULL); // could not delete from backend (possibly for lack of delete right)
HRESULT hrDeleteFail = E_FAIL; if (pPrimarySite != NULL) { hrDeleteFail = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, DSA_NEWOBJ_CTX_CLEANUP); }
if (FAILED(hrDeleteFail)) { // put out a warning
ReportErrorEx(m_hWnd,IDS_CANT_DELETE_BAD_NEW_OBJECT,S_OK, MB_OK, NULL, 0); } return hr; }
// tell all the extensions to release the temporary object
ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() == NULL); m_siteManager.SetObject(NULL);
if (pPrimarySite != NULL) { hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), DSA_NEWOBJ_CTX_CLEANUP); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; } else { // collect data from the primary pages
// the first of them will do a create new
for (int i = 0; i < m_pages.GetSize(); i++) { CCreateNewObjectPageBase* pPage = m_pages[i]; if (pPage != m_pFinishPage) { hr = ((CCreateNewObjectDataPage*)pPage)->OnPreCommit(TRUE); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; // some of the primary pages failed
} } // for
} // tell the extensions about the new object
ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() != NULL); m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr());
// collect data from extensions
hr = WriteData(DSA_NEWOBJ_CTX_CLEANUP); return hr; }
BOOL CCreateNewObjectWizardBase::OnFinish() { CWaitCursor wait;
BOOL bRetVal = TRUE; // default is dismiss
// before doing the commit give the extensions a chance to
// write their data
BOOL bPostCommit = FALSE; HRESULT hr = WriteData(DSA_NEWOBJ_CTX_PRECOMMIT); if (FAILED(hr)) return FALSE; // do not dismiss
// do the commit to the backend
hr = m_pNewADsObjectCreateInfo->HrSetInfo(TRUE /*fSilentError*/); if (FAILED(hr)) { // if present, the primary extension will have to handle the failure
// by displaying an error message
HRESULT hrSetInfoFail = E_FAIL; CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite(); if (pPrimarySite != NULL) { hrSetInfoFail = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, DSA_NEWOBJ_CTX_COMMIT); }
if (FAILED(hrSetInfoFail)) { // either no primary extension or not handled by it,
// use the internal handler
OnFinishSetInfoFailed(hr); } return FALSE; // do not dismiss
}
// start the post commit phase
bPostCommit = TRUE; m_pNewADsObjectCreateInfo->SetPostCommit(bPostCommit); hr = m_pNewADsObjectCreateInfo->HrAddDefaultAttributes(); if (FAILED(hr)) return FALSE; // do not dismiss
BOOL bNeedDeleteFromBackend = FALSE;
if (SUCCEEDED(hr)) { // the commit went well, need to tell the primary pages and
// the extensions to write
hr = WriteData(DSA_NEWOBJ_CTX_POSTCOMMIT); if (FAILED(hr)) { bNeedDeleteFromBackend = TRUE; } } m_pNewADsObjectCreateInfo->SetPostCommit(/*bPostCommit*/FALSE); // restore
// failed the post commit, try to remove from
// the backend and recreate a valid temporary object
if (bNeedDeleteFromBackend) { ASSERT(bRetVal); // the wizard would be hosed
hr = RecreateObject(); if (FAILED(hr)) { // we are really up creek
bRetVal = TRUE; //bail out, the m_hrReturnValue will be set below
hr = S_FALSE; // avoid error message in the snapin
} else { // we deleted the committed object, we can keep the wizard up
return FALSE; } }
if (bRetVal) { // we are actually dismissing the wizard,
// set the hr value that will be returned by the modal wizard call itself
m_hrReturnValue = hr; } return bRetVal; }
void CCreateNewObjectWizardBase::OnFinishSetInfoFailed(HRESULT hr) { PVOID apv[1] = {(LPWSTR)m_pNewADsObjectCreateInfo->GetName()}; ReportErrorEx(GetWnd(),IDS_12_GENERIC_CREATION_FAILURE,hr, MB_OK | MB_ICONERROR, apv, 1); }
void CCreateNewObjectWizardBase::LoadCaptions() { // compute the caption only the first time
if (m_szCaption.IsEmpty()) { LPCTSTR pszObjectClass = GetInfo()->m_pszObjectClass; ASSERT(pszObjectClass != NULL); ASSERT(lstrlen(pszObjectClass) > 0); WCHAR szFriendlyName[256]; GetInfo()->GetBasePathsInfo()->GetFriendlyClassName(pszObjectClass, szFriendlyName, 256); UINT nCaptionRes = (GetInfo()->GetCopyFromObject() == NULL) ? IDS_s_CREATE_NEW : IDS_s_COPY;
m_szCaption.Format(nCaptionRes, szFriendlyName); ASSERT(!m_szCaption.IsEmpty()); } if (m_szOKButtonCaption.IsEmpty()) { m_szOKButtonCaption.LoadString(IDS_WIZARD_OK); } }
HICON CCreateNewObjectWizardBase::GetClassIcon() { if (m_hClassIcon == NULL) { DWORD dwFlags = DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON; if (GetInfo()->IsContainer()) dwFlags |= DSGIF_DEFAULTISCONTAINER; m_hClassIcon = GetInfo()->GetBasePathsInfo()->GetIcon(GetInfo()->m_pszObjectClass, dwFlags, 32,32); } return m_hClassIcon; }
HRESULT CCreateNewObjectWizardBase::InitPrimaryExtension() { ASSERT(m_pNewADsObjectCreateInfo != NULL);
HRESULT hr = m_siteManager.CreatePrimaryExtension( &(m_pNewADsObjectCreateInfo->GetCreateInfo()->clsidWizardPrimaryPage), m_pNewADsObjectCreateInfo->m_pIADsContainer, m_pNewADsObjectCreateInfo->m_pszObjectClass); return hr; }
/////////////////////////////////////////////////////////////////////
// CIconCtrl
BEGIN_MESSAGE_MAP(CIconCtrl, CStatic) ON_WM_PAINT() END_MESSAGE_MAP()
void CIconCtrl::OnPaint() { PAINTSTRUCT ps; CDC* pDC = BeginPaint(&ps); if (m_hIcon != NULL) pDC->DrawIcon(0, 0, m_hIcon); EndPaint(&ps); }
/////////////////////////////////////////////////////////////////////
// CCreateNewObjectPageBase
#define WM_FORMAT_CAPTION (WM_USER+1)
BEGIN_MESSAGE_MAP(CCreateNewObjectPageBase, CPropertyPageEx_Mine) ON_MESSAGE(WM_FORMAT_CAPTION, OnFormatCaption ) END_MESSAGE_MAP()
CCreateNewObjectPageBase::CCreateNewObjectPageBase(UINT nIDTemplate) : CPropertyPageEx_Mine(nIDTemplate) { m_pWiz = NULL; }
BOOL CCreateNewObjectPageBase::OnInitDialog() { CPropertyPageEx_Mine::OnInitDialog();
// set the name of the container
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); SetDlgItemText(IDC_EDIT_CONTAINER, pNewADsObjectCreateInfo->GetContainerCanonicalName());
// set the class icon
VERIFY(m_iconCtrl.SubclassDlgItem(IDC_STATIC_ICON, this)); m_iconCtrl.SetIcon(GetWiz()->GetClassIcon());
return TRUE; }
BOOL CCreateNewObjectPageBase::OnSetActive() { BOOL bRet = CPropertyPageEx_Mine::OnSetActive(); PostMessage(WM_FORMAT_CAPTION); return bRet; }
LONG CCreateNewObjectPageBase::OnFormatCaption(WPARAM, LPARAM) { // set the title of the Wizard window
HWND hWndSheet = ::GetParent(m_hWnd); ASSERT(::IsWindow(hWndSheet)); ::SetWindowText(hWndSheet, (LPCWSTR)GetWiz()->GetCaption()); return 0; }
/////////////////////////////////////////////////////////////////////
// CCreateNewObjectDataPage
CCreateNewObjectDataPage::CCreateNewObjectDataPage(UINT nIDTemplate) : CCreateNewObjectPageBase(nIDTemplate) { m_bFirstTimeGetDataCalled = TRUE; }
BOOL CCreateNewObjectDataPage::OnSetActive() { BOOL bValid = FALSE; if (m_bFirstTimeGetDataCalled) { // first time we call, pass the IADs* pIADsCopyFrom pointer we copy from
IADs* pIADsCopyFrom = GetWiz()->GetInfo()->GetCopyFromObject(); bValid = GetData(pIADsCopyFrom); m_bFirstTimeGetDataCalled = FALSE; } else { bValid = GetData(NULL); }
GetWiz()->SetWizardButtons(this, bValid); return CCreateNewObjectPageBase::OnSetActive(); }
LRESULT CCreateNewObjectDataPage::OnWizardNext() { CWaitCursor wait; // move to next page only if SetData() succeeded
if (SUCCEEDED(SetData())) { // if this is the last primary page, notify the extensions
GetWiz()->SetObjectForExtensions(this); return 0; // move to the next page
} return -1; // do not advance
}
LRESULT CCreateNewObjectDataPage::OnWizardBack() { // move to prev page only if SetData() succeeded
return SUCCEEDED(SetData()) ? 0 : -1; }
BOOL CCreateNewObjectDataPage::OnKillActive() { // we do not know what page it will jump to, so we
// set it to the most sensible choice for an extension
GetWiz()->SetWizardButtonsMiddle(TRUE); return CCreateNewObjectPageBase::OnKillActive(); }
BOOL CCreateNewObjectDataPage::OnWizardFinish() { // this method is called only if this page is the
// last one (that is this is the only primary native page
// and there are no pages from secondary extensions)
if (FAILED(SetData())) return FALSE;
// notify the extensions of a new IADs* pointer
GetWiz()->SetObjectForExtensions(this);
return GetWiz()->OnFinish(); }
/////////////////////////////////////////////////////////////////////
// CCreateNewObjectFinishPage
BEGIN_MESSAGE_MAP(CCreateNewObjectFinishPage, CCreateNewObjectPageBase) ON_EN_SETFOCUS(IDC_EDIT_SUMMARY, OnSetFocusEdit) END_MESSAGE_MAP()
CCreateNewObjectFinishPage::CCreateNewObjectFinishPage() : CCreateNewObjectPageBase(CCreateNewObjectFinishPage::IDD) { m_bNeedSetFocus = FALSE; }
BOOL CCreateNewObjectFinishPage::OnSetActive() { // need to collect all info from pages
// and put it in the summary info edit box
CString szBuf; GetWiz()->GetSummaryInfo(szBuf); WriteSummary(szBuf); m_bNeedSetFocus = TRUE;
GetWiz()->SetWizardButtons(this, TRUE); return CCreateNewObjectPageBase::OnSetActive(); }
BOOL CCreateNewObjectFinishPage::OnKillActive() { GetWiz()->SetWizardButtonsMiddle(TRUE); return CCreateNewObjectPageBase::OnKillActive(); }
BOOL CCreateNewObjectFinishPage::OnWizardFinish() { return GetWiz()->OnFinish(); }
void CCreateNewObjectFinishPage::OnSetFocusEdit() { CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SUMMARY); pEdit->SetSel(-1,0, TRUE); if (m_bNeedSetFocus) { m_bNeedSetFocus = FALSE; TRACE(_T("Resetting Focus\n"));
HWND hwndSheet = ::GetParent(m_hWnd); ASSERT(::IsWindow(hwndSheet)); HWND hWndFinishCtrl =::GetDlgItem(hwndSheet, 0x3025); ASSERT(::IsWindow(hWndFinishCtrl)); ::SetFocus(hWndFinishCtrl); } }
void CCreateNewObjectFinishPage::WriteSummary(LPCWSTR lpszSummaryText) { // allocate temporary buffer
size_t nLen = wcslen(lpszSummaryText) + 1; WCHAR* pBuf = new WCHAR[nLen*2]; if (!pBuf) { return; }
// change '\n' into '\r\n' sequence
LPCTSTR pSrc = lpszSummaryText; TCHAR* pDest = pBuf; while (*pSrc != NULL) { if ( ( pSrc != lpszSummaryText) && (*(pSrc-1) != TEXT('\r')) && (*pSrc == TEXT('\n')) ) { *(pDest++) = '\r'; } *(pDest++) = *(pSrc++); } *pDest = NULL; // NULL terminate the destination buffer
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SUMMARY); pEdit->SetWindowText(pBuf); delete[] pBuf; pBuf = 0; }
///////////////////////////////////////////////////////////////////
// CCreateNewNamedObjectPage
BEGIN_MESSAGE_MAP(CCreateNewNamedObjectPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange) END_MESSAGE_MAP()
BOOL CCreateNewNamedObjectPage::ValidateName(LPCTSTR) { return TRUE; }
BOOL CCreateNewNamedObjectPage::OnInitDialog() { CCreateNewObjectDataPage::OnInitDialog();
Edit_LimitText (GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, MAX_RDN_SIZE); SetDlgItemText(IDC_EDIT_OBJECT_NAME, GetWiz()->GetInfo()->m_strDefaultObjectName); return TRUE; }
BOOL CCreateNewNamedObjectPage::GetData(IADs*) { return !m_strName.IsEmpty(); }
void CCreateNewNamedObjectPage::OnNameChange() { GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strName); m_strName.TrimLeft(); m_strName.TrimRight(); // Enable the OK button only if the name is not empty
GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty()); }
HRESULT CCreateNewNamedObjectPage::SetData(BOOL) { if ( !ValidateName( m_strName ) ) return E_INVALIDARG; // Store the object name in the temporary storage
HRESULT hr = GetWiz()->GetInfo()->HrCreateNew(m_strName); return hr; }
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW CN UNC WIZARD
BEGIN_MESSAGE_MAP(CCreateNewVolumePage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange) ON_EN_CHANGE(IDC_EDIT_UNC_PATH, OnPathChange) END_MESSAGE_MAP()
CCreateNewVolumePage::CCreateNewVolumePage() : CCreateNewObjectDataPage(CCreateNewVolumePage::IDD) { }
BOOL CCreateNewVolumePage::OnInitDialog() { CCreateNewObjectDataPage::OnInitDialog(); SetDlgItemText(IDC_EDIT_OBJECT_NAME, GetWiz()->GetInfo()->m_strDefaultObjectName); Edit_LimitText(GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, 64); Edit_LimitText (GetDlgItem(IDC_EDIT_UNC_PATH)->m_hWnd, MAX_PATH - 1); return TRUE; }
void CCreateNewVolumePage::OnNameChange() { GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strName); m_strName.TrimLeft(); m_strName.TrimRight(); _UpdateUI(); }
void CCreateNewVolumePage::OnPathChange() { GetDlgItemText(IDC_EDIT_UNC_PATH, OUT m_strUncPath); m_strUncPath.TrimLeft(); m_strUncPath.TrimRight(); _UpdateUI(); }
void CCreateNewVolumePage::_UpdateUI() { //
// Enable the OK button only if both name and path are not empty and it is a valid
// UNC path
//
BOOL bIsValidShare = FALSE; DWORD dwPathType = 0; if (!I_NetPathType(NULL, (PWSTR)(PCWSTR)m_strUncPath, &dwPathType, 0) && dwPathType == ITYPE_UNC) { bIsValidShare = TRUE; }
GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty() && bIsValidShare); }
BOOL CCreateNewVolumePage::GetData(IADs*) { return !m_strName.IsEmpty() && !m_strUncPath.IsEmpty(); }
HRESULT CCreateNewVolumePage::SetData(BOOL) { // Store the object name in the temporary storage
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); HRESULT hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName); if (FAILED(hr)) { return hr; } hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_uNCName), m_strUncPath); ASSERT(SUCCEEDED(hr)); return hr; }
CCreateNewVolumeWizard:: CCreateNewVolumeWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); }
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW PRINT QUEUE WIZARD
BEGIN_MESSAGE_MAP(CCreateNewPrintQPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_UNC_PATH, OnPathChange) END_MESSAGE_MAP()
CCreateNewPrintQPage::CCreateNewPrintQPage() : CCreateNewObjectDataPage(CCreateNewPrintQPage::IDD) { }
BOOL CCreateNewPrintQPage::GetData(IADs*) { CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
CComPtr<IADs> spObj; HRESULT hr = pNewADsObjectCreateInfo->m_pIADsContainer->QueryInterface( IID_IADs, (void **)&spObj); if (SUCCEEDED(hr)) { CComBSTR bsPath; spObj->get_ADsPath (&bsPath); m_strContainer = bsPath; } return FALSE; }
void CCreateNewPrintQPage::OnPathChange() { GetDlgItemText(IDC_EDIT_UNC_PATH, OUT m_strUncPath); m_strUncPath.TrimLeft(); m_strUncPath.TrimRight(); _UpdateUI(); }
void CCreateNewPrintQPage::_UpdateUI() { // Enable the OK button only if both name and path are not empty
GetWiz()->SetWizardButtons(this, !m_strUncPath.IsEmpty()); }
HRESULT CCreateNewPrintQPage::SetData(BOOL bSilent) { CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
CWaitCursor CWait;
HINSTANCE hWinspool = NULL; BOOL (*pfnPublishPrinter)(HWND, PCWSTR, PCWSTR, PCWSTR, PWSTR *, DWORD); hWinspool = LoadLibrary(L"Winspool.drv"); if (!hWinspool) { INT Result2 = GetLastError(); if (!bSilent) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath}; ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); } return HRESULT_FROM_WIN32(Result2); } pfnPublishPrinter = (BOOL (*)(HWND, PCWSTR, PCWSTR, PCWSTR, PWSTR *, DWORD)) GetProcAddress(hWinspool, (LPCSTR) 217); if (!pfnPublishPrinter) { INT Result2 = GetLastError(); if (!bSilent) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath}; ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); } FreeLibrary(hWinspool); return HRESULT_FROM_WIN32(Result2); }
BOOL Result = pfnPublishPrinter ( m_hWnd, (LPCWSTR)m_strUncPath, (LPCWSTR)m_strContainer, (LPCWSTR)NULL, &m_pwszNewObj, PUBLISHPRINTER_QUERY);
FreeLibrary(hWinspool);
if (!Result) { INT Result2 = GetLastError(); if (Result2 == ERROR_INVALID_LEVEL) { if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_CANT_CREATE_NT5_PRINTERS,S_OK, MB_OK, NULL, 0); } } else { if (!bSilent) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath}; ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); } } return HRESULT_FROM_WIN32(Result2); } else { IADs* pIADs = NULL; HRESULT hr = DSAdminOpenObject(m_pwszNewObj, IID_IADs, (void **)&pIADs, TRUE /*bServer*/); GlobalFree(m_pwszNewObj); m_pwszNewObj = NULL;
if (SUCCEEDED(hr)) { pNewADsObjectCreateInfo->SetIADsPtr(pIADs); pIADs->Release(); // addref'd by the above Set()
} else { if (!bSilent) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath}; ReportErrorEx (m_hWnd,IDS_12_FAILED_TO_ACCESS_PRINTER,hr, MB_OK | MB_ICONERROR, apv, 1); } return hr; }
} return S_OK; }
CCreateNewPrintQWizard:: CCreateNewPrintQWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); }
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW COMPUTER WIZARD
BEGIN_MESSAGE_MAP(CCreateNewComputerPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_DNS_NAME, OnNameChange) ON_EN_CHANGE(IDC_EDIT_SAM_NAME, OnSamNameChange) ON_BN_CLICKED(IDC_CHANGE_PRINCIPAL_BUTTON, OnChangePrincipalButton) END_MESSAGE_MAP()
CCreateNewComputerPage::CCreateNewComputerPage() : CCreateNewObjectDataPage(CCreateNewComputerPage::IDD) { }
BOOL CCreateNewComputerPage::OnInitDialog() { Edit_LimitText (GetDlgItem(IDC_EDIT_DNS_NAME)->m_hWnd, 63); Edit_LimitText (GetDlgItem(IDC_EDIT_SAM_NAME)->m_hWnd, 15);
CCreateNewObjectDataPage::OnInitDialog();
CString szDefault; szDefault.LoadString(IDS_NEW_COMPUTER_PRINCIPAL_DEFAULT); SetDlgItemText(IDC_PRINCIPAL_EDIT, szDefault);
return TRUE; }
BOOL CCreateNewComputerPage::GetData(IADs*) { return !m_strName.IsEmpty(); //we need a computer name
}
inline LPWSTR WINAPI MyA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp) { ATLASSERT(lpa != NULL); ATLASSERT(lpw != NULL); // verify that no illegal character present
// since lpw was allocated based on the size of lpa
// don't worry about the number of chars
lpw[0] = '\0'; MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); return lpw; }
#define A2W_OEM(lpa) (\
((_lpaMine = lpa) == NULL) ? NULL : (\ _convert = (lstrlenA(_lpaMine)+1),\ MyA2WHelper((LPWSTR) alloca(_convert*2), _lpaMine, _convert, CP_OEMCP)))
void _UnicodeToOemConvert(IN PCWSTR pszUnicode, OUT CString& szOemUnicode) { USES_CONVERSION;
// add this for the macro to work
PCSTR _lpaMine = NULL;
// convert to CHAR OEM
int nLen = lstrlen(pszUnicode); PSTR pszOemAnsi = new CHAR[3*(nLen+1)]; // more, to be sure...
if (pszOemAnsi) { CharToOem(pszUnicode, pszOemAnsi);
// convert it back to WCHAR on OEM CP
szOemUnicode = A2W_OEM(pszOemAnsi); delete[] pszOemAnsi; pszOemAnsi = 0; } }
void CCreateNewComputerPage::OnNameChange() { GetDlgItemText(IDC_EDIT_DNS_NAME, OUT m_strName); m_strName.TrimLeft(); m_strName.TrimRight(); // generate a SAM account name from the name
CONST DWORD computerNameLen = 32; DWORD Len = computerNameLen; WCHAR szDownLevel[computerNameLen];
if (m_strName.IsEmpty()) { Len = 0; } else { // generate the SAM account name from CN
// run through the OEM conversion, just to
// behave the same way as typing in the OEM
// edit box
CString szOemUnicode; _UnicodeToOemConvert(m_strName, szOemUnicode); //TRACE(L"szOemUnicode = %s\n", (LPCWSTR)szOemUnicode);
// run through the DNS validation
if (!DnsHostnameToComputerName((LPWSTR)(LPCWSTR)szOemUnicode, szDownLevel, &Len)) { Len = 0; } }
if (Len > 0) { m_strSamName = szDownLevel; } else { m_strSamName.Empty(); }
SetDlgItemText(IDC_EDIT_SAM_NAME, m_strSamName);
GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty() && !m_strSamName.IsEmpty()); }
void CCreateNewComputerPage::OnSamNameChange() { GetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strSamName);
GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty() && !m_strSamName.IsEmpty()); }
HRESULT CCreateNewComputerPage::_ValidateSamName() { ASSERT(!m_strSamName.IsEmpty());
// prep name for error if needed
PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName}; CONST DWORD computerNameLen = 32; DWORD Len = computerNameLen; WCHAR szDownLevel[computerNameLen]; UINT status = 0; UINT answer = IDNO;
NET_API_STATUS netstatus = I_NetNameValidate( 0, (LPWSTR)(LPCWSTR)m_strSamName, NAMETYPE_COMPUTER, 0); if (netstatus != NERR_Success) { ReportErrorEx(m_hWnd,IDS_12_INVALID_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(netstatus), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); return HRESULT_FROM_WIN32(netstatus); }
// NTRAID#NTBUG9-472020-2002/01/16-ronmart-switched from DnsValidateDnsName to DnsValidateName
// NTRAID#NTBUG9-651865-2002/07/16-JeffJon-When Ron made the switch to use DnsValidateName
// the DnsNameHostnameLabel flag should have been used instead of the DnsNameDomainLabel flag
status = DnsValidateName_W((LPWSTR)(LPCWSTR)m_strSamName, DnsNameHostnameLabel); if (status == DNS_ERROR_NON_RFC_NAME) { answer = ReportErrorEx(m_hWnd,IDS_12_NON_RFC_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(status), MB_YESNO | MB_ICONWARNING, apv, 1, 0, FALSE); if (answer == IDNO) { return HRESULT_FROM_WIN32(status); } } else { if (status != ERROR_SUCCESS) { ReportErrorEx(m_hWnd,IDS_12_INVALID_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(status), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); return HRESULT_FROM_WIN32(status); } }
if (m_strSamName.Find(L".") >= 0) { ReportErrorEx(m_hWnd,IDS_12_SAM_COMPUTER_NAME_DOTTED,S_OK/*ignored*/, MB_OK | MB_ICONERROR, apv, 1); return HRESULT_FROM_WIN32(DNS_STATUS_DOTTED_NAME); }
// further validate the SAM account name, to make sure it did not get changed
BOOL bValidSamName = DnsHostnameToComputerName((LPWSTR)(LPCWSTR)m_strSamName, szDownLevel, &Len);
TRACE(L"DnsHostnameToComputerName(%s) returned szDownLevel = %s and bValidSamName = 0x%x\n", (LPCWSTR)m_strSamName, szDownLevel, bValidSamName);
if (!bValidSamName || (_wcsicmp(m_strSamName, szDownLevel) != 0)) { ReportErrorEx(m_hWnd,IDS_12_SAM_COMPUTER_NAME_NOT_VALIDATED, S_OK/*ignored*/, MB_OK | MB_ICONERROR, apv, 1);
return E_FAIL; }
return S_OK; }
HRESULT CCreateNewComputerPage::_ValidateName() { // prep name for error if needed
PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName}; UINT status = 0; UINT answer = IDNO;
NET_API_STATUS netstatus = I_NetNameValidate( 0, (LPWSTR)(LPCWSTR)m_strName, NAMETYPE_COMPUTER, 0); if (netstatus != NERR_Success) { ReportErrorEx(m_hWnd,IDS_12_INVALID_COMPUTER_NAME,HRESULT_FROM_WIN32(netstatus), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); return HRESULT_FROM_WIN32(netstatus); }
// NTRAID#NTBUG9-472020-2002/01/16-ronmart-switched from DnsValidateDnsName to DnsValidateName
// NTRAID#NTBUG9-651865-2002/07/16-JeffJon-When Ron made the switch to use DnsValidateName
// the DnsNameHostnameLabel flag should have been used instead of the DnsNameDomainLabel flag
status = DnsValidateName_W((LPWSTR)(LPCWSTR)m_strName, DnsNameHostnameLabel);
if (status == DNS_ERROR_NON_RFC_NAME) { answer = ReportErrorEx(m_hWnd,IDS_12_NON_RFC_COMPUTER_NAME,HRESULT_FROM_WIN32(status), MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, apv, 1, 0, FALSE); if (answer == IDNO) { return HRESULT_FROM_WIN32(status); } } else { if (status != ERROR_SUCCESS) { ReportErrorEx(m_hWnd,IDS_12_INVALID_COMPUTER_NAME,HRESULT_FROM_WIN32(status), MB_OK | MB_ICONERROR, apv, 1, 0, FALSE); return HRESULT_FROM_WIN32(status); } }
if (m_strName.Find(L".") >= 0) { ReportErrorEx(m_hWnd,IDS_12_COMPUTER_NAME_DOTTED,S_OK/*ignored*/, MB_OK | MB_ICONERROR, apv, 1); return HRESULT_FROM_WIN32(DNS_STATUS_DOTTED_NAME); } return S_OK; }
HRESULT CCreateNewComputerPage::SetData(BOOL) { CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
// name validation
HRESULT hr = _ValidateName(); if (FAILED(hr)) { TRACE(L"_ValidateName() failed\n"); return hr; }
hr = _ValidateSamName(); if (FAILED(hr)) { TRACE(L"_ValidateSamName() failed\n"); return hr; }
// do object creation
hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName); if (FAILED(hr)) { return hr; }
// create the ADSI attribute by adding $ at the end
CString szTemp = m_strSamName + L"$"; hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_samAccountName), szTemp);
// set the account type and the desired flags
LONG lFlags = UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD; if (IsDlgButtonChecked(IDC_NT4_BDC_CHECK)) { lFlags |= UF_SERVER_TRUST_ACCOUNT; } else { lFlags |= UF_WORKSTATION_TRUST_ACCOUNT; }
hr = pNewADsObjectCreateInfo->HrAddVariantLong(CComBSTR(gsz_userAccountControl), lFlags);
ASSERT(SUCCEEDED(hr));
return hr; }
HRESULT CCreateNewComputerPage::OnPostCommit(BOOL bSilent) { HRESULT hr; CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); IADs * pIADs = NULL; IADsUser * pIADsUser = NULL; BOOL bSetPasswordOK = FALSE; BOOL bSetSecurityOK = FALSE;
//prepare for error message, if needed
PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName}; // The object was created successfully, so try to update some other attributes
// try to set the password
pIADs = pNewADsObjectCreateInfo->PGetIADsPtr(); ASSERT(pIADs != NULL); hr = pIADs->QueryInterface(IID_IADsUser, OUT (void **)&pIADsUser); if (FAILED(hr) && !bSilent) { ASSERT(FALSE); // should never get here in normal operations
ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr, MB_OK | MB_ICONERROR, NULL, 0); } else { ASSERT(pIADsUser != NULL); if (IsDlgButtonChecked(IDC_NT4_CHECK)) { // NT 4 password, "$<computername>"
CString szPassword; szPassword = m_strSamName; szPassword = szPassword.Left(14); INT loc = szPassword.Find(L"$"); if (loc > 0) { szPassword = szPassword.Left(loc); }
// NTRAID#NTBUG9-483038-10/18/2001-JeffJon
// CString::MakeLower() doesn't lower case German characters
// correctly. Using _wcslwr instead. setlocale must be
// called before calling _wcslwr so that it properly lowercases
// extended characters. Store the result and call setlocale
// again when done to set it back to the original so as not
// to affect other snapins in the process.
PWSTR oldLocale = _wsetlocale(LC_ALL, L"");
CString lowerCaseNewPwd = _wcslwr((LPWSTR)(LPCWSTR)szPassword);
_wsetlocale(LC_ALL, oldLocale);
CWaitCursor cwait;
TRACE(L"Setting NT 4 style password\n"); hr = pIADsUser->SetPassword(CComBSTR(lowerCaseNewPwd)); } else { // W2K password, randomly generated. The generated password
// is not necessarily readable
CWaitCursor cwait; HCRYPTPROV hCryptProv = NULL; if (::CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT|CRYPT_VERIFYCONTEXT)) { int nChars = 14; // password length
WCHAR* pszPassword = new WCHAR[nChars+1]; // allow one more for NULL
if (!pszPassword) { return E_OUTOFMEMORY; }
if (::CryptGenRandom(hCryptProv, (nChars*sizeof(WCHAR)), (BYTE*)pszPassword)) { // there is a VERY REMOTE possibility of a 16 bit
// pattern of all zeroes that looks like a WCHAR NULL
// so we check this and we substitute an arbitrary value
for (int k=0; k<nChars; k++) { if (pszPassword[k] == NULL) pszPassword[k] = 0x1; // arbitrary
} // put a NULL at the end
pszPassword[nChars] = NULL; ASSERT(lstrlen(pszPassword) == nChars);
TRACE(L"Setting W2K random password\n"); hr = pIADsUser->SetPassword(CComBSTR(pszPassword)); } else { // CryptGenRandom() failed
hr = HRESULT_FROM_WIN32(::GetLastError()); } ::CryptReleaseContext(hCryptProv, 0x0); delete[] pszPassword; pszPassword = 0; } else { // CryptAcquireContext() failed
hr = HRESULT_FROM_WIN32(::GetLastError()); } } // QI
if (SUCCEEDED(hr)) { bSetPasswordOK = TRUE; } else { if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_12_CANT_SET_COMP_PWD,hr, MB_OK | MB_ICONWARNING, apv, 1); } } pIADsUser->Release(); } // try to write ACL
hr = S_OK; if (m_securityPrincipalSidHolder.Get() == NULL) { // no need to set the ACL, we are fine
bSetSecurityOK = TRUE; } else { CWaitCursor cwait; hr = SetSecurity(); } if (SUCCEEDED(hr)) { bSetSecurityOK = TRUE; } else { TRACE1("INFO: Unable to set security for computer %s.\n", (LPCTSTR)m_strName); if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_12_UNABLE_TO_WRITE_COMP_ACL,hr, MB_OK | MB_ICONWARNING, apv, 1); } }
hr = S_OK; if (bSetPasswordOK && bSetSecurityOK) { // success on the first steps, finally can enable the account
CComVariant varAccount; hr = pNewADsObjectCreateInfo->HrGetAttributeVariant(CComBSTR(gsz_userAccountControl), OUT &varAccount); if (SUCCEEDED(hr)) { // got user account control, can change flag
ASSERT(varAccount.vt == VT_I4); varAccount.lVal &= ~UF_ACCOUNTDISABLE; hr = pNewADsObjectCreateInfo->HrAddVariantLong(CComBSTR(gsz_userAccountControl), varAccount.lVal); if (SUCCEEDED(hr)) { // Try to persist the changes
CWaitCursor cwait; hr = pNewADsObjectCreateInfo->HrSetInfo(TRUE /* fSilentError */); } } // handle errors, if any
if (FAILED(hr)) { TRACE1("INFO: Unable to commit account control for computer %s.\n", (LPCTSTR)m_strName); if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_12_UNABLE_TO_WRITE_ACCT_CTRL,hr, MB_OK | MB_ICONWARNING, apv, 1); } hr = S_OK; // treat as a warning, the account is left disabled
} } return hr; }
#define FILTER_ONE (UGOP_USERS | \
UGOP_ACCOUNT_GROUPS_SE | \ UGOP_RESOURCE_GROUPS_SE | \ UGOP_UNIVERSAL_GROUPS_SE | \ UGOP_BUILTIN_GROUPS | \ UGOP_WELL_KNOWN_PRINCIPALS_USERS \ )
#define FILTER_TWO (UGOP_USERS | \
UGOP_ACCOUNT_GROUPS_SE | \ UGOP_UNIVERSAL_GROUPS_SE | \ UGOP_WELL_KNOWN_PRINCIPALS_USERS | \ UGOP_USERS | \ UGOP_GLOBAL_GROUPS | \ UGOP_ALL_NT4_WELLKNOWN_SIDS \ )
void CCreateNewComputerPage::GetSummaryInfo(CString& s) { if (IsDlgButtonChecked(IDC_NT4_CHECK)) { CString sz; sz.LoadString(IDS_COMPUTER_CREATE_DLG_NT4_ACCOUNT); s += sz; s += L"\n"; }
if (IsDlgButtonChecked(IDC_NT4_BDC_CHECK)) { CString sz; sz.LoadString(IDS_COMPUTER_CREATE_DLG_NT4_BDC); s += sz; s += L"\n"; } }
HRESULT CCreateNewComputerPage::_LookupSamAccountNameFromSid(PSID pSid, CString& szSamAccountName) { HRESULT hr = S_OK; // need to use the SID and lookup the SAM account name
WCHAR szName[MAX_PATH], szDomain[MAX_PATH]; DWORD cchName = MAX_PATH-1, cchDomain = MAX_PATH-1; SID_NAME_USE sne;
LPCWSTR lpszServerName = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName(); if (!LookupAccountSid(lpszServerName, pSid, szName, &cchName, szDomain, &cchDomain, &sne)) { DWORD dwErr = GetLastError(); TRACE(_T("LookupAccountSid failed with error %d\n"), dwErr); return HRESULT_FROM_WIN32(dwErr); }
szSamAccountName = szDomain; szSamAccountName += L"\\"; szSamAccountName += szName; return hr; }
DSOP_SCOPE_INIT_INFO g_aComputerPrincipalDSOPScopes[] = { #if 0
{ cbSize, flType, flScope, { { flBothModes, flMixedModeOnly, flNativeModeOnly }, flDownlevel, }, pwzDcName, pwzADsPath, hr // OUT
}, #endif
// The Global Catalog
{ sizeof(DSOP_SCOPE_INIT_INFO), DSOP_SCOPE_TYPE_GLOBAL_CATALOG, DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS, { { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_WELL_KNOWN_PRINCIPALS, 0, 0 }, 0, }, NULL, NULL, S_OK },
// The domain to which the target computer is joined.
{ sizeof(DSOP_SCOPE_INIT_INFO), DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN, DSOP_SCOPE_FLAG_STARTING_SCOPE | DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS, { // joined domain is always NT5 for DS ACLs Editor
{ 0, //mixed: users, well known SIDs, local groups, builtin groups, global groups, computers
DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_BUILTIN_GROUPS | DSOP_FILTER_GLOBAL_GROUPS_SE,
//native users, well known SIDs, local groups, builtin groups, global groups, universal groups, computers
DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_BUILTIN_GROUPS | DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE }, 0, // zero for downlevel joined domain, should be DS-aware
}, NULL, NULL, S_OK },
// The domains in the same forest (enterprise) as the domain to which
// the target machine is joined. Note these can only be DS-aware
{ sizeof(DSOP_SCOPE_INIT_INFO), DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN, DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS, { { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0}, 0, }, NULL, NULL, S_OK },
// Uplevel domains external to the enterprise but trusted directly by the
// domain to which the target machine is joined.
{ sizeof(DSOP_SCOPE_INIT_INFO), DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN, DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS, { { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0}, DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS, }, NULL, NULL, S_OK },
// Downlevel domains external to the enterprise but trusted directly by the
// domain to which the target machine is joined.
{ sizeof(DSOP_SCOPE_INIT_INFO), DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN, DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS, { { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0}, DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS, }, NULL, NULL, S_OK }, };
void CCreateNewComputerPage::OnChangePrincipalButton() { static UINT cfDsObjectPicker = 0; if (cfDsObjectPicker == 0) cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
// create object picker COM object
CComPtr<IDsObjectPicker> spDsObjectPicker; HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void**)&spDsObjectPicker); if (FAILED(hr)) return;
// set init info
DSOP_INIT_INFO InitInfo; ZeroMemory(&InitInfo, sizeof(InitInfo));
InitInfo.cbSize = sizeof(DSOP_INIT_INFO); InitInfo.pwzTargetComputer = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName(); InitInfo.cDsScopeInfos = sizeof(g_aComputerPrincipalDSOPScopes)/sizeof(DSOP_SCOPE_INIT_INFO); InitInfo.aDsScopeInfos = g_aComputerPrincipalDSOPScopes; InitInfo.flOptions = 0; InitInfo.cAttributesToFetch = 1; LPCWSTR lpszObjectSID = L"objectSid"; InitInfo.apwzAttributeNames = const_cast<LPCTSTR *>(&lpszObjectSID);
//
// Loop through the scopes assigning the DC name
//
for (UINT idx = 0; idx < InitInfo.cDsScopeInfos; idx++) { // Don't set the DC name for external downlevel trusts. This may cause connection
// problems in Object Picker
if (!(InitInfo.aDsScopeInfos->flScope & DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN)) { InitInfo.aDsScopeInfos[idx].pwzDcName = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName(); } }
//
// initialize object picker
//
hr = spDsObjectPicker->Initialize(&InitInfo); if (FAILED(hr)) return;
// invoke the dialog
CComPtr<IDataObject> spdoSelections;
hr = spDsObjectPicker->InvokeDialog(m_hWnd, &spdoSelections); if (hr == S_FALSE || !spdoSelections) { return; }
// retrieve data from data object
FORMATETC fmte = {(CLIPFORMAT)cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM medium = {TYMED_NULL, NULL, NULL}; PDS_SELECTION_LIST pDsSelList = NULL;
hr = spdoSelections->GetData(&fmte, &medium); if (FAILED(hr)) return;
pDsSelList = (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal); CComBSTR bsDN;
if (pDsSelList != NULL) { ASSERT(pDsSelList->cItems == 1); // single selection
TRACE(_T("pwzName = %s\n"), pDsSelList->aDsSelection[0].pwzName); TRACE(_T("pwzADsPath = %s\n"), pDsSelList->aDsSelection[0].pwzADsPath); TRACE(_T("pwzClass = %s\n"), pDsSelList->aDsSelection[0].pwzClass); TRACE(_T("pwzUPN = %s\n"), pDsSelList->aDsSelection[0].pwzUPN);
// get the SID
ASSERT(pDsSelList->aDsSelection[0].pvarFetchedAttributes != NULL); if (pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].vt != VT_EMPTY) { ASSERT(pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].vt == (VT_ARRAY | VT_UI1)); PSID pSid = pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].parray->pvData; ASSERT(IsValidSid(pSid));
// deep copy SID
if (!m_securityPrincipalSidHolder.Copy(pSid)) { ASSERT(FALSE); // should never get here in normal operations
ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr, MB_OK | MB_ICONERROR, NULL, 0); goto Exit; } }
UpdateSecurityPrincipalUI(&(pDsSelList->aDsSelection[0])); } else { PVOID apv[1] = {(LPWSTR)(pDsSelList->aDsSelection[0].pwzName)}; ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_GET_SAM_ACCNT_NAME,hr, MB_OK | MB_ICONERROR, apv, 1); goto Exit; }
Exit: GlobalUnlock(medium.hGlobal); ReleaseStgMedium(&medium);
}
void CCreateNewComputerPage::UpdateSecurityPrincipalUI(PDS_SELECTION pDsSelection) { TRACE(L"CCreateNewComputerPage::UpdateSecurityPrincipalUI()\n");
HRESULT hr = S_OK;
CString szText;
LPWSTR pwzADsPath = pDsSelection->pwzADsPath; TRACE(L"pDsSelection->pwzADsPath = %s\n", pDsSelection->pwzADsPath);
// get the X500 name (remove the provider ("LDAP://") in front of the name
if ((pwzADsPath != NULL) && (pwzADsPath[0] != NULL)) { CComBSTR bstrProvider;
// need a fresh instance because we can set it to WINNT provider
// and pretty much trash it (oh boy!!!)
CPathCracker pathCracker; hr = pathCracker.Set(CComBSTR(pwzADsPath), ADS_SETTYPE_FULL); if (FAILED(hr)) { goto End; } hr = pathCracker.Retrieve(ADS_FORMAT_PROVIDER, &bstrProvider); TRACE(L"bstrProvider = %s\n", bstrProvider); if (FAILED(hr)) { goto End; }
if (_wcsicmp(bstrProvider, L"LDAP") == 0) { // it is an LDAP path, get the DN out of it
// get the DN
CComBSTR bstrDN; hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN); if (FAILED(hr)) { goto End; }
// get the canonical name out of the DN
LPWSTR pszCanonical = NULL; hr = ::CrackName((LPWSTR)bstrDN, &pszCanonical, GET_OBJ_CAN_NAME, NULL); if (pszCanonical != NULL) { szText = pszCanonical; ::LocalFreeStringW(&pszCanonical); }
} else if (_wcsicmp(bstrProvider, L"WinNT") == 0) { // we got an NT 4.0 user or group,
// the mpath is something like: "WinNT://mydomain/JoeB"
CComBSTR bstrWindows; // get "mydomain/JoeB"
hr = pathCracker.Retrieve(ADS_FORMAT_WINDOWS_DN, &bstrWindows); if (FAILED(hr)) { goto End; } szText = bstrWindows; // flip the slash to reverse slash
int nCh = szText.Find(L'/'); if (nCh != -1) { szText.SetAt(nCh, L'\\'); } } }
End:
if (szText.IsEmpty()) { szText = pDsSelection->pwzName; }
SetDlgItemText(IDC_PRINCIPAL_EDIT, szText); }
HRESULT CCreateNewComputerPage::GetDefaultSecurityDescriptorFromSchema( CSimpleSecurityDescriptorHolder& sdHolder) { HRESULT hr = S_OK;
do { // Get the schema path
CString schemaPath; GetWiz()->GetInfo()->GetBasePathsInfo()->GetSchemaPath(schemaPath); if (schemaPath.IsEmpty()) { TRACE(L"Failed to get the schema path"); hr = E_FAIL; break; }
// Initialize the search object
CDSSearch schemaSearcher;
hr = InitializeSchemaSearcher(schemaPath, schemaSearcher); if (FAILED(hr)) { TRACE(L"Failed to initialize schema searcher: hr = 0x%x", hr); break; }
// Run the query
hr = schemaSearcher.DoQuery(); if (FAILED(hr)) { TRACE(L"Failed DoQuery on schema searcher: hr = 0x%x", hr); break; }
hr = schemaSearcher.GetNextRow(); if (FAILED(hr)) { TRACE(L"Failed to get a row from the schema search object: hr = 0x%x", hr); break; }
// Get the value from the search object
ADS_SEARCH_COLUMN searchColumn; ZeroMemory(&searchColumn, sizeof(ADS_SEARCH_COLUMN));
hr = schemaSearcher.GetColumn(g_pszDefaultSecurityDescriptor, &searchColumn); if (FAILED(hr)) { TRACE(L"Failed to get the defaultSecurityDescriptor column from search object: hr = 0x%x", hr); break; }
// Initialize the SD from the SDDL
if (searchColumn.dwNumValues > 0 && searchColumn.pADsValues && searchColumn.pADsValues->CaseIgnoreString) { hr = sdHolder.InitializeFromSDDL( GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName(), searchColumn.pADsValues->CaseIgnoreString); }
hr = schemaSearcher.FreeColumn(&searchColumn); if (FAILED(hr)) { TRACE(L"Failed to free the search column: hr = 0x%x", hr); } } while (false);
return hr; }
HRESULT CCreateNewComputerPage::InitializeSchemaSearcher( const CString& schemaPath, CDSSearch& schemaSearcher) { HRESULT hr = S_OK;
do { hr = schemaSearcher.Init(schemaPath); if (FAILED(hr)) { TRACE(L"Failed to initialize the schema search object: hr = 0x%x", hr); break; }
PWSTR pszFilter = L"(&(objectCategory=classSchema)(ldapDisplayName=computer))"; PWSTR pszAttrs[] = { g_pszDefaultSecurityDescriptor };
hr = schemaSearcher.SetAttributeList(pszAttrs, sizeof(pszAttrs)/sizeof(PWSTR)); if (FAILED(hr)) { TRACE(L"Failed to set the attribute list in the schema search object: hr = 0x%x", hr); break; }
hr = schemaSearcher.SetFilterString(pszFilter); if (FAILED(hr)) { TRACE(L"Failed to set the filter string in the schema search object: hr = 0x%x", hr); break; }
hr = schemaSearcher.SetSearchScope(ADS_SCOPE_ONELEVEL); if (FAILED(hr)) { TRACE(L"Failed to set the search scope in the schema search object: hr = 0x%x", hr); break; }
} while (false);
return hr; }
// DESCRIPTION : this function gives the specified SID the same rights as
// creator owner in the given ACL.
//
// NOTE: Due to the memory management constraints of all the security APIs
// this turns out to be a huge function. Functions like BuildTrusteeWithObjectAndSid()
// don't allocate any memory and instead just set pointers to existing memory in the
// structure, so if I use any locals they must remain in the scope of the constructed
// Trustee object or else I could run into failures.
HRESULT CCreateNewComputerPage::AddCreatorOwnerAccessForSID( PACL defaultAcl, PACL acl, PSID securityPrincipalSID, CSimpleAclHolder& newDacl) { HRESULT hr = S_OK;
PEXPLICIT_ACCESS completeAccessList = 0; PEXPLICIT_ACCESS creatorOwnerAccessList = 0; ULONG entries = 0; ULONG emptyObjectsAndSidsUsed = 0;
// We need to dynamically allocate the emptyObjectsAndSid because
// there needs to be one for each time its used in BuildTrusteeWithObjectsAndSid
POBJECTS_AND_SID emptyObjectsAndSid = 0;
do { if (!defaultAcl || !acl || !securityPrincipalSID) { ASSERT(defaultAcl); ASSERT(acl); ASSERT(securityPrincipalSID);
hr = E_INVALIDARG; break; }
// Get all the entries from the ACL
ULONG totalEntries = 0;
DWORD error = GetExplicitEntriesFromAcl( defaultAcl, &totalEntries, &completeAccessList); if (ERROR_SUCCESS != error) { hr = HRESULT_FROM_WIN32(error); TRACE(L"Failed to GetExplicitEntriesFromAcl: hr = 0x%x", hr); break; }
if (totalEntries <= 0) { hr = E_FAIL; TRACE(L"No entries were returned from GetExplicitEntriesFromAcl"); break; }
// We know that there will be no more entries for creator/owner
// than are already present, so allocate the new array with
// the max and then entries will be the number the array
// actually contains
creatorOwnerAccessList = new EXPLICIT_ACCESS[totalEntries];
if (!creatorOwnerAccessList) { hr = E_OUTOFMEMORY; break; }
::ZeroMemory(creatorOwnerAccessList, totalEntries * sizeof(EXPLICIT_ACCESS));
emptyObjectsAndSid = new OBJECTS_AND_SID[totalEntries];
if (!emptyObjectsAndSid) { hr = E_OUTOFMEMORY; break; }
::ZeroMemory(emptyObjectsAndSid, totalEntries * sizeof(OBJECTS_AND_SID));
// Loop through all the entries and copy over any for creator/owner
static SID creatorOwnerSID = {SID_REVISION,1,SECURITY_CREATOR_SID_AUTHORITY,{SECURITY_CREATOR_OWNER_RID}};
for (ULONG index = 0; index < totalEntries; ++index) { if (completeAccessList[index].Trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID) { POBJECTS_AND_SID objectsAndSid = reinterpret_cast<POBJECTS_AND_SID>(completeAccessList[index].Trustee.ptstrName);
if (objectsAndSid && EqualSid(&creatorOwnerSID, objectsAndSid->pSid)) { // Fill in the Trustee member of the new entry in the creatorOwnerAccessList
// with the SID of the new security principal
creatorOwnerAccessList[entries] = completeAccessList[index];
BuildTrusteeWithObjectsAndSid( &(creatorOwnerAccessList[entries].Trustee), &(emptyObjectsAndSid[emptyObjectsAndSidsUsed++]), &objectsAndSid->ObjectTypeGuid, &objectsAndSid->InheritedObjectTypeGuid, securityPrincipalSID);
++entries; } } else if (completeAccessList[index].Trustee.TrusteeForm == TRUSTEE_IS_SID) { PSID currentSID = reinterpret_cast<PSID>(completeAccessList[index].Trustee.ptstrName);
if (currentSID && EqualSid(&creatorOwnerSID, currentSID)) { // Fill in the Trustee member of the new entry in the creatorOwnerAccessList
// with the SID of the new security principal
creatorOwnerAccessList[entries] = completeAccessList[index];
BuildTrusteeWithSid( &(creatorOwnerAccessList[entries].Trustee), securityPrincipalSID);
++entries; } } else { // REVIEW_JEFFJON : Can we get any of the other forms here?
// If so, what do we do with them?
ASSERT(FALSE); continue; } }
error = SetEntriesInAcl( entries, creatorOwnerAccessList, acl, &(newDacl.m_pAcl));
if (ERROR_SUCCESS != error) { hr = HRESULT_FROM_WIN32(error); TRACE(L"Failed to SetEntriesInAcl: hr = 0x%x", hr); break; }
} while (false);
if (completeAccessList) { LocalFree(completeAccessList); completeAccessList = 0; }
if (creatorOwnerAccessList) { delete[] creatorOwnerAccessList; creatorOwnerAccessList = 0; }
if (emptyObjectsAndSid) { delete[] emptyObjectsAndSid; emptyObjectsAndSid = 0; }
return hr; }
HRESULT CCreateNewComputerPage::BuildNewAccessList(PACL pDacl, CSimpleAclHolder& Dacl) { // NTRAID#NTBUG-509482-2002/03/05-JeffJon-We need to read the default
// security descriptor for computer objects from the schema and apply
// all the ACEs for the creator/owner to the selected object
HRESULT hr = S_OK;
do { // Get the defaultSecurityDescriptor from the schema
CSimpleSecurityDescriptorHolder sdHolder;
hr = GetDefaultSecurityDescriptorFromSchema(sdHolder); if (FAILED(hr)) { TRACE(L"Failed to get the default security descriptor from the schema: hr = %x", hr); break; }
if (!sdHolder.m_pSD) { TRACE(L"Failed to get the default security descriptor from the schema."); hr = E_FAIL; break; }
// Pull out the DACL from the SD
BOOL daclPresent = TRUE; BOOL daclDefaulted = FALSE; PACL pDefaultDacl = 0;
BOOL result = GetSecurityDescriptorDacl( sdHolder.m_pSD, &daclPresent, &pDefaultDacl, &daclDefaulted);
if (!result) { DWORD error = GetLastError(); hr = HRESULT_FROM_WIN32(error);
TRACE(L"Failed to GetSecurityDescriptorDacl: hr = 0x%x", hr); break; }
if (!daclPresent) { TRACE(L"GetSecurityDescriptorDacl returned no DACL"); hr = E_FAIL; break; }
PSID securityPrincipalSID = m_securityPrincipalSidHolder.Get(); ASSERT(securityPrincipalSID);
hr = AddCreatorOwnerAccessForSID(pDefaultDacl, pDacl, securityPrincipalSID, Dacl); if (FAILED(hr)) { TRACE(L"Failed AddCreatorOwnerAccessToSID: hr = 0x%x", hr); break; }
} while (false);
return hr; }
HRESULT CCreateNewComputerPage::SetSecurity() { // get the ADSI object pointer
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); IADs* pObj = pNewADsObjectCreateInfo->PGetIADsPtr();
// get the full LDAP path of the object
CComBSTR bstrObjectLdapPath; HRESULT hr = pObj->get_ADsPath(&bstrObjectLdapPath); ASSERT (SUCCEEDED(hr)); if (FAILED(hr)) { return hr; }
UnescapePath(bstrObjectLdapPath, /*bDN*/ FALSE, bstrObjectLdapPath);
PACL pAcl = NULL; CSimpleSecurityDescriptorHolder SDHolder;
TRACE(_T("GetDsObjectSD(%s)\n"), bstrObjectLdapPath);
// read info
DWORD dwErr = ::GetDsObjectSD( bstrObjectLdapPath, &pAcl, &(SDHolder.m_pSD));
TRACE(L"GetDsObjectSD() returned dwErr = 0x%x\n", dwErr);
hr = HRESULT_FROM_WIN32(dwErr);
if (FAILED(hr)) { TRACE(_T("failed on GetDsObjectSD()\n")); return hr; }
// build the new DACL
CSimpleAclHolder Dacl; hr = BuildNewAccessList(pAcl, Dacl);
if (FAILED(hr)) { TRACE(_T("failed on BuildNewAccessList()\n")); return hr; }
// commit changes
dwErr = ::SetDsObjectDacl( (LPCWSTR)(BSTR)bstrObjectLdapPath, Dacl.m_pAcl);
TRACE(L"SetDsObjectDacl() returned dwErr = 0x%x\n", dwErr);
hr = HRESULT_FROM_WIN32(dwErr);
return hr; }
BOOL CCreateNewComputerPage::OnError(HRESULT hr) { BOOL bRetVal = FALSE;
if( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS ) {
HRESULT Localhr; DWORD LastError; WCHAR Buf1[256], Buf2[256]; Localhr = ADsGetLastError (&LastError, Buf1, 256, Buf2, 256); switch( LastError ) { case ERROR_USER_EXISTS: { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName}; ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_COMPUTER_EXISTS,hr, MB_OK|MB_ICONWARNING , apv, 1); bRetVal = TRUE; } break;
case ERROR_DS_OBJ_STRING_NAME_EXISTS: { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName}; ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_COMPUTER_DS_OBJ_STRING_NAME_EXISTS,hr, MB_OK|MB_ICONWARNING , apv, 1); bRetVal = TRUE; } break; } } return bRetVal; }
CCreateNewComputerWizard:: CCreateNewComputerWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); }
void CCreateNewComputerWizard::OnFinishSetInfoFailed(HRESULT hr) {
AFX_MANAGE_STATE(AfxGetStaticModuleState()); if ( !( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS && m_page1.OnError( hr ) ) ) { // everything else is handled by the base class
CCreateNewObjectWizardBase::OnFinishSetInfoFailed(hr); } }
///////////////////////////////////////////////////////////////
// NEW OU WIZARD
BEGIN_MESSAGE_MAP(CCreateNewOUPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange) END_MESSAGE_MAP()
CCreateNewOUPage::CCreateNewOUPage() : CCreateNewObjectDataPage(CCreateNewOUPage::IDD) { }
BOOL CCreateNewOUPage::OnInitDialog() { Edit_LimitText (GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, 64); CCreateNewObjectDataPage::OnInitDialog(); return TRUE; }
BOOL CCreateNewOUPage::GetData(IADs*) { return !m_strOUName.IsEmpty(); }
void CCreateNewOUPage::OnNameChange() { GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strOUName); m_strOUName.TrimLeft(); m_strOUName.TrimRight(); GetWiz()->SetWizardButtons(this, !m_strOUName.IsEmpty()); }
HRESULT CCreateNewOUPage::SetData(BOOL) { // Store the object name in the temporary storage
HRESULT hr = GetWiz()->GetInfo()->HrCreateNew(m_strOUName); return hr; }
BOOL CCreateNewOUPage::OnSetActive() { BOOL bRet = CCreateNewObjectDataPage::OnSetActive(); SetDlgItemFocus(IDC_EDIT_OBJECT_NAME); SendDlgItemMessage(IDC_EDIT_OBJECT_NAME, EM_SETSEL, 0, -1);
return bRet; }
BOOL CCreateNewOUPage::OnWizardFinish() { BOOL bFinish = CCreateNewObjectDataPage::OnWizardFinish(); if (!bFinish) { SetDlgItemFocus(IDC_EDIT_OBJECT_NAME); SendDlgItemMessage(IDC_EDIT_OBJECT_NAME, EM_SETSEL, 0, -1); } return bFinish; }
CCreateNewOUWizard:: CCreateNewOUWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); } ///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW GROUP WIZARD
BEGIN_MESSAGE_MAP(CCreateNewGroupPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange) ON_EN_CHANGE(IDC_EDIT_SAM_NAME, OnSamNameChange) ON_BN_CLICKED(IDC_RADIO_SEC_GROUP, OnSecurityOrTypeChange) ON_BN_CLICKED(IDC_RADIO_DISTRIBUTION_GROUP, OnSecurityOrTypeChange) ON_BN_CLICKED(IDC_RADIO_RESOURCE, OnSecurityOrTypeChange) ON_BN_CLICKED(IDC_RADIO_ACCOUNT, OnSecurityOrTypeChange) ON_BN_CLICKED(IDC_RADIO_UNIVERSAL, OnSecurityOrTypeChange) END_MESSAGE_MAP()
CCreateNewGroupPage::CCreateNewGroupPage() : CCreateNewObjectDataPage(CCreateNewGroupPage::IDD) { m_fMixed = FALSE; m_SAMLength = 256; }
BOOL CCreateNewGroupPage::OnInitDialog() { CCreateNewObjectDataPage::OnInitDialog(); VERIFY(_InitUI()); return TRUE; }
BOOL CCreateNewGroupPage::OnSetActive() { BOOL ret = CCreateNewObjectDataPage::OnSetActive();
// Set the focus to the first name field
GetParent()->PostMessage( WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDC_EDIT_OBJECT_NAME)->GetSafeHwnd(), (LPARAM)TRUE);
GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() && !m_strSamName.IsEmpty())); return ret; }
BOOL CCreateNewGroupPage::_InitUI() { // set limit to edit boxes
Edit_LimitText(::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME), 64); Edit_LimitText(::GetDlgItem(m_hWnd, IDC_EDIT_SAM_NAME), m_SAMLength); // determine if we are in mixed mode by
// retriving the domain we are bound to
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); CComPtr<IADs> spContainerObj; HRESULT hr = pNewADsObjectCreateInfo->m_pIADsContainer->QueryInterface( IID_IADs, (void **)&spContainerObj);
if (SUCCEEDED(hr)) { // retrieve the DN of the container
CComBSTR bstrPath, bstrDN; spContainerObj->get_ADsPath(&bstrPath);
CPathCracker pathCracker; pathCracker.Set(bstrPath, ADS_SETTYPE_FULL); pathCracker.SetDisplayType(ADS_DISPLAY_FULL); pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
// get the 1779 name of the domain
LPWSTR pszDomain1779 = NULL; hr = CrackName (bstrDN, &pszDomain1779, GET_FQDN_DOMAIN_NAME, NULL); if (SUCCEEDED(hr)) { // build LDAP path for domain
CString strDomObj; pNewADsObjectCreateInfo->GetBasePathsInfo()->ComposeADsIPath(strDomObj, pszDomain1779);
LocalFreeStringW(&pszDomain1779);
// bind to the domain object
CComPtr<IADs> spDomainObj; hr = DSAdminOpenObject(strDomObj, IID_IADs, (void **) &spDomainObj, TRUE /*bServer*/); if (SUCCEEDED(hr)) { // retrieve the mixed node attribute
CComVariant Mixed; CComBSTR bsMixed(L"nTMixedDomain"); spDomainObj->Get(bsMixed, &Mixed); m_fMixed = (BOOL)Mixed.bVal; } } }
// initial setup of radiobutton state
if (m_fMixed) { EnableDlgItem (IDC_RADIO_UNIVERSAL, FALSE); // no universal groups allowed
} // default is global security group
((CButton *)GetDlgItem(IDC_RADIO_ACCOUNT))->SetCheck(1); ((CButton *)GetDlgItem(IDC_RADIO_SEC_GROUP))->SetCheck(1);
return TRUE; }
HRESULT CCreateNewGroupPage::SetData(BOOL) { HRESULT hr;
//
// First check for illegal characters
//
int iFind = m_strSamName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS); if (iFind != -1 && !m_strSamName.IsEmpty()) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName}; if (IDYES == ReportErrorEx (m_hWnd,IDS_GROUP_SAMNAME_ILLEGAL,S_OK, MB_YESNO | MB_ICONWARNING, apv, 1)) { while (iFind != -1) { m_strSamName.SetAt(iFind, L'_'); iFind = m_strSamName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS); } SetDlgItemText(IDC_EDIT_SAM_NAME, m_strSamName); } else { //
// Set the focus to the edit box and select the text
//
GetDlgItem(IDC_EDIT_SAM_NAME)->SetFocus(); SendDlgItemMessage(IDC_EDIT_SAM_NAME, EM_SETSEL, 0 , -1); return E_INVALIDARG; } }
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); // Store the object name in the temporary storage
hr = pNewADsObjectCreateInfo->HrCreateNew(m_strGroupName); if (FAILED(hr)) { return hr; }
// Create and persist the object
// Store the object name in the temporary storage
hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_samAccountName), m_strSamName); ASSERT(SUCCEEDED(hr));
CComVariant varGroupType; varGroupType.vt = VT_I4;
BOOL Account = IsDlgButtonChecked (IDC_RADIO_ACCOUNT); BOOL Resource = IsDlgButtonChecked (IDC_RADIO_RESOURCE); BOOL Security = IsDlgButtonChecked (IDC_RADIO_SEC_GROUP);
if (Security) varGroupType.lVal = GROUP_TYPE_SECURITY_ENABLED; else varGroupType.lVal = 0;
if (Resource) varGroupType.lVal |= GROUP_TYPE_RESOURCE_GROUP; else if (Account) varGroupType.lVal |= GROUP_TYPE_ACCOUNT_GROUP; else varGroupType.lVal |= GROUP_TYPE_UNIVERSAL_GROUP;
// Update the GroupType
hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(CComBSTR(gsz_groupType), varGroupType); ASSERT(SUCCEEDED(hr));
return hr; }
BOOL CCreateNewGroupPage::GetData(IADs*) { return !m_strGroupName.IsEmpty(); }
void CCreateNewGroupPage::OnNameChange() { GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strGroupName); m_strGroupName.TrimLeft(); m_strGroupName.TrimRight(); SetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strGroupName.Left(m_SAMLength)); GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() && !m_strSamName.IsEmpty())); }
void CCreateNewGroupPage::OnSamNameChange() { GetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strSamName); m_strSamName.TrimLeft(); m_strSamName.TrimRight(); GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() && !m_strSamName.IsEmpty())); }
void CCreateNewGroupPage::OnSecurityOrTypeChange() { if (!IsDlgButtonChecked (IDC_RADIO_SEC_GROUP)) { EnableDlgItem (IDC_RADIO_UNIVERSAL, TRUE); } else { if (m_fMixed) { if (IsDlgButtonChecked (IDC_RADIO_UNIVERSAL)) { ((CButton *)GetDlgItem(IDC_RADIO_ACCOUNT))->SetCheck(1); ((CButton *)GetDlgItem(IDC_RADIO_UNIVERSAL))->SetCheck(0); } EnableDlgItem (IDC_RADIO_UNIVERSAL, FALSE); } } }
CCreateNewGroupWizard::CCreateNewGroupWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); }
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW CONTACT WIZARD
BEGIN_MESSAGE_MAP(CCreateNewContactPage, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_EDIT_FIRST_NAME, OnNameChange) ON_EN_CHANGE(IDC_EDIT_INITIALS, OnNameChange) ON_EN_CHANGE(IDC_EDIT_LAST_NAME, OnNameChange) ON_EN_CHANGE(IDC_EDIT_FULL_NAME, OnFullNameChange) ON_EN_CHANGE(IDC_EDIT_DISP_NAME, OnDispNameChange) END_MESSAGE_MAP()
CCreateNewContactPage::CCreateNewContactPage() : CCreateNewObjectDataPage(CCreateNewContactPage::IDD) { }
BOOL CCreateNewContactPage::OnInitDialog() { CCreateNewObjectDataPage::OnInitDialog();
Edit_LimitText (GetDlgItem(IDC_EDIT_FULL_NAME)->m_hWnd, 64); Edit_LimitText (GetDlgItem(IDC_EDIT_LAST_NAME)->m_hWnd, 29); Edit_LimitText (GetDlgItem(IDC_EDIT_FIRST_NAME)->m_hWnd, 28);
// NTRAID#NTBUG9-522001-2002/01/17-JeffJon
// Initials should be limited to 6 characters.
Edit_LimitText (GetDlgItem(IDC_EDIT_INITIALS)->m_hWnd, 6);
Edit_LimitText (GetDlgItem(IDC_EDIT_DISP_NAME)->m_hWnd, 256);
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); m_nameFormatter.Initialize(pNewADsObjectCreateInfo->GetBasePathsInfo(), pNewADsObjectCreateInfo->m_pszObjectClass);
return TRUE; }
HRESULT CCreateNewContactPage::SetData(BOOL) { HRESULT hr; // Store the object name in the temporary storage
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
// create a new temporary ADs object
hr = pNewADsObjectCreateInfo->HrCreateNew(m_strFullName); if (FAILED(hr)) { return hr; } // set the attributes in the cache
hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"givenName"), m_strFirstName); ASSERT(SUCCEEDED(hr)); hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"initials"), m_strInitials); ASSERT(SUCCEEDED(hr)); hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"sn"), m_strLastName); ASSERT(SUCCEEDED(hr)); hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"displayName"), m_strDispName); ASSERT(SUCCEEDED(hr));
return hr; }
BOOL CCreateNewContactPage::GetData(IADs*) { return !m_strFullName.IsEmpty(); }
void CCreateNewContactPage::OnNameChange() { GetDlgItemText(IDC_EDIT_FIRST_NAME, OUT m_strFirstName); GetDlgItemText(IDC_EDIT_INITIALS, OUT m_strInitials); GetDlgItemText(IDC_EDIT_LAST_NAME, OUT m_strLastName);
m_strFirstName.TrimLeft(); m_strFirstName.TrimRight();
m_strInitials.TrimLeft(); m_strInitials.TrimRight();
m_strLastName.TrimLeft(); m_strLastName.TrimRight();
m_nameFormatter.FormatName(m_strFullName, m_strFirstName.IsEmpty() ? NULL : (LPCWSTR)m_strFirstName, m_strInitials.IsEmpty() ? NULL : (LPCWSTR)m_strInitials, m_strLastName.IsEmpty() ? NULL : (LPCWSTR)m_strLastName); SetDlgItemText(IDC_EDIT_FULL_NAME, IN m_strFullName);
GetWiz()->SetWizardButtons(this, !m_strFullName.IsEmpty()); }
void CCreateNewContactPage::OnFullNameChange() { GetDlgItemText(IDC_EDIT_FULL_NAME, OUT m_strFullName); GetWiz()->SetWizardButtons(this, !m_strFullName.IsEmpty()); }
void CCreateNewContactPage::OnDispNameChange() { GetDlgItemText(IDC_EDIT_DISP_NAME, OUT m_strDispName); m_strDispName.TrimLeft(); m_strDispName.TrimRight(); }
CCreateNewContactWizard::CCreateNewContactWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&m_page1); }
#ifdef FRS_CREATE
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW FRS SUBSCRIBER WIZARD
HRESULT CCreateNewFrsSubscriberPage::SetData(BOOL bSilent) { CString strRootPath; CString strStagingPath; if ( !ReadAbsolutePath( IDC_FRS_ROOT_PATH, strRootPath) || !ReadAbsolutePath( IDC_FRS_STAGING_PATH, strStagingPath ) ) { return E_INVALIDARG; }
HRESULT hr = S_OK;
// Add more properties, we don't want to create it unless all of these work
CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); ASSERT( NULL != pNewADsObjectCreateInfo ); hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty( gsz_fRSRootPath, strRootPath, TRUE ); ASSERT(SUCCEEDED(hr)); hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty( gsz_fRSStagingPath, strStagingPath, TRUE ); ASSERT(SUCCEEDED(hr));
// no need to commit here, wait until after extensions have had a shot
return CCreateNewNamedObjectPage::SetData(bSilent); }
BOOL CCreateNewFrsSubscriberPage::ReadAbsolutePath( int ctrlID, OUT CString& strrefValue ) { // CODEWORK this should also select the text in this field
GetDlgItemText(ctrlID, OUT strrefValue); DWORD PathType = 0; if ( NERR_Success != I_NetPathType( NULL, const_cast<LPTSTR>((LPCTSTR)strrefValue), &PathType, 0 ) || ITYPE_PATH_ABSD != PathType ) { PVOID apv[1] = {(LPWSTR)(LPCWSTR)strrefValue}; ReportErrorEx (::GetParent(m_hWnd),IDS_2_INVALID_ABSOLUTE_PATH,S_OK, MB_OK, apv, 1);
SetDlgItemFocus(ctrlID); return FALSE; } return TRUE; } #endif // FRS_CREATE
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// NEW SITE LINKWIZARD
BEGIN_MESSAGE_MAP(CCreatePageWithDuellingListboxes, CCreateNewObjectDataPage) ON_EN_CHANGE(IDC_NEW_OBJECT_NAME, OnNameChange) ON_BN_CLICKED(IDC_DUELLING_RB_ADD, OnDuellingButtonAdd) ON_BN_CLICKED(IDC_DUELLING_RB_REMOVE, OnDuellingButtonRemove) ON_LBN_SELCHANGE(IDC_DUELLING_LB_OUT, OnDuellingListboxSelchange) ON_LBN_SELCHANGE(IDC_DUELLING_LB_IN, OnDuellingListboxSelchange) ON_WM_DESTROY() END_MESSAGE_MAP()
CCreatePageWithDuellingListboxes::CCreatePageWithDuellingListboxes( UINT nIDTemplate, LPCWSTR lpcwszAttrName, const DSPROP_BSTR_BLOCK& bstrblock ) : CCreateNewObjectDataPage(nIDTemplate) , m_strAttrName( lpcwszAttrName ) , m_bstrblock( bstrblock ) { }
BOOL CCreatePageWithDuellingListboxes::GetData(IADs*) { return FALSE; // start disabled
}
void CCreatePageWithDuellingListboxes::OnNameChange() { GetDlgItemText(IDC_NEW_OBJECT_NAME, OUT m_strName); m_strName.TrimLeft(); m_strName.TrimRight(); SetWizardButtons(); }
void CCreatePageWithDuellingListboxes::SetWizardButtons() { BOOL fAllowApply = !(m_strName.IsEmpty()); GetWiz()->SetWizardButtons(this, fAllowApply); }
HRESULT CCreatePageWithDuellingListboxes::SetData(BOOL) { HRESULT hr = S_OK; CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo(); // Store the object name in the temporary storage
hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName); if (FAILED(hr)) { return hr; }
// build the siteList attribute
CStringList strlist; int cItems = ListBox_GetCount( m_hwndInListbox ); ASSERT( 0 <= cItems ); for (int i = cItems-1; i >= 0; i--) { BSTR bstrDN = (BSTR)ListBox_GetItemData( m_hwndInListbox, i ); ASSERT( NULL != bstrDN ); strlist.AddHead( bstrDN ); } ASSERT( strlist.GetCount() > 0 ); CComVariant svar; hr = HrStringListToVariant( OUT svar, IN strlist ); ASSERT( SUCCEEDED(hr) );
//
// set the siteList attribute
//
hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(CComBSTR(m_strAttrName), svar); ASSERT(SUCCEEDED(hr));
//
// no need to commit here, wait until after extensions have had a shot
//
return hr; }
//
// The duelling listbox support uses exports from DSPROP.DLL. Correct
// functioning requires that the control IDs be numbered correctly.
// JonN 8/31/98
//
void CCreatePageWithDuellingListboxes::OnDuellingButtonAdd() { DSPROP_Duelling_ButtonClick( m_hWnd, IDC_DUELLING_RB_ADD ); SetWizardButtons(); }
void CCreatePageWithDuellingListboxes::OnDuellingButtonRemove() { DSPROP_Duelling_ButtonClick( m_hWnd, IDC_DUELLING_RB_REMOVE ); SetWizardButtons(); }
void CCreatePageWithDuellingListboxes::OnDuellingListboxSelchange() { // don't allow Add/Remove if there are <3 sites
if (2 < (ListBox_GetCount(m_hwndInListbox) + ListBox_GetCount(m_hwndOutListbox)) ) { DSPROP_Duelling_UpdateButtons( m_hWnd, IDC_DUELLING_RB_ADD ); } }
void CCreatePageWithDuellingListboxes::OnDestroy() { DSPROP_Duelling_ClearListbox( m_hwndInListbox ); DSPROP_Duelling_ClearListbox( m_hwndOutListbox ); CCreateNewObjectDataPage::OnDestroy(); }
BOOL CCreatePageWithDuellingListboxes::OnSetActive() { m_hwndInListbox = ::GetDlgItem( m_hWnd, IDC_DUELLING_LB_IN ); m_hwndOutListbox = ::GetDlgItem( m_hWnd, IDC_DUELLING_LB_OUT ); ASSERT( NULL != m_hwndInListbox && NULL != m_hwndOutListbox );
HWND hwndInitial = m_hwndOutListbox; if (3 > m_bstrblock.QueryCount()) { // move all sitelinks to "in"
// Add/Remove will never be enabled
hwndInitial = m_hwndInListbox; } HRESULT hr = DSPROP_Duelling_Populate( hwndInitial, m_bstrblock ); if ( FAILED(hr) ) return FALSE; return CCreateNewObjectDataPage::OnSetActive(); }
CCreateNewSiteLinkPage::CCreateNewSiteLinkPage( const DSPROP_BSTR_BLOCK& bstrblock ) : CCreatePageWithDuellingListboxes( CCreateNewSiteLinkPage::IDD, gsz_siteList, bstrblock) { }
BOOL CCreateNewSiteLinkPage::OnInitDialog() { CCreatePageWithDuellingListboxes::OnInitDialog();
// NTRAID#NTBUG9-477962-2001/10/09-jeffjon
// Limit the sitelink name to MAX_RDN_SIZE characters to avoid overflow
SendDlgItemMessage(IDC_NEW_OBJECT_NAME, EM_SETLIMITTEXT, (WPARAM)MAX_RDN_SIZE, 0);
return FALSE; }
BOOL CCreateNewSiteLinkPage::OnSetActive() { if (m_bstrblock.QueryCount() < 2) { // change "must contain two sites" text
CString sz; sz.LoadString(IDS_SITELINK_DLGTEXT_ONE_SITE); ::SetDlgItemText( m_hWnd, IDC_STATIC_MESSAGE, sz ); }
return CCreatePageWithDuellingListboxes::OnSetActive(); }
HRESULT CCreateNewSiteLinkPage::SetData(BOOL bSilent) { BOOL fAllowApply = TRUE; int cIn = ListBox_GetCount(m_hwndInListbox); if (1 > cIn) fAllowApply = FALSE; // zero sites is a constraint violation
else if (2 > cIn) { int cOut = ListBox_GetCount(m_hwndOutListbox); if (1 <= cOut) // allow one site if the "out" listbox is empty
fAllowApply = FALSE; } if (fAllowApply) return CCreatePageWithDuellingListboxes::SetData(bSilent);
if (!bSilent) { ReportMessageEx(m_hWnd, IDS_SITELINK_NEEDS_TWO_SITES, MB_OK | MB_ICONSTOP); }
return E_FAIL; }
CCreateNewSiteLinkWizard::CCreateNewSiteLinkWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo, const DSPROP_BSTR_BLOCK& bstrblock ) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) , m_page1( bstrblock ) { AddPage(&m_page1); }
CCreateNewSiteLinkBridgePage::CCreateNewSiteLinkBridgePage( const DSPROP_BSTR_BLOCK& bstrblock ) : CCreatePageWithDuellingListboxes( CCreateNewSiteLinkBridgePage::IDD, gsz_siteLinkList, bstrblock) { }
BOOL CCreateNewSiteLinkBridgePage::OnInitDialog() { CCreatePageWithDuellingListboxes::OnInitDialog();
// NTRAID#NTBUG9-477962-2001/10/09-jeffjon
// Limit the site link bridge name to MAX_RDN_SIZE characters to avoid overflow
SendDlgItemMessage(IDC_NEW_OBJECT_NAME, EM_SETLIMITTEXT, (WPARAM)MAX_RDN_SIZE, 0);
return FALSE; }
HRESULT CCreateNewSiteLinkBridgePage::SetData(BOOL bSilent) { BOOL fAllowApply = TRUE; int cIn = ListBox_GetCount(m_hwndInListbox); if (2 > cIn) { fAllowApply = FALSE; } if (fAllowApply) return CCreatePageWithDuellingListboxes::SetData(bSilent);
if (!bSilent) { ReportMessageEx(m_hWnd, IDS_SITELINKBRIDGE_NEEDS_TWO_SITELINKS, MB_OK | MB_ICONSTOP); }
return E_FAIL; }
CCreateNewSiteLinkBridgeWizard:: CCreateNewSiteLinkBridgeWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo, const DSPROP_BSTR_BLOCK& bstrblockSiteLinks ) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) , m_page1( bstrblockSiteLinks ) { AddPage(&m_page1); }
// NTRAID#NTBUG9-283026-2001/06/13-lucios - Begin
// Extending the detection of <automatically generated>
// for object creation from JonN's original code inserted in
// rename.cpp, CDSRenameNTDSConnection::DoRename()
BOOL CCreateNewObjectConnectionWizard::OnFinish() { CString strNewName; m_page1.GetDlgItemText(IDC_EDIT_OBJECT_NAME,strNewName); strNewName.TrimLeft(); strNewName.TrimRight(); CString strKCCGenerated; strKCCGenerated.LoadString (IDS_CONNECTION_KCC_GENERATED); if ( !strNewName.CompareNoCase(strKCCGenerated) ) { TRACE (_T("CCreateNewObjectCnWizard::OnFinish blocked creation of object")); ReportErrorEx (m_page1.m_hWnd,IDS_CONNECTION_RENAME_KCCSTRING,S_OK, MB_OK | MB_ICONWARNING, NULL, 0); return false; }
return CCreateNewObjectCnWizard::OnFinish(); } // NTRAID#NTBUG9-283026-2001/06/13-lucios - End
|