WindowsXP-SP1/admin/snapin/dsadmin/dssnap.cpp
2020-09-30 16:53:49 +02:00

8011 lines
220 KiB
C++

//+-------------------------------------------------------------------------
//
// Windows NT Directory Service Administration SnapIn
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: dssnap.cpp
//
// Contents: DS App
//
// History: 02-Oct-96 WayneSc Created
// 06-Mar-97 EricB - added Property Page Extension support
// 24-Jul-97 Dan Morin - Integrated "Generic Create" wizard
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "util.h"
#include "uiutil.h"
#include "dsutil.h"
#include "dssnap.h"
#include "ContextMenu.h"
#include "DataObj.h"
#include "dsctx.h"
#include "DSdirect.h"
#include "dsdlgs.h"
#include "DSEvent.h"
#include "dsfilter.h"
#include "dsthread.h"
#include "fsmoui.h"
#include "helpids.h"
#include "newobj.h" // CNewADsObjectCreateInfo
#include "query.h"
#include "queryui.h"
#include "querysup.h"
#include "rename.h"
#include <notify.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define STRING_LEN (32 * sizeof(OLECHAR))
extern LPWSTR g_lpszLoggedInUser;
#define INITGUID
#include <initguid.h>
#include <dsadminp.h>
const wchar_t* SNAPIN_INTERNAL = L"DS_ADMIN_INTERNAL";
// Define the profiling statics
IMPLEMENT_PROFILING;
//////////////////////////////////////////////////////////////////////////////////
// standard attributes array (for queries)
const INT g_nStdCols = 8;
const LPWSTR g_pStandardAttributes[g_nStdCols] = {L"ADsPath",
L"name",
L"displayName",
L"objectClass",
L"groupType",
L"description",
L"userAccountControl",
L"systemFlags"};
extern const INT g_nADsPath = 0;
extern const INT g_nName = 1;
extern const INT g_nDisplayName = 2;
extern const INT g_nObjectClass = 3;
extern const INT g_nGroupType = 4;
extern const INT g_nDescription = 5;
extern const INT g_nUserAccountControl = 6;
extern const INT g_nSystemFlags = 7;
///////////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI CDsAdminModule::UpdateRegistryCLSID(const CLSID& clsid, BOOL bRegister)
{
static const WCHAR szIPS32[] = _T("InprocServer32");
static const WCHAR szCLSID[] = _T("CLSID");
static const WCHAR szThreadingModel[] = _T("ThreadingModel");
static const WCHAR szThreadModelValue[] = _T("Both");
HRESULT hRes = S_OK;
LPOLESTR lpOleStrCLSIDValue;
::StringFromCLSID(clsid, &lpOleStrCLSIDValue);
CRegKey key;
if (bRegister)
{
LONG lRes = key.Open(HKEY_CLASSES_ROOT, szCLSID);
if (lRes == ERROR_SUCCESS)
{
lRes = key.Create(key, lpOleStrCLSIDValue);
if (lRes == ERROR_SUCCESS)
{
WCHAR szModule[_MAX_PATH];
::GetModuleFileName(m_hInst, szModule, _MAX_PATH);
lRes = key.SetKeyValue(szIPS32, szModule);
if (lRes == ERROR_SUCCESS)
{
lRes = key.Open(key, szIPS32);
if (lRes == ERROR_SUCCESS)
{
key.SetValue(szThreadModelValue, szThreadingModel);
}
}
}
}
if (lRes != ERROR_SUCCESS)
hRes = HRESULT_FROM_WIN32(lRes);
}
else
{
key.Attach(HKEY_CLASSES_ROOT);
if (key.Open(key, szCLSID) == ERROR_SUCCESS)
key.RecurseDeleteKey(lpOleStrCLSIDValue);
}
::CoTaskMemFree(lpOleStrCLSIDValue);
return hRes;
}
CDsAdminModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_DSSnapin, CDSSnapin)
OBJECT_ENTRY(CLSID_DSSnapinEx, CDSSnapinEx)
OBJECT_ENTRY(CLSID_SiteSnapin, CSiteSnapin)
OBJECT_ENTRY(CLSID_DSAboutSnapin, CDSSnapinAbout)
OBJECT_ENTRY(CLSID_SitesAboutSnapin, CSitesSnapinAbout)
OBJECT_ENTRY(CLSID_DSContextMenu, CDSContextMenu)
OBJECT_ENTRY(CLSID_DsAdminCreateObj, CDsAdminCreateObj)
OBJECT_ENTRY(CLSID_DsAdminChooseDCObj, CDsAdminChooseDCObj)
OBJECT_ENTRY(CLSID_DSAdminQueryUIForm, CQueryFormBase)
END_OBJECT_MAP()
CCommandLineOptions _commandLineOptions;
class CDSApp : public CWinApp
{
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
};
CDSApp theApp;
BOOL CDSApp::InitInstance()
{
_Module.Init(ObjectMap, m_hInstance);
InitGroupTypeStringTable();
_commandLineOptions.Initialize();
return CWinApp::InitInstance();
}
int CDSApp::ExitInstance()
{
_Module.Term();
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
#if (FALSE)
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
#endif
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
#ifdef _USE_MFC
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE;
#else
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
#endif
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
LPCTSTR g_cszBasePath = _T("Software\\Microsoft\\MMC\\SnapIns");
LPCTSTR g_cszNameString = _T("NameString");
LPCTSTR g_cszNameStringIndirect = _T("NameStringIndirect");
LPCTSTR g_cszProvider = _T("Provider");
LPCTSTR g_cszVersion = _T("Version");
LPCTSTR g_cszAbout = _T("About");
LPCTSTR g_cszStandAlone = _T("StandAlone");
LPCTSTR g_cszExtension = _T("Extension");
LPCTSTR g_cszNodeTypes = _T("NodeTypes");
LPCTSTR GUIDToCString(REFGUID guid, CString & str)
{
USES_CONVERSION;
OLECHAR lpszGUID[128];
int nChars = ::StringFromGUID2(guid, lpszGUID, 128);
LPTSTR lpString = OLE2T(lpszGUID);
LPTSTR lpGUID = str.GetBuffer(nChars);
if (lpGUID)
{
CopyMemory(lpGUID, lpString, nChars*sizeof(TCHAR));
str.ReleaseBuffer();
}
return str;
}
HRESULT _RegisterSnapinHelper(CRegKey& rkBase, REFGUID guid,
REFGUID about, UINT nNameStringID,
BOOL bStandalone, CRegKey& rkCLSID)
{
HRESULT hr = S_OK;
CString strKey;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
CString str;
BOOL result;
// Create snapin GUID key and set properties
rkCLSID.Create(rkBase, GUIDToCString(guid, str));
result = str.LoadString (nNameStringID);
rkCLSID.SetValue(str, g_cszNameString);
// JonN 4/26/00 100624: MUI: MMC: Shared Folders snap-in
// stores its display information in the registry
{
WCHAR szModule[_MAX_PATH];
::GetModuleFileName(AfxGetInstanceHandle(), szModule, _MAX_PATH);
str.Format( _T("@%s,-%d"), szModule, nNameStringID );
rkCLSID.SetValue(str, g_cszNameStringIndirect);
}
str.LoadString (IDS_SNAPIN_PROVIDER);
rkCLSID.SetValue(str, g_cszProvider);
rkCLSID.SetValue(CString(_T("1.0")), g_cszVersion);
// Create "StandAlone" or "Extension" key
CRegKey rkStandAloneOrExtension;
rkStandAloneOrExtension.Create(rkCLSID, bStandalone ? g_cszStandAlone : g_cszExtension);
rkCLSID.SetValue (GUIDToCString(about, str),
g_cszAbout);
}
catch(CMemoryException * e)
{
e->Delete();
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
catch(COleException * e)
{
e->Delete();
hr = SELFREG_E_CLASS;
}
return hr;
}
void _RegisterNodeTypes(CRegKey& rkCLSID, UINT)
{
// Create "NodeTypes" key
CRegKey rkNodeTypes;
rkNodeTypes.Create(rkCLSID, g_cszNodeTypes);
// NodeTypes guids
CString str;
str.LoadString (IDS_SNAPIN_PROVIDER);
CRegKey rkN1;
rkN1.Create(rkNodeTypes, GUIDToCString(cDefaultNodeType, str));
}
void _RegisterQueryForms()
{
PWSTR pszDSQueryCLSID = NULL;
::StringFromCLSID(CLSID_DsQuery, &pszDSQueryCLSID);
ASSERT(pszDSQueryCLSID != NULL);
if (pszDSQueryCLSID != NULL)
{
CString szForms = pszDSQueryCLSID;
::CoTaskMemFree(pszDSQueryCLSID);
szForms = L"CLSID\\" + szForms;
CRegKey rkCLSID_DSQUERY_FORM;
LONG status = rkCLSID_DSQUERY_FORM.Open(HKEY_CLASSES_ROOT, szForms);
if (status != ERROR_SUCCESS)
{
return;
}
CRegKey rkDSUIFormKey;
status = rkDSUIFormKey.Create(rkCLSID_DSQUERY_FORM, L"Forms");
if (status == ERROR_SUCCESS)
{
PWSTR pszDSAFormCLSID = NULL;
::StringFromCLSID(CLSID_DSAdminQueryUIForm, &pszDSAFormCLSID);
ASSERT(pszDSAFormCLSID != NULL);
if (pszDSAFormCLSID != NULL)
{
CRegKey rkDSAdminFormKey;
status = rkDSAdminFormKey.Create(rkDSUIFormKey, pszDSAFormCLSID);
if (status == ERROR_SUCCESS)
{
rkDSAdminFormKey.SetValue(pszDSAFormCLSID, L"CLSID");
}
::CoTaskMemFree(pszDSAFormCLSID);
}
}
}
}
HRESULT RegisterSnapin()
{
HRESULT hr = S_OK;
CString strKey;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
CString str;
CRegKey rkBase;
INT status;
status = rkBase.Open(HKEY_LOCAL_MACHINE, g_cszBasePath);
if (status || !rkBase.m_hKey)
return hr;
// REGISTER DS ADMIN STANDALONE
CRegKey rkCLSID_DS;
hr = _RegisterSnapinHelper(rkBase, CLSID_DSSnapin, CLSID_DSAboutSnapin,
IDS_DS_MANAGER, TRUE, rkCLSID_DS);
if (SUCCEEDED(hr))
{
_RegisterNodeTypes(rkCLSID_DS, IDS_DS_MANAGER);
}
// REGISTER DS ADMIN EXTENSION
CRegKey rkCLSID_DS_EX;
hr = _RegisterSnapinHelper(rkBase, CLSID_DSSnapinEx, GUID_NULL,
IDS_DS_MANAGER_EX, FALSE, rkCLSID_DS_EX);
if (SUCCEEDED(hr) && rkCLSID_DS_EX.m_hKey != NULL)
{
_RegisterNodeTypes(rkCLSID_DS_EX, IDS_DS_MANAGER_EX);
}
// REGISTER SITE ADMIN STANDALONE
CRegKey rkCLSID_SITE;
hr = _RegisterSnapinHelper(rkBase, CLSID_SiteSnapin, CLSID_SitesAboutSnapin,
IDS_SITE_MANAGER, TRUE, rkCLSID_SITE);
if (SUCCEEDED(hr) && rkCLSID_SITE.m_hKey != NULL)
{
_RegisterNodeTypes(rkCLSID_SITE, IDS_SITE_MANAGER);
}
//
// Register dsquery forms extension
//
_RegisterQueryForms();
}
catch(CMemoryException * e)
{
e->Delete();
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
catch(COleException * e)
{
e->Delete();
hr = SELFREG_E_CLASS;
}
return hr;
}
HRESULT UnregisterSnapin()
{
HRESULT hr = S_OK;
try
{
CRegKey rkBase;
rkBase.Open(HKEY_LOCAL_MACHINE, g_cszBasePath);
if (rkBase.m_hKey != NULL)
{
CString str;
rkBase.RecurseDeleteKey(GUIDToCString(CLSID_DSSnapin, str));
rkBase.RecurseDeleteKey(GUIDToCString(CLSID_DSSnapinEx, str));
rkBase.RecurseDeleteKey(GUIDToCString(CLSID_SiteSnapin, str));
}
}
catch(CException * e)
{
DWORD err = ::GetLastError();
hr = HRESULT_FROM_WIN32(err);
e->Delete();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
HRESULT hRes = S_OK;
// registers objects
hRes = _Module.RegisterServer(FALSE);
if (FAILED(hRes))
return hRes;
hRes = RegisterSnapin();
return hRes;
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
_Module.UnregisterServer();
UnregisterSnapin();
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CTargetingInfo
const DWORD CTargetingInfo::m_dwSaveDomainFlag = 0x1;
#ifdef _MMC_ISNAPIN_PROPERTY
// properties the snapin supports
LPCWSTR g_szServer = L"Server";
LPCWSTR g_szDomain = L"Domain";
LPCWSTR g_szRDN = L"RDN";
HRESULT CTargetingInfo::InitFromSnapinProperties(long cProps, //property count
MMC_SNAPIN_PROPERTY* pProps) //properties array
{
TRACE(L"CTargetingInfo::InitFromSnapinProperties()\n");
// loop through the list of properties and set the variables
BOOL bDomainSpecified = FALSE;
for (long k=0; k< cProps; k++)
{
if (!bDomainSpecified && (_wcsicmp(pProps[k].pszPropName, g_szServer) == 0))
{
m_szStoredTargetName = pProps[k].varValue.bstrVal;
}
else if (_wcsicmp(pProps[k].pszPropName, g_szDomain) == 0)
{
// domain takes the precedence over server name
bDomainSpecified = TRUE;
m_szStoredTargetName = pProps[k].varValue.bstrVal;
}
else if (_wcsicmp(pProps[k].pszPropName, g_szRDN) == 0)
{
m_szRootRDN = pProps[k].varValue.bstrVal;
}
}
// remove leading and trailing blanks
m_szStoredTargetName.TrimLeft();
m_szStoredTargetName.TrimRight();
return S_OK;
}
#endif // _MMC_ISNAPIN_PROPERTY
void CTargetingInfo::_InitFromCommandLine()
{
// get the command line switches /Domain or /Server
LPCWSTR lpszDomainRoot = _commandLineOptions.GetDomainOverride();
LPCWSTR lpszServerName = _commandLineOptions.GetServerOverride();
// domain takes the precedence over server name
m_szStoredTargetName = (lpszDomainRoot != NULL) ? lpszDomainRoot : lpszServerName;
// remove leading and trailing blanks
m_szStoredTargetName.TrimLeft();
m_szStoredTargetName.TrimRight();
m_szRootRDN = _commandLineOptions.GetRDNOverride();
}
HRESULT CTargetingInfo::Load(IStream* pStm)
{
DWORD dwFlagsTemp;
HRESULT hr = LoadDWordHelper(pStm, (DWORD*)&dwFlagsTemp);
if (FAILED(hr))
return hr;
if (dwFlagsTemp == 0)
return S_OK;
if (m_szStoredTargetName.IsEmpty())
{
// no command line parameters:
// read flags and string from stream
m_dwFlags = dwFlagsTemp;
hr = LoadStringHelper(m_szStoredTargetName, pStm);
}
else
{
// have command line parameters:
// we do the load to preserve the loading sequence,
// but we discard the results
CString szThrowAway;
hr = LoadStringHelper(szThrowAway, pStm);
}
return hr;
}
HRESULT CTargetingInfo::Save(IStream* pStm, LPCWSTR lpszCurrentTargetName)
{
HRESULT hr = SaveDWordHelper(pStm, m_dwFlags);
if (FAILED(hr))
return hr;
if (m_dwFlags == 0)
return S_OK;
CString szTemp = lpszCurrentTargetName;
return SaveStringHelper(szTemp, pStm);
}
/////////////////////////////////////////////////////////////////////////////
// CIconManager
HRESULT CIconManager::Init(IImageList* pScpImageList, SnapinType snapintype)
{
if (pScpImageList == NULL)
return E_INVALIDARG;
m_pScpImageList = pScpImageList;
HRESULT hr;
hr = _LoadIconFromResource(
(snapintype == SNAPINTYPE_SITE) ? IDI_SITEREPL : IDI_DSADMIN,
&m_iRootIconIndex);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
return hr;
hr = _LoadIconFromResource(
(snapintype == SNAPINTYPE_SITE) ? IDI_SITEREPL_ERR : IDI_DSADMIN_ERR,
&m_iRootIconErrIndex);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
return hr;
hr = _LoadIconFromResource(IDI_ICON_WAIT, &m_iWaitIconIndex);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
return hr;
hr = _LoadIconFromResource(IDI_ICON_WARN, &m_iWarnIconIndex);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
return hr;
hr = _LoadIconFromResource(IDI_FAVORITES, &m_iFavoritesIconIndex);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
return hr;
hr = _LoadIconFromResource(IDI_QUERY, &m_iQueryIconIndex);
ASSERT(SUCCEEDED(hr));
hr = _LoadIconFromResource(IDI_QUERY_INVALID, &m_iQueryInvalidIconIndex);
ASSERT(SUCCEEDED(hr));
return hr;
}
HRESULT _SetIconHelper(IImageList* pImageList, HICON hiClass16, HICON hiClass32,
int iIndex, BOOL bAdd32 = FALSE)
{
HRESULT hr = pImageList->ImageListSetIcon((LONG_PTR *)hiClass16, iIndex);
if (SUCCEEDED(hr) && (hiClass32 != NULL))
{
#ifdef ILSI_LARGE_ICON
if (bAdd32)
{
HRESULT hr1 = pImageList->ImageListSetIcon((LONG_PTR *)hiClass32, ILSI_LARGE_ICON(iIndex));
ASSERT(SUCCEEDED(hr1));
}
#endif
}
return hr;
}
HRESULT CIconManager::FillInIconStrip(IImageList* pImageList)
{
// cannot do this passing a scope pane image list interface
ASSERT(m_pScpImageList != pImageList);
HRESULT hr = S_OK;
INT iTempIndex = _GetBaseIndex();
for (POSITION pos = m_IconInfoList.GetHeadPosition(); pos != NULL; )
{
CIconInfo* pInfo = m_IconInfoList.GetNext(pos);
hr = _SetIconHelper(pImageList, pInfo->m_hiClass16, pInfo->m_hiClass32, iTempIndex, TRUE);
if (FAILED(hr))
break;
iTempIndex++;
}
return hr;
}
HRESULT CIconManager::AddClassIcon(IN LPCWSTR lpszClass,
IN MyBasePathsInfo* pPathInfo,
IN DWORD dwFlags,
INOUT int* pnIndex)
{
HICON hiClass16 = pPathInfo->GetIcon(lpszClass, dwFlags, 16,16);
HICON hiClass32 = pPathInfo->GetIcon(lpszClass, dwFlags, 32,32);
return AddIcon(hiClass16, hiClass32, pnIndex);
}
HRESULT CIconManager::AddIcon(IN HICON hiClass16, IN HICON hiClass32, INOUT int* pnIndex)
{
ASSERT(pnIndex != NULL);
ASSERT(hiClass16 != NULL);
ASSERT(m_pScpImageList != NULL);
*pnIndex = -1;
int iNextIcon = _GetNextFreeIndex();
HRESULT hr = _SetIconHelper(m_pScpImageList, hiClass16, hiClass32, iNextIcon);
if (FAILED(hr))
return hr;
CIconInfo* pInfo = new CIconInfo;
if (pInfo)
{
pInfo->m_hiClass16 = hiClass16;
pInfo->m_hiClass32 = hiClass32;
m_IconInfoList.AddTail(pInfo);
*pnIndex = iNextIcon;
}
return hr;
}
HRESULT CIconManager::_LoadIconFromResource(IN UINT nIconResID, INOUT int* pnIndex)
{
ASSERT(pnIndex != NULL);
ASSERT(m_pScpImageList != NULL);
HICON hIcon = ::LoadIcon(_Module.GetModuleInstance(),
MAKEINTRESOURCE(nIconResID));
ASSERT(hIcon != NULL);
if (hIcon == NULL)
return E_INVALIDARG;
return AddIcon(hIcon, NULL, pnIndex);
}
/////////////////////////////////////////////////////////////////////////////
// CInternalFormatCracker
HRESULT CInternalFormatCracker::Extract(LPDATAOBJECT lpDataObject)
{
_Free();
if (lpDataObject == NULL)
return E_INVALIDARG;
SMMCDataObjects * pDO = NULL;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { CDSDataObject::m_cfInternal, NULL,
DVASPECT_CONTENT, -1, TYMED_HGLOBAL
};
FORMATETC formatetc2 = { CDSDataObject::m_cfMultiSelDataObjs, NULL,
DVASPECT_CONTENT, -1, TYMED_HGLOBAL
};
HRESULT hr = lpDataObject->GetData(&formatetc2, &stgmedium);
if (FAILED(hr)) {
// Attempt to get data from the object
do
{
hr = lpDataObject->GetData(&formatetc, &stgmedium);
if (FAILED(hr))
break;
m_pInternalFormat = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
if (m_pInternalFormat == NULL)
{
if (SUCCEEDED(hr))
hr = E_FAIL;
break;
}
} while (FALSE);
return hr;
} else {
pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
for (UINT i = 0; i < pDO->count; i++) {
hr = pDO->lpDataObject[i]->GetData(&formatetc, &stgmedium);
if (FAILED(hr))
break;
m_pInternalFormat = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal);
if (m_pInternalFormat != NULL)
break;
}
}
return hr;
}
LPDATAOBJECT
CInternalFormatCracker::ExtractMultiSelect(LPDATAOBJECT lpDataObject)
{
_Free();
if (lpDataObject == NULL)
return NULL;
SMMCDataObjects * pDO = NULL;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { CDSDataObject::m_cfMultiSelDataObjs, NULL,
DVASPECT_CONTENT, -1, TYMED_HGLOBAL
};
if (FAILED(lpDataObject->GetData(&formatetc, &stgmedium))) {
return NULL;
} else {
pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
return pDO->lpDataObject[0]; //assume that ours is the 1st
}
}
/////////////////////////////////////////////////////////////////////
// CObjectNamesFormatCracker
CLIPFORMAT CObjectNamesFormatCracker::m_cfDsObjectNames =
(CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
HRESULT CObjectNamesFormatCracker::Extract(LPDATAOBJECT lpDataObject)
{
_Free();
if (lpDataObject == NULL)
return E_INVALIDARG;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { m_cfDsObjectNames, NULL,
DVASPECT_CONTENT, -1, TYMED_HGLOBAL
};
HRESULT hr = lpDataObject->GetData(&formatetc, &stgmedium);
if (FAILED(hr))
{
return hr;
}
m_pDsObjectNames = reinterpret_cast<LPDSOBJECTNAMES>(stgmedium.hGlobal);
if (m_pDsObjectNames == NULL)
{
if (SUCCEEDED(hr))
hr = E_FAIL;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
// CDSNotifyHandlerManager
typedef struct
{
DWORD cNotifyExtensions; // how many extension CLSIDs?
CLSID aNotifyExtensions[1];
} DSCLASSNOTIFYINFO, * LPDSCLASSNOTIFYINFO;
HRESULT DsGetClassNotifyInfo(IN MyBasePathsInfo* pBasePathInfo,
OUT LPDSCLASSNOTIFYINFO* ppInfo)
{
static LPCWSTR lpszSettingsObjectClass = L"dsUISettings";
static LPCWSTR lpszSettingsObject = L"cn=DS-UI-Default-Settings";
static LPCWSTR lpszNotifyProperty = L"dsUIAdminNotification";
if ( (ppInfo == NULL) || (pBasePathInfo == NULL) )
return E_INVALIDARG;
*ppInfo = NULL;
// get the display specifiers locale container (e.g. 409)
CComPtr<IADsContainer> spLocaleContainer;
HRESULT hr = pBasePathInfo->GetDisplaySpecifier(NULL, IID_IADsContainer, (void**)&spLocaleContainer);
if (FAILED(hr))
return hr;
// bind to the settings object
CComPtr<IDispatch> spIDispatchObject;
hr = spLocaleContainer->GetObject((LPWSTR)lpszSettingsObjectClass,
(LPWSTR)lpszSettingsObject,
&spIDispatchObject);
if (FAILED(hr))
return hr;
CComPtr<IADs> spSettingsObject;
hr = spIDispatchObject->QueryInterface(IID_IADs, (void**)&spSettingsObject);
if (FAILED(hr))
return hr;
// get multivaled property in string list form
CComVariant var;
CStringList stringList;
hr = spSettingsObject->Get((LPWSTR)lpszNotifyProperty, &var);
if (FAILED(hr))
return hr;
hr = HrVariantToStringList(var, stringList);
if (FAILED(hr))
return hr;
size_t nCount = stringList.GetCount();
// allocate memory
DWORD cbCount = sizeof(DSCLASSNOTIFYINFO);
if (nCount>1)
cbCount += static_cast<ULONG>((nCount-1)*sizeof(CLSID));
*ppInfo = (LPDSCLASSNOTIFYINFO)::LocalAlloc(LPTR, cbCount);
if ((*ppInfo) == NULL)
return E_OUTOFMEMORY;
ZeroMemory(*ppInfo, cbCount);
(*ppInfo)->cNotifyExtensions = 0;
int* pArr = new int[nCount];
if (!pArr)
{
return E_OUTOFMEMORY;
}
CString szEntry, szIndex, szGUID;
for (POSITION pos = stringList.GetHeadPosition(); pos != NULL; )
{
szEntry = stringList.GetNext(pos);
int nComma = szEntry.Find(L",");
if (nComma == -1)
continue;
szIndex = szEntry.Left(nComma);
int nIndex = _wtoi((LPCWSTR)szIndex);
if (nIndex <= 0)
continue; // allow from 1 up
// strip leading and traling blanks
szGUID = szEntry.Mid(nComma+1);
szGUID.TrimLeft();
szGUID.TrimRight();
GUID* pGuid= &((*ppInfo)->aNotifyExtensions[(*ppInfo)->cNotifyExtensions]);
hr = ::CLSIDFromString((LPWSTR)(LPCWSTR)szGUID, pGuid);
if (SUCCEEDED(hr))
{
pArr[(*ppInfo)->cNotifyExtensions] = nIndex;
((*ppInfo)->cNotifyExtensions)++;
}
}
if (((*ppInfo)->cNotifyExtensions) > 1)
{
// need to sort by index in pArr
while (TRUE)
{
BOOL bSwapped = FALSE;
for (UINT k=1; k < ((*ppInfo)->cNotifyExtensions); k++)
{
if (pArr[k] < pArr[k-1])
{
// swap
int nTemp = pArr[k];
pArr[k] = pArr[k-1];
pArr[k-1] = nTemp;
GUID temp = (*ppInfo)->aNotifyExtensions[k];
(*ppInfo)->aNotifyExtensions[k] = (*ppInfo)->aNotifyExtensions[k-1];
(*ppInfo)->aNotifyExtensions[k-1] = temp;
bSwapped = TRUE;
}
}
if (!bSwapped)
break;
}
}
delete[] pArr;
pArr = 0;
return S_OK;
}
HRESULT CDSNotifyHandlerManager::Init()
{
_Free(); // prepare for delayed initialization
return S_OK;
}
HRESULT CDSNotifyHandlerManager::Load(MyBasePathsInfo* pBasePathInfo)
{
if (m_state != uninitialized)
return S_OK; // already done, bail out
// start the initialization process
ASSERT(m_pInfoArr == NULL);
m_state = noHandlers;
LPDSCLASSNOTIFYINFO pInfo = NULL;
HRESULT hr = DsGetClassNotifyInfo(pBasePathInfo, &pInfo);
if (SUCCEEDED(hr) && (pInfo != NULL) && (pInfo->cNotifyExtensions > 0))
{
m_nArrSize = pInfo->cNotifyExtensions;
m_pInfoArr = new CDSNotifyHandlerInfo[m_nArrSize];
for (DWORD i=0; i<pInfo->cNotifyExtensions; i++)
{
hr = ::CoCreateInstance(pInfo->aNotifyExtensions[i],
NULL, CLSCTX_INPROC_SERVER,
IID_IDsAdminNotifyHandler,
(void**)(&m_pInfoArr[i].m_spIDsAdminNotifyHandler));
if (SUCCEEDED(hr) && m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL)
{
hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Initialize(NULL,
&(m_pInfoArr[i].m_nRegisteredEvents));
if (FAILED(hr) || m_pInfoArr[i].m_nRegisteredEvents == 0)
{
// release if init failed or not registered for any event
m_pInfoArr[i].m_spIDsAdminNotifyHandler = NULL;
}
else
{
m_state = hasHandlers;
} //if
} //if
} // for
} // if
if (pInfo != NULL)
::LocalFree(pInfo);
return S_OK;
}
void CDSNotifyHandlerManager::Begin(ULONG uEvent, IDataObject* pArg1, IDataObject* pArg2)
{
ASSERT(m_state == hasHandlers);
HRESULT hr;
for (UINT i=0; i<m_nArrSize; i++)
{
ASSERT(!m_pInfoArr[i].m_bTransactionPending);
ASSERT(!m_pInfoArr[i].m_bNeedsNotify);
ASSERT(m_pInfoArr[i].m_nFlags == 0);
ASSERT(m_pInfoArr[i].m_szDisplayString.IsEmpty());
if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
(m_pInfoArr[i].m_nRegisteredEvents & uEvent) )
{
//
// this call is to set the context information for the event,
// we ignore the returned result
//
CComBSTR bstr;
hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Begin(
uEvent, pArg1, pArg2,
&(m_pInfoArr[i].m_nFlags), &bstr);
if (SUCCEEDED(hr) && (bstr != NULL) && (bstr[0] != NULL))
{
//
// extension accepted the notification
//
m_pInfoArr[i].m_bNeedsNotify = TRUE;
m_pInfoArr[i].m_szDisplayString = bstr;
}
//
// mark the extension with a pending transaction
// on it. we will have to call End()
//
m_pInfoArr[i].m_bTransactionPending = TRUE;
} //if
} // for
}
void CDSNotifyHandlerManager::Notify(ULONG nItem, ULONG uEvent)
{
ASSERT(m_state == hasHandlers);
HRESULT hr;
for (UINT i=0; i<m_nArrSize; i++)
{
if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
(m_pInfoArr[i].m_nRegisteredEvents & uEvent) && m_pInfoArr[i].m_bNeedsNotify)
{
// should only call if the transaction was started by a Begin() call
ASSERT(m_pInfoArr[i].m_bTransactionPending);
hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->Notify(nItem,
m_pInfoArr[i].m_nFlags);
} //if
} // for
}
void CDSNotifyHandlerManager::End(ULONG uEvent)
{
ASSERT(m_state == hasHandlers);
HRESULT hr;
for (UINT i=0; i<m_nArrSize; i++)
{
if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
(m_pInfoArr[i].m_nRegisteredEvents & uEvent) )
{
ASSERT(m_pInfoArr[i].m_bTransactionPending);
hr = m_pInfoArr[i].m_spIDsAdminNotifyHandler->End();
// reset the state flags
m_pInfoArr[i].m_bNeedsNotify = FALSE;
m_pInfoArr[i].m_bTransactionPending = FALSE;
m_pInfoArr[i].m_nFlags= 0;
m_pInfoArr[i].m_szDisplayString.Empty();
} //if
} // for
}
UINT CDSNotifyHandlerManager::NeedNotifyCount(ULONG uEvent)
{
ASSERT(m_state == hasHandlers);
UINT iCount = 0;
for (UINT i=0; i<m_nArrSize; i++)
{
if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
(m_pInfoArr[i].m_nRegisteredEvents & uEvent) &&
m_pInfoArr[i].m_bNeedsNotify)
{
ASSERT(m_pInfoArr[i].m_bTransactionPending);
iCount++;
} //if
} // for
return iCount;
}
void CDSNotifyHandlerManager::SetCheckListBox(CCheckListBox* pCheckListBox, ULONG uEvent)
{
ASSERT(m_state == hasHandlers);
UINT iListBoxIndex = 0;
for (UINT i=0; i<m_nArrSize; i++)
{
if ( (m_pInfoArr[i].m_spIDsAdminNotifyHandler != NULL) &&
(m_pInfoArr[i].m_nRegisteredEvents & uEvent) &&
m_pInfoArr[i].m_bNeedsNotify)
{
ASSERT(m_pInfoArr[i].m_bTransactionPending);
pCheckListBox->InsertString(iListBoxIndex, m_pInfoArr[i].m_szDisplayString);
int nCheck = 0;
if (m_pInfoArr[i].m_nFlags & DSA_NOTIFY_FLAG_ADDITIONAL_DATA)
nCheck = 1;
pCheckListBox->SetCheck(iListBoxIndex, nCheck);
if (m_pInfoArr[i].m_nFlags & DSA_NOTIFY_FLAG_FORCE_ADDITIONAL_DATA)
pCheckListBox->Enable(iListBoxIndex, FALSE);
pCheckListBox->SetItemData(iListBoxIndex, (DWORD_PTR)(&m_pInfoArr[i]));
iListBoxIndex++;
} //if
} // for
}
void CDSNotifyHandlerManager::ReadFromCheckListBox(CCheckListBox* pCheckListBox, ULONG)
{
ASSERT(m_state == hasHandlers);
int nCount = pCheckListBox->GetCount();
ASSERT(nCount != LB_ERR);
for (int i=0; i< nCount; i++)
{
int nCheck = pCheckListBox->GetCheck(i);
CDSNotifyHandlerInfo* pInfo = (CDSNotifyHandlerInfo*)
pCheckListBox->GetItemData(i);
ASSERT(pInfo != NULL);
if ((pInfo->m_nFlags & DSA_NOTIFY_FLAG_FORCE_ADDITIONAL_DATA) == 0)
{
if (nCheck == 0)
pInfo->m_nFlags &= ~DSA_NOTIFY_FLAG_ADDITIONAL_DATA;
else
pInfo->m_nFlags |= DSA_NOTIFY_FLAG_ADDITIONAL_DATA;
}
} // for
}
//////////////////////////////////////////////////////////////////////
// IComponentData implementation
// WARNING this ctor passes an incomplete "this" pointer to other ctors
CDSComponentData::CDSComponentData() :
m_pShlInit(NULL),
m_pScope(NULL),
m_pFrame(NULL)
#ifdef _MMC_ISNAPIN_PROPERTY
,
m_pProperties(NULL)
#endif //_MMC_ISNAPIN_PROPERTY
{
ExceptionPropagatingInitializeCriticalSection(&m_cs);
m_ActiveDS = NULL;
m_pClassCache = NULL;
m_pQueryFilter = NULL;
m_pFavoritesNodesHolder = NULL;
m_pHiddenWnd = NULL;
m_pBackgroundThreadInfo = new CBackgroundThreadInfo;
m_pScpImageList = NULL;
m_bRunAsPrimarySnapin = TRUE;
m_bAddRootWhenExtended = FALSE;
m_bDirty = FALSE;
m_SerialNumber = 1000; // arbitrary starting point
m_ColumnWidths[0] = DEFAULT_NAME_COL_WIDTH;
m_ColumnWidths[1] = DEFAULT_TYPE_COL_WIDTH;
m_ColumnWidths[2] = DEFAULT_DESC_COL_WIDTH;
m_InitSuccess = FALSE;
m_InitAttempted = FALSE;
m_lpszSnapinHelpFile = NULL;
}
HRESULT CDSComponentData::FinalConstruct()
{
// This must be delayed until this ctor so that the virtual
// callouts work propery
// create and initialize hidden window
m_pHiddenWnd = new CHiddenWnd(this);
if (m_pHiddenWnd == NULL)
return E_OUTOFMEMORY;
if (!m_pHiddenWnd->Create())
{
TRACE(_T("Failed to create hidden window\n"));
ASSERT(FALSE);
return E_FAIL;
}
// create directory object
m_ActiveDS = new CDSDirect (this);
if (m_ActiveDS == NULL)
return E_OUTOFMEMORY;
// create class cache
m_pClassCache = new CDSCache;
if (m_pClassCache == NULL)
return E_OUTOFMEMORY;
m_pClassCache->Initialize(QuerySnapinType(), GetBasePathsInfo(), TRUE);
// create saved queries holder
if (QuerySnapinType() == SNAPINTYPE_DS)
{
m_pFavoritesNodesHolder = new CFavoritesNodesHolder();
if (m_pFavoritesNodesHolder == NULL)
return E_OUTOFMEMORY;
// REVIEW_MARCOC_PORT this is just to test/demo
// m_pFavoritesNodesHolder->BuildTestTree(_commandLineOptions.GetSavedQueriesXMLFile(),
// QuerySnapinType());
// graft the subtree under the snapin root
m_RootNode.GetFolderInfo()->AddNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
}
// create filter
m_pQueryFilter = new CDSQueryFilter();
if (m_pQueryFilter == NULL)
return E_OUTOFMEMORY;
/* BUGBUG BUGBUG: this is a gross hack to get around a blunder
in dsuiext.dll. in order to see get DS extension information,
we MUST have USERDNSDOMAIN set in the environment
*/
{
WCHAR * pszUDD = NULL;
pszUDD = _wgetenv (L"USERDNSDOMAIN");
if (pszUDD == NULL) {
_wputenv (L"USERDNSDOMAIN=not-present");
}
}
return S_OK;
}
void CDSComponentData::FinalRelease()
{
_DeleteHiddenWnd();
// Dump the profiling data
DUMP_PROFILING_RESULTS;
}
CDSComponentData::~CDSComponentData()
{
TRACE(_T("~CDSComponentData entered...\n"));
::DeleteCriticalSection(&m_cs);
ASSERT(m_pScope == NULL);
if (m_pBackgroundThreadInfo != NULL)
{
delete m_pBackgroundThreadInfo;
}
// clean up the Class Cache
if (m_pClassCache != NULL)
{
delete m_pClassCache;
m_pClassCache = NULL;
}
// cleanup saved queries holder
if (m_pFavoritesNodesHolder != NULL)
{
m_RootNode.GetFolderInfo()->RemoveNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
delete m_pFavoritesNodesHolder;
m_pFavoritesNodesHolder = NULL;
}
// clean up the ADSI interface
if (m_ActiveDS != NULL)
{
delete m_ActiveDS;
m_ActiveDS = NULL;
}
if (m_pShlInit)
{
m_pShlInit->Release();
m_pShlInit = NULL;
}
if (m_pScpImageList) {
m_pScpImageList->Release();
m_pScpImageList = NULL;
}
if (m_pQueryFilter) {
delete m_pQueryFilter;
m_pQueryFilter = NULL;
}
if (g_lpszLoggedInUser != NULL)
{
delete[] g_lpszLoggedInUser;
g_lpszLoggedInUser = NULL;
}
TRACE(_T("~CDSComponentData leaving...\n"));
}
HWND CDSComponentData::GetHiddenWindow()
{
ASSERT(m_pHiddenWnd != NULL);
ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
return m_pHiddenWnd->m_hWnd;
}
void CDSComponentData::_DeleteHiddenWnd()
{
if (m_pHiddenWnd == NULL)
return;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_pHiddenWnd->m_hWnd != NULL)
{
VERIFY(m_pHiddenWnd->DestroyWindow());
}
delete m_pHiddenWnd;
m_pHiddenWnd = NULL;
}
BOOL CDSComponentData::ExpandComputers()
{
Lock();
BOOL b = m_pQueryFilter->ExpandComputers();
Unlock();
return b;
}
BOOL CDSComponentData::IsAdvancedView()
{
return m_pQueryFilter->IsAdvancedView();
}
BOOL CDSComponentData::ViewServicesNode()
{
return m_pQueryFilter->ViewServicesNode();
}
class CLockHandler
{
public:
CLockHandler(CDSComponentData* pCD)
{
m_pCD = pCD;
m_pCD->Lock();
}
~CLockHandler()
{
m_pCD->Unlock();
}
private:
CDSComponentData* m_pCD;
};
STDMETHODIMP CDSComponentData::Initialize(LPUNKNOWN pUnknown)
{
ASSERT(pUnknown != NULL);
HRESULT hr;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// MMC should only call ::Initialize once!
ASSERT(m_pScope == NULL);
pUnknown->QueryInterface(IID_IConsoleNameSpace2,
reinterpret_cast<void**>(&m_pScope));
// Get console's pre-registered clipboard formats
hr = pUnknown->QueryInterface(IID_IConsole3, reinterpret_cast<void**>(&m_pFrame));
if (FAILED(hr))
{
TRACE(TEXT("QueryInterface for IID_IConsole3 failed, hr: 0x%x\n"), hr);
return hr;
}
//
// Bind to the property sheet COM object at startup and hold its pointer
// until shutdown so that its cache can live as long as us.
//
hr = CoCreateInstance(CLSID_DsPropertyPages, NULL, CLSCTX_INPROC_SERVER,
IID_IShellExtInit, (void **)&m_pShlInit);
if (FAILED(hr))
{
TRACE(TEXT("CoCreateInstance on CLSID_DsPropertyPages failed, hr: 0x%x\n"), hr);
return hr;
}
hr = m_pFrame->QueryScopeImageList (&m_pScpImageList);
if (FAILED(hr))
{
TRACE(TEXT("Query for ScopeImageList failed, hr: 0x%x\n"), hr);
return hr;
}
hr = m_iconManager.Init(m_pScpImageList, QuerySnapinType());
if (FAILED(hr))
{
TRACE(TEXT("m_iconManager.Init() failed, hr: 0x%x\n"), hr);
return hr;
}
if (!_StartBackgroundThread())
return E_FAIL;
m_pFrame->GetMainWindow(&m_hwnd);
// NOTICE: we should initialize the filter only if the MyBasePathsInfo
// initialization call has succeeded (need schema path for filtering).
// In reality, we need the filter initialized for loading from a stream:
// with a failure, this initialization is "wrong" because it has
// bad naming context info, but we will re initalize when we get good
// info through retargeting
hr = m_pQueryFilter->Init(this);
if (FAILED(hr))
return hr;
return S_OK;
}
STDMETHODIMP CDSComponentData::CreateComponent(LPCOMPONENT* ppComponent)
{
ASSERT(ppComponent != NULL);
CComObject<CDSEvent>* pObject;
CComObject<CDSEvent>::CreateInstance(&pObject);
ASSERT(pObject != NULL);
// Store IComponentData
pObject->SetIComponentData(this);
return pObject->QueryInterface(IID_IComponent,
reinterpret_cast<void**>(ppComponent));
}
STDMETHODIMP CDSComponentData::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT(m_pScope != NULL);
HRESULT hr = S_FALSE;
CUINode* pUINode = NULL;
// Since it's my folder it has an internal format.
// Design Note: for extension. I can use the fact, that the data object doesn't have
// my internal format and I should look at the node type and see how to extend it.
if (lpDataObject != NULL)
{
CInternalFormatCracker dobjCracker;
if (FAILED(dobjCracker.Extract(lpDataObject)))
{
if ((event == MMCN_EXPAND) && (arg == TRUE) && !m_bRunAsPrimarySnapin)
{
// this is a namespace extension, need to add
// the root of the snapin
hr = _OnNamespaceExtensionExpand(lpDataObject, param);
if (FAILED(hr))
{
hr = S_FALSE;
}
return hr;
}
return S_OK;
}
// got a valid data object
pUINode = dobjCracker.GetCookie();
}
if (event == MMCN_PROPERTY_CHANGE)
{
TRACE(_T("CDSComponentData::Notify() - property change, pDataObj = 0x%08x, param = 0x%08x, arg = %d.\n"),
lpDataObject, param, arg);
if (param != 0)
{
hr = _OnPropertyChange((LPDATAOBJECT)param, TRUE);
if (FAILED(hr))
{
hr = S_FALSE;
}
return hr;
}
return S_FALSE;
}
if (pUINode == NULL)
return S_FALSE;
switch (event)
{
case MMCN_PRELOAD:
{
_OnPreload((HSCOPEITEM)arg);
hr = S_OK;
}
break;
case MMCN_EXPANDSYNC:
{
MMC_EXPANDSYNC_STRUCT* pExpandStruct =
reinterpret_cast<MMC_EXPANDSYNC_STRUCT*>(param);
if (pExpandStruct->bExpanding)
{
_OnExpand(pUINode, pExpandStruct->hItem,event);
pExpandStruct->bHandled = TRUE;
hr = S_OK;
}
}
break;
case MMCN_EXPAND:
if (arg == TRUE)
{ // Show
_OnExpand(pUINode,(HSCOPEITEM)param,event);
hr = S_OK;
}
break;
case MMCN_DELETE:
{
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
if (pDSUINode == NULL)
{
hr = pUINode->Delete(this);
}
else
{
hr = _DeleteFromBackendAndUI(lpDataObject, pDSUINode);
}
if (FAILED(hr))
{
hr = S_FALSE;
}
}
break;
case MMCN_RENAME:
hr = _Rename (pUINode, (LPWSTR)param);
if (FAILED(hr))
{
hr = S_FALSE;
}
break;
case MMCN_REFRESH:
hr = Refresh (pUINode);
if (FAILED(hr))
{
hr = S_FALSE;
}
break;
default:
hr = S_FALSE;
}
return hr;
}
STDMETHODIMP CDSComponentData::Destroy()
{
// sever all ties with cookies having pending requests
m_queryNodeTable.Reset();
// wait for all the threads to shut down.
_ShutDownBackgroundThread();
// destroy the hidden window
_DeleteHiddenWnd();
if (m_pScope)
{
m_pScope->Release();
m_pScope = NULL;
}
if (m_pFrame)
{
m_pFrame->Release();
m_pFrame = NULL;
}
#ifdef _MMC_ISNAPIN_PROPERTY
if (m_pProperties)
{
m_pProperties->Release();
m_pProperties = NULL;
}
#endif //_MMC_ISNAPIN_PROPERTY
return S_OK;
}
STDMETHODIMP CDSComponentData::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
ASSERT(ppDataObject != NULL);
HRESULT hr;
CUINode* pNode;
CComObject<CDSDataObject>* pObject;
CComObject<CDSDataObject>::CreateInstance(&pObject);
ASSERT(pObject != NULL);
if (pObject != NULL)
{
// Check to see if we have a valid cookie or we should use the snapin
// cookie
//
pNode = reinterpret_cast<CUINode*>(cookie);
if (pNode == NULL)
{
pNode = &m_RootNode;
}
// Save cookie and type for delayed rendering
pObject->SetType(type, QuerySnapinType());
pObject->SetComponentData(this);
pObject->SetCookie(pNode);
hr = pObject->QueryInterface(IID_IDataObject,
reinterpret_cast<void**>(ppDataObject));
//TRACE(_T("xx.%03x> CDSComponentData::QueryDataObject (CDsDataObject 0x%x)\n"),
// GetCurrentThreadId(), *ppDataObject);
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
STDMETHODIMP CDSComponentData::GetDisplayInfo(LPSCOPEDATAITEM scopeInfo)
{
CUINode* pNode = reinterpret_cast<CUINode*>(scopeInfo->lParam);
ASSERT(pNode != NULL);
ASSERT(pNode->IsContainer());
if (scopeInfo->mask & SDI_STR)
{
#ifdef DBG
BOOL bNoName = (pNode->GetParent() == &m_RootNode) && _commandLineOptions.IsNoNameCommandLine();
scopeInfo->displayname = bNoName ? L"" : const_cast<LPTSTR>(pNode->GetName());
#else
scopeInfo->displayname = const_cast<LPTSTR>(pNode->GetName());
#endif
}
if (scopeInfo->mask & SDI_IMAGE)
{
scopeInfo->nImage = GetImage(pNode, FALSE);
}
if (scopeInfo->mask & SDI_OPENIMAGE)
{
scopeInfo->nOpenImage = GetImage(pNode, TRUE);
}
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//// IPersistStream interface members
STDMETHODIMP CDSComponentData::GetClassID(CLSID *pClassID)
{
ASSERT(pClassID != NULL);
ASSERT(m_bRunAsPrimarySnapin);
// Copy the CLSID for this snapin
switch (QuerySnapinType())
{
case SNAPINTYPE_DS:
*pClassID = CLSID_DSSnapin;
break;
case SNAPINTYPE_DSEX:
*pClassID = CLSID_DSSnapinEx;
break;
case SNAPINTYPE_SITE:
*pClassID = CLSID_SiteSnapin;
break;
default:
ASSERT(FALSE);
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP CDSComponentData::IsDirty()
{
ASSERT(m_bRunAsPrimarySnapin);
m_pFrame->UpdateAllViews(NULL, NULL, DS_CHECK_COLUMN_WIDTHS);
return m_bDirty ? S_OK : S_FALSE;
}
// IMPORTANT NOTICE: this value has to be bumped up EVERY time
// a change is made to the stream format
#define DS_STREAM_VERSION ((DWORD)0x08)
#define DS_STREAM_BEFORE_SAVED_QUERIES ((DWORD)0x07)
#define DS_STREAM_W2K_VERSION ((DWORD)0x07)
STDMETHODIMP CDSComponentData::Load(IStream *pStm)
{
// serialization on extensions not supported
if (!m_bRunAsPrimarySnapin)
return E_FAIL;
ASSERT(pStm);
// read the version ##
DWORD dwVersion;
HRESULT hr = LoadDWordHelper(pStm, &dwVersion);
// if ( FAILED(hr) ||(dwVersion != DS_STREAM_VERSION) )
if (FAILED(hr) || dwVersion < DS_STREAM_W2K_VERSION)
return E_FAIL;
// read targeting info
hr = m_targetingInfo.Load(pStm);
if (FAILED(hr))
return hr;
//
// Initialize the root from the target info so that columns
// can be loaded from the DS
//
hr = _InitRootFromCurrentTargetInfo();
if (FAILED(hr))
return hr;
// read filtering options
hr = m_pQueryFilter->Load(pStm);
if (FAILED(hr))
return hr;
// read the class cache information
hr = m_pClassCache->Load(pStm);
if (FAILED(hr))
return hr;
if (dwVersion > DS_STREAM_BEFORE_SAVED_QUERIES)
{
hr = m_pFavoritesNodesHolder->Load(pStm, this);
if (FAILED(hr))
{
return hr;
}
}
m_bDirty = FALSE; // start clean
return hr;
}
STDMETHODIMP CDSComponentData::Save(IStream *pStm, BOOL fClearDirty)
{
// serialization on extensions not supported
if (!m_bRunAsPrimarySnapin)
return E_FAIL;
ASSERT(pStm);
// write the version ##
HRESULT hr = SaveDWordHelper(pStm, DS_STREAM_VERSION);
if (FAILED(hr))
return hr;
// save targeting info
hr = m_targetingInfo.Save(pStm, GetBasePathsInfo()->GetDomainName());
if (FAILED(hr))
return hr;
// save filtering options
hr = m_pQueryFilter->Save(pStm);
if (FAILED(hr))
return hr;
// save the class cache information
hr = m_pClassCache->Save(pStm);
if (FAILED(hr))
return hr;
if (QuerySnapinType() == SNAPINTYPE_DS)
{
//
// Save the saved queries folder for dsadmin only
//
hr = m_pFavoritesNodesHolder->Save(pStm);
if (FAILED(hr))
return hr;
}
if (fClearDirty)
m_bDirty = FALSE;
return hr;
}
STDMETHODIMP CDSComponentData::GetSizeMax(ULARGE_INTEGER *pcbSize)
{
ASSERT(pcbSize);
ASSERT(FALSE);
//
// Arbitrary values but I don't think we ever get called
//
pcbSize->LowPart = 0xffff;
pcbSize->HighPart= 0x0;
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// IExtendPropertySheet Implementation
//+----------------------------------------------------------------------------
//
// Member: CDSComponentData::IExtendPropertySheet::CreatePropertyPages
//
// Synopsis: Called in response to a user click on the Properties context
// menu item.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CDSComponentData::CreatePropertyPages(LPPROPERTYSHEETCALLBACK pCall,
LONG_PTR lNotifyHandle,
LPDATAOBJECT pDataObject)
{
CDSCookie* pCookie = NULL;
TRACE(_T("xx.%03x> CDSComponentData::CreatePropertyPages()\n"),
GetCurrentThreadId());
//
// Validate Inputs
//
if (pCall == NULL)
{
return E_INVALIDARG;
}
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
CInternalFormatCracker dobjCracker;
if (FAILED(dobjCracker.Extract(pDataObject)))
{
return E_NOTIMPL;
}
//
// Pass the Notify Handle to the data object.
//
PROPSHEETCFG SheetCfg = {lNotifyHandle};
FORMATETC fe = {CDSDataObject::m_cfPropSheetCfg, NULL, DVASPECT_CONTENT,
-1, TYMED_HGLOBAL};
STGMEDIUM sm = {TYMED_HGLOBAL, NULL, NULL};
sm.hGlobal = (HGLOBAL)&SheetCfg;
pDataObject->SetData(&fe, &sm, FALSE);
if (dobjCracker.GetCookieCount() > 1) // multiple selection
{
//
// Pass a unique identifier to the data object
//
GUID guid;
hr = ::CoCreateGuid(&guid);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
WCHAR pszGuid[40];
if (!::StringFromGUID2(guid, pszGuid, 40))
{
ASSERT(FALSE);
return E_FAIL;
}
FORMATETC multiSelectfe = {CDSDataObject::m_cfMultiSelectProppage, NULL, DVASPECT_CONTENT,
-1, TYMED_HGLOBAL};
STGMEDIUM multiSelectsm = {TYMED_HGLOBAL, NULL, NULL};
multiSelectsm.hGlobal = (HGLOBAL)pszGuid;
pDataObject->SetData(&multiSelectfe, &multiSelectsm, FALSE);
hr = GetClassCache()->TabCollect_AddMultiSelectPropertyPages(pCall, lNotifyHandle, pDataObject, GetBasePathsInfo());
}
else // single selection
{
CUINode* pUINode = dobjCracker.GetCookie();
if (pUINode == NULL)
{
return E_NOTIMPL;
}
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
if (pDSUINode == NULL)
{
//
// Delegate page creation to the node
//
return pUINode->CreatePropertyPages(pCall, lNotifyHandle, pDataObject, this);
}
pCookie = GetDSCookieFromUINode(pDSUINode);
ASSERT(pCookie != NULL);
CString szPath;
GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
FORMATETC mfe = {CDSDataObject::m_cfMultiSelectProppage, NULL, DVASPECT_CONTENT,
-1, TYMED_HGLOBAL};
STGMEDIUM msm = {TYMED_HGLOBAL, NULL, NULL};
msm.hGlobal = (HGLOBAL)(LPCWSTR)szPath;
pDataObject->SetData(&mfe, &msm, FALSE);
//
// See if a sheet is already up for this object.
//
if (IsSheetAlreadyUp(pDataObject))
{
return S_OK;
}
//
// Initialize and create the pages. Create an instance of the
// CDsPropertyPages object for each sheet because each sheet runs on its
// own thread.
//
IShellExtInit * pShlInit;
hr = CoCreateInstance(CLSID_DsPropertyPages, NULL, CLSCTX_INPROC_SERVER,
IID_IShellExtInit, (void **)&pShlInit);
if (FAILED(hr))
{
TRACE(TEXT("CoCreateInstance on CLSID_DsPropertyPages failed, hr: 0x%x\n"), hr);
return hr;
}
//
// Initialize the sheet with the data object
//
hr = pShlInit->Initialize(NULL, pDataObject, 0);
if (FAILED(hr))
{
TRACE(TEXT("pShlInit->Initialize failed, hr: 0x%x\n"), hr);
pShlInit->Release();
return hr;
}
IShellPropSheetExt * pSPSE;
hr = pShlInit->QueryInterface(IID_IShellPropSheetExt, (void **)&pSPSE);
pShlInit->Release();
if (FAILED(hr))
{
TRACE(TEXT("pShlInit->QI for IID_IShellPropSheetExt failed, hr: 0x%x\n"), hr);
return hr;
}
//
// Add pages to the sheet
//
hr = pSPSE->AddPages(AddPageProc, (LPARAM)pCall);
if (FAILED(hr))
{
TRACE(TEXT("pSPSE->AddPages failed, hr: 0x%x\n"), hr);
pSPSE->Release();
return hr;
}
pSPSE->Release();
}
// REVIEW_MARCOC_PORT: need to clean up and leave the locking/unlocking
// working for non DS property pages
//_SheetLockCookie(pUINode);
return hr;
}
//+----------------------------------------------------------------------------
//
// Member: CDSComponentData::IExtendPropertySheet::QueryPagesFor
//
// Synopsis: Called before a context menu is posted. If we support a
// property sheet for this object, then return S_OK.
//
//-----------------------------------------------------------------------------
STDMETHODIMP CDSComponentData::QueryPagesFor(LPDATAOBJECT pDataObject)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
TRACE(TEXT("CDSComponentData::QueryPagesFor().\n"));
BOOL bHasPages = FALSE;
//
// Look at the data object and see if it an item in the scope pane.
//
CInternalFormatCracker dobjCracker;
HRESULT hr = dobjCracker.Extract(pDataObject);
if (FAILED(hr) || !dobjCracker.HasData())
{
//
// not internal format, not ours
//
return S_FALSE;
}
//
// this is the MMC snapin wizard, we do not have one
//
if (dobjCracker.GetType() == CCT_SNAPIN_MANAGER)
{
return S_FALSE;
}
if (dobjCracker.GetCookieCount() > 1) // multiple selection
{
bHasPages = TRUE;
}
else // single selection
{
CUINode* pUINode = dobjCracker.GetCookie();
if (pUINode == NULL)
{
return S_FALSE;
}
bHasPages = pUINode->HasPropertyPages(pDataObject);
}
return (bHasPages) ? S_OK : S_FALSE;
}
//+----------------------------------------------------------------------------
//
// Member: CDSComponentData::IComponentData::CompareObjects
//
// Synopsis: If the data objects belong to the same DS object, then return
// S_OK.
//
//-----------------------------------------------------------------------------
class CCompareCookieByDN
{
public:
CCompareCookieByDN(LPCWSTR lpszDN) { m_lpszDN = lpszDN;}
bool operator()(CDSUINode* pUINode)
{
CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
if (pCookie == NULL)
{
return FALSE;
}
return (_wcsicmp(m_lpszDN, pCookie->GetPath()) == 0);
}
private:
LPCWSTR m_lpszDN;
};
STDMETHODIMP CDSComponentData::CompareObjects(LPDATAOBJECT pDataObject1,
LPDATAOBJECT pDataObject2)
{
TRACE(TEXT("CDSComponentData::CompareObjects().\n"));
CInternalFormatCracker dobjCracker1;
CInternalFormatCracker dobjCracker2;
if (FAILED(dobjCracker1.Extract(pDataObject1)) ||
FAILED(dobjCracker2.Extract(pDataObject2)))
{
return S_FALSE; // could not get internal format
}
CUINode* pUINode1 = dobjCracker1.GetCookie();
CUINode* pUINode2 = dobjCracker2.GetCookie();
//
// must have valid nodes
//
if ( (pUINode1 == NULL) || (pUINode2 == NULL) )
{
return S_FALSE;
}
if (dobjCracker1.GetCookieCount() == 1 &&
dobjCracker2.GetCookieCount() == 1 &&
pUINode1 == pUINode2)
{
//
// same pointer, they are the same (either both from real nodes
// or both from secondary pages)
//
return S_OK;
}
//
// if they are not the same, we compare them by DN, because we
// support only property pages on DS objects
//
CObjectNamesFormatCracker objectNamesFormatCracker1;
CObjectNamesFormatCracker objectNamesFormatCracker2;
if ( (FAILED(objectNamesFormatCracker1.Extract(pDataObject1))) ||
(FAILED(objectNamesFormatCracker2.Extract(pDataObject2))) )
{
// one or both not a DS object: we assume they are different
return S_FALSE;
}
if ( (objectNamesFormatCracker1.GetCount() != 1) ||
(objectNamesFormatCracker2.GetCount() != 1) )
{
//
// We are allowing as many multiple selection pages up as the user wants
//
return S_FALSE;
}
TRACE(L"CDSComponentData::CompareObjects(%s, %s)\n", objectNamesFormatCracker1.GetName(0),
objectNamesFormatCracker2.GetName(0));
return (_wcsicmp(objectNamesFormatCracker1.GetName(0),
objectNamesFormatCracker2.GetName(0)) == 0) ? S_OK : S_FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu implementation
//
STDMETHODIMP CDSComponentData::AddMenuItems(LPDATAOBJECT pDataObject,
LPCONTEXTMENUCALLBACK pContextMenuCallback,
long *pInsertionAllowed)
{
HRESULT hr = S_OK;
TRACE(_T("CDSComponentData::AddMenuItems()\n"));
AFX_MANAGE_STATE(AfxGetStaticModuleState());
DATA_OBJECT_TYPES dotType;
CUINode* pUINode = NULL;
CUIFolderInfo* pFolderInfo = NULL;
CInternalFormatCracker dobjCracker;
hr = dobjCracker.Extract(pDataObject);
if (FAILED(hr))
{
ASSERT (FALSE); // Invalid Data Object
return E_UNEXPECTED;
}
dotType = dobjCracker.GetType();
pUINode = dobjCracker.GetCookie();
if (pUINode==NULL || dotType==0)
{
ASSERT(FALSE); // Invalid args
return E_UNEXPECTED;
}
//
// Retrieve context menu verb handler form node
//
CContextMenuVerbs* pMenuVerbs = pUINode->GetContextMenuVerbsObject(this);
if (pMenuVerbs == NULL)
{
ASSERT(FALSE);
return E_UNEXPECTED;
}
if (pUINode->IsContainer())
{
pFolderInfo = pUINode->GetFolderInfo();
ASSERT(pFolderInfo != NULL);
pFolderInfo->UpdateSerialNumber(this);
}
//
// Use the IContextMenuCallback2 interface so that we can use
// language independent IDs on the menu items.
//
CComPtr<IContextMenuCallback2> spMenuCallback2;
hr = pContextMenuCallback->QueryInterface(IID_IContextMenuCallback2, (PVOID*)&spMenuCallback2);
if (FAILED(hr))
{
ASSERT(FALSE && L"Failed to QI for the IContextMenuCallback2 interface.");
return E_UNEXPECTED;
}
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW)
{
//
// Load New Menu
//
hr = pMenuVerbs->LoadNewMenu(spMenuCallback2,
m_pShlInit,
pDataObject,
pUINode,
pInsertionAllowed);
ASSERT(SUCCEEDED(hr));
}
if ( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP )
{
//
// Load Top Menu
//
hr = pMenuVerbs->LoadTopMenu(spMenuCallback2, pUINode);
ASSERT(SUCCEEDED(hr));
}
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK)
{
//
// Load Task Menu
//
hr = pMenuVerbs->LoadTaskMenu(spMenuCallback2, pUINode);
ASSERT(SUCCEEDED(hr));
}
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
{
//
// Load View Menu
//
hr = pMenuVerbs->LoadViewMenu(spMenuCallback2, pUINode);
ASSERT(SUCCEEDED(hr));
}
return hr;
}
STDMETHODIMP CDSComponentData::Command(long nCommandID, LPDATAOBJECT pDataObject)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (nCommandID >= IDM_NEW_OBJECT_BASE)
{
// creation of a new DS object
return _CommandNewDSObject(nCommandID, pDataObject);
}
if ((nCommandID >= MENU_MERGE_BASE) && (nCommandID <= MENU_MERGE_LIMIT))
{
// range of menu ID's coming from shell extensions
return _CommandShellExtension(nCommandID, pDataObject);
}
HRESULT hr = S_OK;
CInternalFormatCracker dobjCracker;
hr = dobjCracker.Extract(pDataObject);
if (FAILED(hr))
{
ASSERT (FALSE); // Invalid Data Object
return hr;
}
DATA_OBJECT_TYPES dotType = dobjCracker.GetType();
CUINode* pUINode = dobjCracker.GetCookie();
if (pUINode == NULL || dotType == 0)
{
ASSERT(FALSE); // Invalid args
return E_FAIL;
}
if (IS_CLASS(*pUINode, CDSUINode))
{
CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
// menu ID's from standard DSA hard coded values
switch (nCommandID)
{
case IDM_DS_OBJECT_FIND:
{
LPCWSTR lpszPath = NULL;
if (pCookie == NULL)
{
lpszPath = m_RootNode.GetPath();
}
else
{
lpszPath = pCookie->GetPath();
}
m_ActiveDS->DSFind(m_hwnd, lpszPath);
}
break;
case IDM_GEN_TASK_MOVE:
{
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
ASSERT(pDSUINode != NULL);
_MoveObject(pDSUINode);
m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
}
break;
case IDM_VIEW_COMPUTER_HACK:
if (CanRefreshAll())
{
Lock();
m_pQueryFilter->ToggleExpandComputers();
Unlock();
BOOL fDoRefresh = m_pClassCache->ToggleExpandSpecialClasses(m_pQueryFilter->ExpandComputers());
m_bDirty = TRUE;
if (fDoRefresh)
{
RefreshAll();
}
}
break;
case IDM_GEN_TASK_SELECT_DOMAIN:
case IDM_GEN_TASK_SELECT_FOREST:
if (CanRefreshAll())
{
GetDomain();
}
break;
case IDM_GEN_TASK_SELECT_DC:
if (CanRefreshAll())
{
GetDC();
}
break;
#ifdef FIXUPDC
case IDM_GEN_TASK_FIXUP_DC:
#endif // FIXUPDC
case IDM_GEN_TASK_RUN_KCC:
{
ASSERT(pCookie != NULL);
//
// Pass the LDAP path of the parent cookie to _FixupDC or _RunKCC.
// The current cookie is a nTDSDSA object,
// and the parent cookie must be a server object
//
CUINode* pParentUINode = pUINode->GetParent();
ASSERT(pParentUINode != NULL);
CDSCookie *pParentCookie = GetDSCookieFromUINode(pParentUINode);
ASSERT(pParentCookie != NULL);
CString strServerPath = pParentCookie->GetPath();
CString strPath = GetBasePathsInfo()->GetProviderAndServerName();
strPath += strServerPath;
#ifdef FIXUPDC
switch (nCommandID)
{
case IDM_GEN_TASK_FIXUP_DC:
_FixupDC(strPath);
break;
case IDM_GEN_TASK_RUN_KCC:
#endif // FIXUPDC
_RunKCC(strPath);
#ifdef FIXUPDC
break;
default:
ASSERT(FALSE);
break;
}
#endif // FIXUPDC
}
break;
case IDM_GEN_TASK_EDIT_FSMO:
{
EditFSMO();
}
break;
case IDM_GEN_TASK_RAISE_VERSION:
RaiseVersion();
break;
case IDM_VIEW_ADVANCED:
{
if (CanRefreshAll())
{
ASSERT( SNAPINTYPE_SITE != QuerySnapinType() );
m_pQueryFilter->ToggleAdvancedView();
m_bDirty = TRUE;
RefreshAll();
}
}
break;
case IDM_VIEW_SERVICES_NODE:
{
if (CanRefreshAll())
{
ASSERT( SNAPINTYPE_SITE == QuerySnapinType() );
m_pQueryFilter->ToggleViewServicesNode();
m_bDirty = TRUE;
if (m_RootNode.GetFolderInfo()->IsExpanded())
{
Refresh(&m_RootNode, FALSE /*bFlushCache*/ );
}
}
}
break;
case IDM_VIEW_FILTER_OPTIONS:
{
if (CanRefreshAll())
{
ASSERT(m_bRunAsPrimarySnapin);
if (m_pQueryFilter->EditFilteringOptions())
{
m_bDirty = TRUE;
RefreshAll();
}
}
}
break;
} // switch
}
else // Other node types
{
pUINode->OnCommand(nCommandID, this);
}
return S_OK;
}
HRESULT CDSComponentData::_CommandNewDSObject(long nCommandID,
LPDATAOBJECT pDataObject)
{
ASSERT(nCommandID >= IDM_NEW_OBJECT_BASE);
UINT objIndex = nCommandID - IDM_NEW_OBJECT_BASE;
if (pDataObject == NULL)
return E_INVALIDARG;
CInternalFormatCracker internalFormat;
HRESULT hr = internalFormat.Extract(pDataObject);
if (FAILED(hr))
{
return hr;
}
if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
{
return E_INVALIDARG;
}
CUINode* pContainerUINode = internalFormat.GetCookie();
ASSERT(pContainerUINode != NULL);
// can do this for DS objects only
CDSUINode* pContainerDSUINode = dynamic_cast<CDSUINode*>(pContainerUINode);
if (pContainerDSUINode == NULL)
{
ASSERT(FALSE); // should never happen
return E_INVALIDARG;
}
CDSUINode* pNewDSUINode = NULL;
// pNewCookie is filled in if it is a leaf, then we call UpdateAllViews
hr = _CreateDSObject(pContainerDSUINode, pContainerDSUINode->GetCookie()->GetChildListEntry(objIndex), NULL, &pNewDSUINode);
if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewDSUINode != NULL))
{
m_pFrame->UpdateAllViews(pDataObject, (LPARAM)pNewDSUINode, DS_CREATE_OCCURRED);
m_pFrame->UpdateAllViews(pDataObject, (LPARAM)pContainerDSUINode, DS_UNSELECT_OBJECT);
}
m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
return S_OK;
}
HRESULT CDSComponentData::_CommandShellExtension(long nCommandID,
LPDATAOBJECT pDataObject)
{
CComPtr<IContextMenu> spICM;
HRESULT hr = m_pShlInit->QueryInterface(IID_IContextMenu, (void **)&spICM);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
// just call the shell extension
HWND hwnd;
CMINVOKECOMMANDINFO cmiCommand;
hr = m_pFrame->GetMainWindow (&hwnd);
ASSERT (hr == S_OK);
cmiCommand.hwnd = hwnd;
cmiCommand.cbSize = sizeof (CMINVOKECOMMANDINFO);
cmiCommand.fMask = SEE_MASK_ASYNCOK;
cmiCommand.lpVerb = MAKEINTRESOURCEA(nCommandID - MENU_MERGE_BASE);
spICM->InvokeCommand(&cmiCommand);
// get the internal clibard format to see if it was one of our objects
// from the DS context emnu extension
CInternalFormatCracker internalFormat;
hr = internalFormat.Extract(pDataObject);
if (FAILED(hr))
{
return hr;
}
if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
{
return E_INVALIDARG;
}
CUINode* pUINode = internalFormat.GetCookie();
ASSERT(pUINode != NULL);
if (pUINode->GetExtOp() & OPCODE_MOVE)
{
// REVIEW_MARCOC_PORT: need to generalize this for all folder types
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
ASSERT(pDSUINode != NULL);
if (pDSUINode != NULL)
{
CUINode* pNewParentNode = MoveObjectInUI(pDSUINode);
if (pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
{
Refresh(pNewParentNode);
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CDSComponentData::ISnapinHelp2 members
STDMETHODIMP
CDSComponentData::GetHelpTopic(LPOLESTR* lpCompiledHelpFile)
{
if (lpCompiledHelpFile == NULL)
return E_INVALIDARG;
if (m_lpszSnapinHelpFile == NULL)
{
*lpCompiledHelpFile = NULL;
return E_NOTIMPL;
}
CString szHelpFilePath;
LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH);
UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH);
if (nLen == 0)
return E_FAIL;
szHelpFilePath.ReleaseBuffer();
szHelpFilePath += L"\\help\\";
szHelpFilePath += m_lpszSnapinHelpFile;
UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR);
*lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
if (*lpCompiledHelpFile != NULL)
{
memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
}
return S_OK;
}
STDMETHODIMP
CDSComponentData::GetLinkedTopics(LPOLESTR* lpCompiledHelpFile)
{
if (lpCompiledHelpFile == NULL)
return E_INVALIDARG;
CString szHelpFilePath;
LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH);
UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH);
if (nLen == 0)
return E_FAIL;
szHelpFilePath.ReleaseBuffer();
szHelpFilePath += L"\\help\\";
szHelpFilePath += DSADMIN_LINKED_HELP_FILE;
UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR);
*lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
if (*lpCompiledHelpFile != NULL)
{
memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
}
return S_OK;
}
#ifdef _MMC_ISNAPIN_PROPERTY
/////////////////////////////////////////////////////////////////////////////
// CDSComponentData::ISnapinProperties members
// struct defining each entry
struct CSnapinPropertyEntry
{
LPCWSTR lpszName;
DWORD dwFlags;
};
// actual table
static const CSnapinPropertyEntry g_snapinPropertyArray[] =
{
{ g_szServer, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
{ g_szDomain, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
{ g_szRDN, MMC_PROP_CHANGEAFFECTSUI|MMC_PROP_MODIFIABLE|MMC_PROP_PERSIST},
{ NULL, 0x0} // end of table marker
};
STDMETHODIMP CDSComponentData::Initialize(
Properties* pProperties) /* I:my snap-in's properties */
{
TRACE(L"CDSComponentData::ISnapinProperties::Initialize()\n");
if (pProperties == NULL)
{
return E_INVALIDARG;
}
ASSERT(m_pProperties == NULL); // assume called only once
// save the interface pointer,
// it will be released during IComponentData::Destroy()
m_pProperties = pProperties;
m_pProperties->AddRef();
return S_OK;
}
STDMETHODIMP CDSComponentData::QueryPropertyNames(
ISnapinPropertiesCallback* pCallback) /* I:interface to add prop names*/
{
TRACE(L"CDSComponentData::QueryPropertyNames()\n");
HRESULT hr = S_OK;
// just loop through the table and add the entries
for (int k= 0; g_snapinPropertyArray[k].lpszName != NULL; k++)
{
hr = pCallback->AddPropertyName(g_snapinPropertyArray[k].lpszName,
NULL,
g_snapinPropertyArray[k].dwFlags);
if (FAILED(hr))
{
break;
}
}
return hr;
}
/*+-------------------------------------------------------------------------*
* CDSComponentData::PropertiesChanged
*
* This method is called when the snap-in's property set has changed.
*
* Returns:
* S_OK change was successful
* S_FALSE change was ignored
* E_INVALIDARG a changed property was invalid (e.g. a malformed
* computer name)
* E_FAIL a changed property was valid, but couldn't be used
* (e.g. a valid name for a computer that couldn't be
* located)
*--------------------------------------------------------------------------*/
STDMETHODIMP CDSComponentData::PropertiesChanged(
long cChangedProps, /* I:changed property count */
MMC_SNAPIN_PROPERTY* pChangedProps) /* I:changed properties */
{
TRACE(L"CDSComponentData::PropertiesChanged()\n");
// for the time being we do not allow any property change,
// we accept only initialization, so make a quick change and bail out
// if things are not such
for (long k=0; k< cChangedProps; k++)
{
if (pChangedProps[k].eAction != MMC_PROPACT_INITIALIZING)
{
return S_FALSE; // change ignored
}
if (pChangedProps[k].varValue.vt != VT_BSTR)
{
// something is wrong, refuse
return E_INVALIDARG;
}
}
// delegate to the targeting info object
HRESULT hr = m_targetingInfo.InitFromSnapinProperties(cChangedProps, pChangedProps);
// need to add here the properties for advanced view and alike
return hr;
}
#endif //_MMC_ISNAPIN_PROPERTY
/////////////////////////////////////////////////////////////////////////////
// internal helpers
HRESULT CDSComponentData::_InitRootFromBasePathsInfo(MyBasePathsInfo* pBasePathsInfo)
{
// we assume the MyBasePathsInfo we get is valid,
// we just swap info around and rebuild the related
// data structures
GetBasePathsInfo()->InitFromInfo(pBasePathsInfo);
m_InitSuccess = TRUE;
TRACE(_T("in _InitRootFromBasePathsInfo, set m_InitSuccess to true\n"));
return _InitRootFromValidBasePathsInfo();
}
HRESULT CDSComponentData::_InitRootFromCurrentTargetInfo()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CWaitCursor wait;
HRESULT hr = S_OK;
//
// This function may be called twice if we are loading from a file,
// so don't try to initialize a second time
//
if (m_InitAttempted)
{
return S_OK;
}
BOOL bLocalLogin;
bLocalLogin = IsLocalLogin();
//if user logged in locally and noting given on
//command line
LPCWSTR lpszServerOrDomain = m_targetingInfo.GetTargetString();
BOOL bNoTarget = ( (lpszServerOrDomain == NULL) ||
(lpszServerOrDomain[0] == NULL) );
if( bNoTarget && bLocalLogin && (SNAPINTYPE_SITE != QuerySnapinType()))
{
TRACE(_T("LoggedIn as Local User and No Command Line arguments\n"));
CString szMsg;
szMsg.LoadString(IDS_LOCAL_LOGIN_ERROR);
CComPtr<IDisplayHelp> spIDisplayHelp;
hr = m_pFrame->QueryInterface (IID_IDisplayHelp,
(void **)&spIDisplayHelp);
CMoreInfoMessageBox dlg(m_hwnd, spIDisplayHelp , FALSE);
dlg.SetMessage(szMsg);
dlg.SetURL(DSADMIN_MOREINFO_LOCAL_LOGIN_ERROR);
dlg.DoModal();
m_InitSuccess = FALSE;
TRACE(_T("in _InitRootFromCurrentTargetInfo, set m_InitSuccess to false\n"));
}
else
{
// initialize base paths
hr = GetBasePathsInfo()->InitFromName(lpszServerOrDomain);
//
// JonN 5/4/00
// 55400: SITEREPL: Should default to local DC regardless of credentials
// If the local machine is in the target forest, we target the domain
// containing the local machine.
//
do // false loop
{
// We cannot follow this procedudure if we couldn't bind initially
if (FAILED(hr)) break;
// Skip this if the user specified a target
if (!bNoTarget) break;
// only do this for SITEREPL
if (SNAPINTYPE_SITE != QuerySnapinType()) break;
// Check whether the user is logged onto the local domain.
CString strComputer; // empty string
CString strLocalDomain;
HRESULT hr2 = GetDnsNameOfDomainOrForest(
strComputer, strLocalDomain, FALSE, TRUE );
if (FAILED(hr2) || strLocalDomain.IsEmpty()) break;
CString strTargetDomain = GetBasePathsInfo()->GetDomainName();
if (strTargetDomain.IsEmpty()) break;
if (!strLocalDomain.CompareNoCase(strTargetDomain)) break;
// The user is not logged onto the local domain.
// We need to determine whether the user is logged onto
// the same forest as the local forest.
CString strLocalForest;
hr2 = GetDnsNameOfDomainOrForest(
strComputer, strLocalForest, FALSE, FALSE );
if (FAILED(hr2) || strLocalForest.IsEmpty()) break;
CString strTargetForest;
strComputer = GetBasePathsInfo()->GetServerName();
hr2 = GetDnsNameOfDomainOrForest(
strComputer, strTargetForest, FALSE, FALSE );
if (FAILED(hr2) || strTargetForest.IsEmpty()) break;
if (strLocalForest.CompareNoCase(strTargetForest)) break;
// The user is logged on to a different domain than the local
// domain, but one in the same forest. There are probably closer DCs
// than the one just located, so use them instead.
// start using hr again here rather than hr2
TRACE(_T("_InitRootFromCurrentTargetInfo() rebinding\n"));
hr = GetBasePathsInfo()->InitFromName(strLocalDomain);
if (FAILED(hr))
{
// try to fall back to initial focus
TRACE(_T("_InitRootFromCurrentTargetInfo() reverting\n"));
hr = GetBasePathsInfo()->InitFromName(lpszServerOrDomain);
}
} while (false); // false loop
// NOTICE: if we fail, we out out the error message, and
// we keep a flag to avoid query expansions, but
// we continue, because we have to keep consistency in all
// the data structures (class cache, filter, etc.)
if (FAILED(hr))
{
TRACE(_T("_InitRootFromCurrentTargetInfo() failed\n"));
ReportErrorEx (m_hwnd, IDS_CANT_GET_ROOTDSE,hr,
MB_OK | MB_ICONERROR, NULL, 0);
m_InitSuccess = FALSE;
TRACE(_T("in _InitRootFromCurrentTargetInfo(), set m_InitSuccess to false\n"));
}
else
{
m_InitSuccess = TRUE;
TRACE(_T("in _InitRootFromCurrentTargetInfo(), set m_InitSuccess to true\n"));
}
}
_InitRootFromValidBasePathsInfo();
m_InitAttempted = TRUE;
return hr;
}
HRESULT CDSComponentData::_InitRootFromValidBasePathsInfo()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
// now set the root node strings. This will be reset below
// with the DNS name of the domain if everything succeeds
CString str;
str.LoadString( ResourceIDForSnapinType[ QuerySnapinType() ] );
m_RootNode.SetName(str);
// rebuild the display spec options struct for Data Objects
hr = BuildDsDisplaySpecOptionsStruct();
if (FAILED(hr))
return hr;
// reset the notification handler
GetNotifyHandlerManager()->Init();
// reset the query filter (already initialized in IComponentData::Initialize())
hr = m_pQueryFilter->Bind();
if (FAILED(hr))
return hr;
CString szServerName = GetBasePathsInfo()->GetServerName();
if (!szServerName.IsEmpty())
{
str += L" [";
str += szServerName;
str += L"]";
}
m_RootNode.SetName(str);
if (QuerySnapinType() == SNAPINTYPE_SITE)
{
//fix the default root path
str = GetBasePathsInfo()->GetConfigNamingContext();
}
else
{
LPCWSTR lpszRootRDN = m_targetingInfo.GetRootRDN();
if ( (lpszRootRDN != NULL) && (lpszRootRDN[0] != NULL) )
{
// add RDN below default naming context
// REVIEW_MARCOC_PORT: need to make sure the RDN is valid
str = m_targetingInfo.GetRootRDN();
str += L",";
str += GetBasePathsInfo()->GetDefaultRootNamingContext();
}
else
{
// just use the default naming context
str = GetBasePathsInfo()->GetDefaultRootNamingContext();
}
}
m_RootNode.SetPath(str);
// update UI if we already have inserted the root (retargeting case)
HSCOPEITEM hScopeItemID = m_RootNode.GetFolderInfo()->GetScopeItem();
if (hScopeItemID != NULL)
{
SCOPEDATAITEM Item;
CString csRoot;
Item.ID = m_RootNode.GetFolderInfo()->GetScopeItem();
Item.mask = SDI_STR;
csRoot = m_RootNode.GetName();
Item.displayname = (LPWSTR)(LPCWSTR)csRoot;
m_pScope->SetItem(&Item);
m_RootNode.SetExtOp(m_InitSuccess ? 0 : OPCODE_ENUM_FAILED);
ChangeScopeItemIcon(&m_RootNode);
}
return hr;
}
void CDSComponentData::GetDomain()
{
CChooseDomainDlg DomainDlg;
// load current bind info
DomainDlg.m_csTargetDomain = GetBasePathsInfo()->GetDomainName();
DomainDlg.m_bSiteRepl = (SNAPINTYPE_SITE == QuerySnapinType());
DomainDlg.m_bSaveCurrent = m_targetingInfo.GetSaveCurrent();
//
// invoke the dialog
//
if (DomainDlg.DoModal() == IDOK)
{
CWaitCursor cwait;
// attempt to bind
MyBasePathsInfo tempBasePathsInfo;
HRESULT hr = tempBasePathsInfo.InitFromName(DomainDlg.m_csTargetDomain);
if (SUCCEEDED(hr))
{
hr = _InitRootFromBasePathsInfo(&tempBasePathsInfo);
if (SUCCEEDED(hr))
{
m_targetingInfo.SetSaveCurrent(DomainDlg.m_bSaveCurrent);
m_bDirty = TRUE;
ClearClassCacheAndRefreshRoot();
}
}
if (FAILED(hr))
{
ReportErrorEx(
m_hwnd,
(DomainDlg.m_bSiteRepl ? IDS_RETARGET_FOREST_FAILED : IDS_RETARGET_DOMAIN_FAILED),
hr, MB_OK | MB_ICONERROR, NULL, 0);
}
}
return;
}
void CDSComponentData::GetDC()
{
CChooseDCDlg DCdlg(CWnd::FromHandle(m_hwnd));
// load current bind info
DCdlg.m_bSiteRepl = (SNAPINTYPE_SITE == QuerySnapinType());
DCdlg.m_csTargetDomain = GetBasePathsInfo()->GetDomainName();
DCdlg.m_csTargetDomainController = GetBasePathsInfo()->GetServerName();
//
// invoke the dialog
//
if (DCdlg.DoModal() == IDOK)
{
CWaitCursor cwait;
CString csNewTarget;
csNewTarget = DCdlg.m_csTargetDomainController;
if (csNewTarget.IsEmpty())
csNewTarget = DCdlg.m_csTargetDomain;
// attempt to bind
MyBasePathsInfo tempBasePathsInfo;
HRESULT hr = tempBasePathsInfo.InitFromName(csNewTarget);
if (SUCCEEDED(hr))
{
hr = _InitRootFromBasePathsInfo(&tempBasePathsInfo);
if (SUCCEEDED(hr))
ClearClassCacheAndRefreshRoot();
}
if (FAILED(hr))
{
ReportErrorEx(
m_hwnd,
IDS_RETARGET_DC_FAILED,
hr, MB_OK | MB_ICONERROR, NULL, 0);
}
}
return;
}
void CDSComponentData::EditFSMO()
{
CComPtr<IDisplayHelp> spIDisplayHelp;
HRESULT hr = m_pFrame->QueryInterface (IID_IDisplayHelp,
(void **)&spIDisplayHelp);
ASSERT(spIDisplayHelp != NULL);
if (SUCCEEDED(hr))
{
HWND hWnd;
m_pFrame->GetMainWindow(&hWnd);
LPCWSTR lpszTODO = L"";
CFsmoPropertySheet sheet(GetBasePathsInfo(), hWnd, spIDisplayHelp, lpszTODO);
sheet.DoModal();
}
}
void CDSComponentData::RaiseVersion(void)
{
HWND hWnd;
m_pFrame->GetMainWindow(&hWnd);
CString strPath;
GetBasePathsInfo()->GetDefaultRootPath(strPath);
PCWSTR pwzDnsName = GetBasePathsInfo()->GetDomainName();
ASSERT(pwzDnsName);
DSPROP_DomainVersionDlg(strPath, pwzDnsName, hWnd);
}
HRESULT CDSComponentData::_OnPreload(HSCOPEITEM hRoot)
{
HRESULT hr = S_OK;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString str;
str.LoadString( ResourceIDForSnapinType[ QuerySnapinType() ] );
m_RootNode.SetName(str);
if (GetBasePathsInfo()->IsInitialized())
{
CString szServerName = GetBasePathsInfo()->GetServerName();
if (!szServerName.IsEmpty())
{
str += L" [";
str += szServerName;
str += L"]";
}
m_RootNode.SetName(str);
}
SCOPEDATAITEM Item;
Item.ID = hRoot;
Item.mask = SDI_STR;
Item.displayname = (LPWSTR)(LPCWSTR)str;
hr = m_pScope->SetItem(&Item);
return hr;
}
HRESULT CDSComponentData::_OnExpand(CUINode* pNode, HSCOPEITEM hParent, MMC_NOTIFY_TYPE event)
{
HRESULT hr = S_OK;
if ((pNode == NULL) || (!pNode->IsContainer()) )
{
ASSERT(FALSE); // Invalid Arguments
return E_INVALIDARG;
}
BEGIN_PROFILING_BLOCK("CDSComponentData::_OnExpand");
CWaitCursor cwait;
if (pNode->GetFolderInfo()->IsExpanded())
{
END_PROFILING_BLOCK;
//
// Short circuit the expansion because the node is already expanded
//
return S_OK;
}
pNode->GetFolderInfo()->SetExpanded();
if (pNode == &m_RootNode)
{
// initialize the paths and targeting
_InitRootFromCurrentTargetInfo();
// add the root cookie to MMC
pNode->GetFolderInfo()->SetScopeItem(hParent);
SCOPEDATAITEM Item;
Item.ID = hParent;
Item.mask = SDI_STR;
Item.displayname = (LPWSTR)(LPCWSTR)(m_RootNode.GetName());
m_pScope->SetItem (&Item);
// also add the root for the saved queries, if present
if (m_pFavoritesNodesHolder != NULL)
{
// add the favorite queries subtree
_AddScopeItem(m_pFavoritesNodesHolder->GetFavoritesRoot(),
m_RootNode.GetFolderInfo()->GetScopeItem());
}
}
if (IS_CLASS(*pNode, CFavoritesNode))
{
// just add the favorites subfolders and query folders
CUINodeList* pNodeList = pNode->GetFolderInfo()->GetContainerList();
for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
{
CUINode* pCurrChildNode = pNodeList->GetNext(pos);
_AddScopeItem(pCurrChildNode,
pNode->GetFolderInfo()->GetScopeItem());
}
END_PROFILING_BLOCK;
// return because we do not need to spawn any background
// thread query
return S_OK;
}
if (!_PostQueryToBackgroundThread(pNode))
{
END_PROFILING_BLOCK;
// no background thread query generated, we are done
return S_OK;
}
// need to spawn a query request
pNode->SetExtOp(OPCODE_EXPAND_IN_PROGRESS);
TIMER(_T("posting request to bg threads\n"));
if (MMCN_EXPANDSYNC == event)
{
// if sync expand, have to wait for the query to complete
MSG tempMSG;
TRACE(L"MMCN_EXPANDSYNC, before while()\n");
while(m_queryNodeTable.IsPresent(pNode))
{
if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadStartNotificationMessage,
CHiddenWnd::s_ThreadDoneNotificationMessage,
PM_REMOVE))
{
DispatchMessage(&tempMSG);
}
} // while
TRACE(L"MMCN_EXPANDSYNC, after while()\n");
}
END_PROFILING_BLOCK;
return hr;
}
HRESULT CDSComponentData::_AddScopeItem(CUINode* pUINode, HSCOPEITEM hParent, BOOL bSetSelected)
{
if (pUINode==NULL)
{
ASSERT(FALSE); // Invalid Arguments
return E_INVALIDARG;
}
ASSERT(pUINode->IsContainer());
HRESULT hr=S_OK;
SCOPEDATAITEM tSDItem;
ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
tSDItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_STATE | SDI_PARAM |SDI_CHILDREN | SDI_PARENT;
tSDItem.relativeID = hParent;
if (IS_CLASS(*pUINode, CSavedQueryNode))
{
tSDItem.cChildren = 0;
}
else
{
tSDItem.cChildren=1;
}
tSDItem.nState = 0;
// insert item into tree control
tSDItem.lParam = reinterpret_cast<LPARAM>(pUINode);
tSDItem.displayname=(LPWSTR)-1;
tSDItem.nOpenImage = GetImage(pUINode, TRUE);
tSDItem.nImage = GetImage(pUINode, FALSE);
hr = m_pScope->InsertItem(&tSDItem);
if (SUCCEEDED(hr) && tSDItem.ID != NULL)
{
pUINode->GetFolderInfo()->SetScopeItem(tSDItem.ID);
if (bSetSelected)
{
m_pFrame->SelectScopeItem(tSDItem.ID);
}
}
return hr;
}
HRESULT CDSComponentData::ChangeScopeItemIcon(CUINode* pUINode)
{
ASSERT(pUINode->IsContainer());
SCOPEDATAITEM tSDItem;
ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
tSDItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
tSDItem.nOpenImage = GetImage(pUINode, TRUE);
tSDItem.nImage = GetImage(pUINode, FALSE);
tSDItem.ID = pUINode->GetFolderInfo()->GetScopeItem();
return m_pScope->SetItem(&tSDItem);
}
HRESULT CDSComponentData::_ChangeResultItemIcon(CUINode* pUINode)
{
ASSERT(!pUINode->IsContainer());
return m_pFrame->UpdateAllViews(NULL,(LPARAM)pUINode, DS_UPDATE_OCCURRED);
}
HRESULT CDSComponentData::ToggleDisabled(CDSUINode* pDSUINode, BOOL bDisable)
{
HRESULT hr = S_OK;
CDSCookie* pCookie = pDSUINode->GetCookie();
ASSERT(pCookie != NULL);
if (pCookie == NULL)
{
return E_INVALIDARG;
}
if (pCookie->IsDisabled() != bDisable)
{
// changed state
if (bDisable)
pCookie->SetDisabled();
else
pCookie->ReSetDisabled();
// now need to change icon
if (pDSUINode->IsContainer())
return ChangeScopeItemIcon(pDSUINode);
else
return _ChangeResultItemIcon(pDSUINode);
}
return hr;
}
HRESULT CDSComponentData::UpdateItem(CUINode* pNode)
{
if (pNode->IsContainer())
{
//
// this is a scope pane item
//
return _UpdateScopeItem(pNode);
}
else
{
//
// this is a result pane item
// tell the views to update
//
return m_pFrame->UpdateAllViews(NULL,(LPARAM)pNode, DS_UPDATE_OCCURRED);
}
}
HRESULT CDSComponentData::_UpdateScopeItem(CUINode* pNode)
{
ASSERT(pNode->IsContainer());
SCOPEDATAITEM tSDItem;
ZeroMemory(&tSDItem, sizeof(SCOPEDATAITEM));
tSDItem.mask = SDI_STR;
tSDItem.displayname = MMC_CALLBACK;
tSDItem.ID = pNode->GetFolderInfo()->GetScopeItem();
return m_pScope->SetItem(&tSDItem);
}
HRESULT CDSComponentData::AddClassIcon(IN LPCWSTR lpszClass, IN DWORD dwFlags, INOUT int* pnIndex)
{
Lock();
HRESULT hr = m_iconManager.AddClassIcon(lpszClass, GetBasePathsInfo(), dwFlags, pnIndex);
Unlock();
return hr;
}
HRESULT CDSComponentData::FillInIconStrip(IImageList* pImageList)
{
Lock();
HRESULT hr = m_iconManager.FillInIconStrip(pImageList);
Unlock();
return hr;
}
BOOL
CDSComponentData::IsNotHiddenClass (LPWSTR pwszClass, CDSCookie* pParentCookie)
{
BOOL bApproved = FALSE;
if (m_CreateInfo.IsEmpty())
{
return FALSE;
}
POSITION pos;
pos = m_CreateInfo.GetHeadPosition();
while (pos)
{
if (!m_CreateInfo.GetNext(pos).CompareNoCase(pwszClass))
{
bApproved = TRUE;
goto done;
}
else
{
if ( (!wcscmp (pwszClass, L"sitesContainer"))
|| (!wcscmp (pwszClass, L"site"))
|| (!wcscmp (pwszClass, L"siteLink"))
|| (!wcscmp (pwszClass, L"siteLinkBridge"))
|| (!wcscmp (pwszClass, L"licensingSiteSettings"))
|| (!wcscmp (pwszClass, L"nTDSSiteSettings"))
|| (!wcscmp (pwszClass, L"serversContainer"))
|| (!wcscmp (pwszClass, L"server"))
|| (!wcscmp (pwszClass, L"nTDSDSA"))
|| (!wcscmp (pwszClass, L"subnet"))
#ifdef FRS_CREATE
|| (!wcscmp (pwszClass, L"nTDSConnection"))
|| (!wcscmp (pwszClass, L"nTFRSSettings"))
|| (!wcscmp (pwszClass, L"nTFRSReplicaSet"))
|| (!wcscmp (pwszClass, L"nTFRSMember"))
|| (!wcscmp (pwszClass, L"nTFRSSubscriptions"))
|| (!wcscmp (pwszClass, L"nTFRSSubscriber"))
#endif // FRS_CREATE
)
{
bApproved = TRUE;
goto done;
}
#ifndef FRS_CREATE
else if ( !wcscmp(pwszClass, L"nTDSConnection"))
{
LPCWSTR pwszParentClass = (pParentCookie) ? pParentCookie->GetClass() : L"";
if ( NULL != pwszParentClass
&& wcscmp(pwszParentClass, L"nTFRSSettings")
&& wcscmp(pwszParentClass, L"nTFRSReplicaSet")
&& wcscmp(pwszParentClass, L"nTFRSMember")
)
{
bApproved = TRUE;
goto done;
}
}
#endif // !FRS_CREATE
}
}
done:
return bApproved;
}
HRESULT
CDSComponentData::FillInChildList(CDSCookie * pCookie)
{
HRESULT hr = S_OK;
LPWSTR pszClasses = L"allowedChildClassesEffective";
LONG uBound, lBound;
UINT index, index2 = 0;
UINT cChildCount = 0;
CString Path;
WCHAR **ppChildren = NULL;
VARIANT *pNames = NULL;
WCHAR *pNextFree;
CComVariant Var;
CComVariant VarProp;
CComVariant varHints;
CComPtr<IADsPropertyList> spDSObject;
GetBasePathsInfo()->ComposeADsIPath(Path, pCookie->GetPath());
hr = DSAdminOpenObject(Path,
IID_IADsPropertyList,
(void **)&spDSObject,
TRUE /*bServer*/);
if (FAILED(hr))
{
TRACE(_T("Bind to Container for IPropertyList failed: %lx.\n"), hr);
goto error;
}
else
{
CComPtr<IADs> spDSObject2;
hr = spDSObject->QueryInterface (IID_IADs, (void **)&spDSObject2);
if (FAILED(hr))
{
TRACE(_T("QI to Container for IADs failed: %lx.\n"), hr);
goto error;
}
ADsBuildVarArrayStr (&pszClasses, 1, &varHints);
spDSObject2->GetInfoEx(varHints, 0);
}
hr = spDSObject->GetPropertyItem (pszClasses,
ADSTYPE_CASE_IGNORE_STRING,
&VarProp);
if (!SUCCEEDED(hr))
{
TRACE(_T("GetPropertyTtem failed: %lx.\n"), hr);
goto error;
}
if (V_VT(&VarProp) == VT_EMPTY)
{
TRACE(_T("GetPropertyTtem return empty VARIANT: vtype is %lx.\n"), V_VT(&VarProp));
goto error;
}
{ // scope to allow goto's to compile
IDispatch * pDisp = NULL;
pDisp = V_DISPATCH(&VarProp);
CComPtr<IADsPropertyEntry> spPropEntry;
hr = pDisp->QueryInterface(IID_IADsPropertyEntry, (void **)&spPropEntry);
hr = spPropEntry->get_Values(&Var);
}
hr = SafeArrayGetUBound (V_ARRAY(&Var), 1, &uBound);
hr = SafeArrayGetLBound (V_ARRAY(&Var), 1, &lBound);
hr = SafeArrayAccessData(V_ARRAY(&Var),
(void **)&pNames);
if (FAILED(hr))
{
TRACE(_T("Accessing safearray data failed: %lx.\n"), hr);
goto error;
}
else
{
if (uBound >= 0)
{
cChildCount = (UINT) (uBound - lBound);
ppChildren = (WCHAR **) LocalAlloc (LPTR,
(cChildCount + 1) * STRING_LEN);
if (ppChildren != NULL)
{
pNextFree = (WCHAR*)(ppChildren + cChildCount + 1);
index2 = 0;
for (index = lBound; index <= (UINT)uBound; index++)
{
CComPtr<IADsPropertyValue> spEntry;
hr = (pNames[index].pdispVal)->QueryInterface (IID_IADsPropertyValue,
(void **)&spEntry);
if (SUCCEEDED(hr))
{
CComBSTR bsObject;
hr = spEntry->get_CaseIgnoreString (&bsObject);
TRACE(_T("----->allowed object number %d: %s\n"),
index, bsObject);
if (IsNotHiddenClass(bsObject, pCookie))
{
TRACE(_T("-----------approved.\n"));
ppChildren[index2] = pNextFree;
pNextFree += wcslen(bsObject)+ sizeof (WCHAR);
wcscpy (ppChildren[index2], bsObject);
index2 ++;
} // if
} // if
} // for
} // if
} // if uBound
#ifdef DBG
else
{
TRACE(_T("--- no classes returned, no creation allowed here.\n"));
}
#endif
VERIFY(SUCCEEDED(SafeArrayUnaccessData(V_ARRAY(&Var))));
}
error:
if (index2 != 0)
{
SortChildList (ppChildren, index2);
pCookie->SetChildList (ppChildren);
}
pCookie->SetChildCount (index2);
return hr;
}
// routine to sort the entries for the "Create New" menu
// simple-minded bubble sort; its a small list
BOOL CDSComponentData::SortChildList (LPWSTR *ppszChildList, UINT cChildCount)
{
LPWSTR Temp;
BOOL IsSorted = FALSE;
while (!IsSorted)
{
IsSorted = TRUE;
// TRACE(_T("At top of while. ready to go again.\n"));
for (UINT index = 0; index < cChildCount - 1; index++)
{
if (wcscmp (ppszChildList[index], ppszChildList[index + 1]) > 0)
{
Temp = ppszChildList[index];
ppszChildList[index] = ppszChildList[index + 1];
ppszChildList[index + 1] = Temp;
//TRACE(_T("Swapped %s and %ws. still not done.\n"),
// ppszChildList[index], ppszChildList[index + 1]);
IsSorted = FALSE;
}
}
}
return IsSorted;
}
/////////////////////////////////////////////////////////////////////
// CDSComponentData::_CreateDSObject()
//
// Create a new ADs object.
//
HRESULT CDSComponentData::_CreateDSObject(CDSUINode* pContainerDSUINode, // IN: container where to create object
LPCWSTR lpszObjectClass, // IN: class of the object to be created
IN CDSUINode* pCopyFromDSUINode, // IN: (optional) object to be copied
OUT CDSUINode** ppSUINodeNew) // OUT: OPTIONAL: Pointer to new node
{
CDSCookie* pNewCookie = NULL;
HRESULT hr = GetActiveDS()->CreateDSObject(pContainerDSUINode,
lpszObjectClass,
pCopyFromDSUINode,
&pNewCookie);
if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewCookie != NULL))
{
// make sure we update the icon cache
m_pFrame->UpdateAllViews(/*unused*/NULL /*pDataObj*/, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
// create a UI node to hold the cookie
*ppSUINodeNew = new CDSUINode(NULL);
(*ppSUINodeNew)->SetCookie(pNewCookie);
if (pNewCookie->IsContainerClass())
{
(*ppSUINodeNew)->MakeContainer();
}
// Add the new node to the link list
pContainerDSUINode->GetFolderInfo()->AddNode(*ppSUINodeNew);
if ((*ppSUINodeNew)->IsContainer())
{
//
// Add the scope item and select it
//
_AddScopeItem(*ppSUINodeNew, pContainerDSUINode->GetFolderInfo()->GetScopeItem(), TRUE);
*ppSUINodeNew = NULL;
}
}
return hr;
}
//
// return S_OK if can copy, S_FALSE if not, some hr error if failed
//
HRESULT CDSComponentData::_CanCopyDSObject(IDataObject* pCopyFromDsObject)
{
if (pCopyFromDsObject == NULL)
{
return E_INVALIDARG;
}
CInternalFormatCracker internalFormat;
HRESULT hr = internalFormat.Extract(pCopyFromDsObject);
if (FAILED(hr))
{
return hr;
}
if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
{
return E_INVALIDARG;
}
//
// Get the node data
//
CUINode* pUINode = internalFormat.GetCookie();
CDSCookie* pCopyFromDsCookie = NULL;
if (IS_CLASS(*pUINode, CDSUINode))
{
pCopyFromDsCookie = GetDSCookieFromUINode(pUINode);
}
if (pCopyFromDsCookie == NULL)
{
return E_INVALIDARG;
}
//
// get the parent node data
//
CUINode* pParentUINode = pUINode->GetParent();
CDSCookie* pContainerDsCookie = NULL;
if (IS_CLASS(*pParentUINode, CDSUINode))
{
pContainerDsCookie = GetDSCookieFromUINode(pParentUINode);
}
if (pContainerDsCookie == NULL)
{
return E_INVALIDARG;
}
//
// get the class to be created
//
LPCWSTR lpszObjectClass = pCopyFromDsCookie->GetClass();
//
// try to find the class in the possible child classes of the container
//
WCHAR ** ppChildren = pContainerDsCookie->GetChildList();
if (ppChildren == NULL)
{
FillInChildList(pContainerDsCookie);
ppChildren = pContainerDsCookie->GetChildList();
}
//
// loop trough the class list to find a match
//
int cChildCount = pContainerDsCookie->GetChildCount();
for (int index = 0; index < cChildCount; index++)
{
if (wcscmp(pContainerDsCookie->GetChildListEntry(index), lpszObjectClass) == 0)
{
return S_OK; // got one, can create
}
}
return S_FALSE; // not found, cannot create
}
HRESULT CDSComponentData::_CopyDSObject(IDataObject* pCopyFromDsObject) // IN object to be copied
{
if (pCopyFromDsObject == NULL)
return E_INVALIDARG;
CInternalFormatCracker internalFormat;
HRESULT hr = internalFormat.Extract(pCopyFromDsObject);
if (FAILED(hr))
{
return hr;
}
if (!internalFormat.HasData() || (internalFormat.GetCookieCount() != 1))
{
return E_INVALIDARG;
}
CUINode* pCopyFromUINode = internalFormat.GetCookie();
ASSERT(pCopyFromUINode != NULL);
// can do this for DS objects only
CDSUINode* pCopyFromDSUINode = dynamic_cast<CDSUINode*>(pCopyFromUINode);
if (pCopyFromDSUINode == NULL)
{
ASSERT(FALSE); // should never happen
return E_INVALIDARG;
}
// get the parent cookie
CDSUINode* pContainerDSUINode = dynamic_cast<CDSUINode*>(pCopyFromDSUINode->GetParent());
if(pContainerDSUINode == NULL)
{
ASSERT(FALSE); // should never happen
return E_INVALIDARG;
}
// get the class to be created
LPCWSTR lpszObjectClass = pCopyFromDSUINode->GetCookie()->GetClass();
// call the object creation code
CDSUINode* pNewDSUINode = NULL;
hr = _CreateDSObject(pContainerDSUINode, lpszObjectClass, pCopyFromDSUINode, &pNewDSUINode);
// update if result pane item
// (if it were a scope item, _CreateDSObject() would update it
if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewDSUINode != NULL))
{
m_pFrame->UpdateAllViews(pCopyFromDsObject, (LPARAM)pNewDSUINode, DS_CREATE_OCCURRED_RESULT_PANE);
m_pFrame->UpdateAllViews(NULL, (LPARAM)pCopyFromDSUINode, DS_UNSELECT_OBJECT);
}
return S_OK;
}
HRESULT
CDSComponentData::_DeleteFromBackendAndUI(IDataObject* pDataObject, CDSUINode* pDSUINode)
{
HRESULT hr = S_OK;
ASSERT(pDSUINode != NULL);
ASSERT(pDSUINode->IsContainer());
// guard against property sheet open on this cookie
if (_WarningOnSheetsUp(pDSUINode))
return S_OK;
CWaitCursor cwait;
// this call will handle the notifications to extensions
CDSCookie* pCookie = GetDSCookieFromUINode(pDSUINode);
hr = _DeleteFromBackEnd(pDataObject, pCookie);
// if deletion happened, delete the scope item from the UI
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
hr = RemoveContainerFromUI(pDSUINode);
delete pDSUINode;
}
return S_OK;
}
HRESULT CDSComponentData::RemoveContainerFromUI(CUINode* pUINode)
{
HRESULT hr = S_OK;
ASSERT(pUINode->IsContainer());
HSCOPEITEM ItemID, ParentItemID;
ItemID = pUINode->GetFolderInfo()->GetScopeItem();
CUINode* pParentNode = NULL;
hr = m_pScope->GetParentItem(ItemID, &ParentItemID,
(MMC_COOKIE *)&pParentNode);
m_pScope->DeleteItem(ItemID, TRUE);
if (SUCCEEDED(hr))
{
ASSERT(pParentNode->IsContainer());
// delete memory
pParentNode->GetFolderInfo()->RemoveNode(pUINode);
}
m_pFrame->UpdateAllViews(NULL, NULL, DS_UPDATE_OBJECT_COUNT);
//
// Remove the '+' sign in the UI if this was the last container child in this container
//
if (pParentNode != NULL &&
ParentItemID != 0 &&
pParentNode->GetFolderInfo()->GetContainerList()->GetCount() == 0)
{
SCOPEDATAITEM sdi;
memset(&sdi, 0, sizeof(SCOPEDATAITEM));
sdi.ID = ParentItemID;
sdi.mask |= SDI_CHILDREN;
sdi.cChildren = 0;
hr = m_pScope->SetItem(&sdi);
}
return hr;
}
///////////////////////////////////////////////////////////////////////////
// CSnapinSingleDeleteHandler
class CSnapinSingleDeleteHandler : public CSingleDeleteHandlerBase
{
public:
CSnapinSingleDeleteHandler(CDSComponentData* pComponentData, HWND hwnd,
CDSCookie* pCookie)
: CSingleDeleteHandlerBase(pComponentData, hwnd)
{
m_pCookie = pCookie;
GetComponentData()->GetBasePathsInfo()->ComposeADsIPath(
m_strItemPath, m_pCookie->GetPath());
}
protected:
CDSCookie* m_pCookie;
CString m_strItemPath;
virtual HRESULT BeginTransaction()
{
return GetTransaction()->Begin(m_pCookie, NULL, NULL, FALSE);
}
virtual HRESULT DeleteObject()
{
return GetComponentData()->GetActiveDS()->DeleteObject(m_pCookie ,FALSE);
}
virtual HRESULT DeleteSubtree()
{
return GetComponentData()->_DeleteSubtreeFromBackEnd(m_pCookie);
}
virtual void GetItemName(OUT CString& szName){ szName = m_pCookie->GetName(); }
virtual LPCWSTR GetItemClass(){ return m_pCookie->GetClass(); }
virtual LPCWSTR GetItemPath(){ return m_strItemPath; }
};
/*
NOTICE: the function will return S_OK on success, S_FALSE if aborted
by user, some FAILED(hr) otherwise
*/
HRESULT CDSComponentData::_DeleteFromBackEnd(IDataObject*, CDSCookie* pCookie)
{
ASSERT(pCookie != NULL);
CSnapinSingleDeleteHandler deleteHandler(this, m_hwnd, pCookie);
return deleteHandler.Delete();
}
HRESULT
CDSComponentData::_DeleteSubtreeFromBackEnd(CDSCookie* pCookie)
{
HRESULT hr = S_OK;
CComPtr<IADsDeleteOps> spObj;
CString szPath;
GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
hr = DSAdminOpenObject(szPath,
IID_IADsDeleteOps,
(void **)&spObj,
TRUE /*bServer*/);
if (SUCCEEDED(hr))
{
hr = spObj->DeleteObject(NULL); //flag is reserved by ADSI
}
return hr;
}
HRESULT CDSComponentData::_Rename(CUINode* pUINode, LPWSTR NewName)
{
//
// Verify parameters
//
if (pUINode == NULL || NewName == NULL)
{
ASSERT(FALSE);
return E_INVALIDARG;
}
CWaitCursor cwait;
HRESULT hr = S_OK;
CDSCookie* pCookie = NULL;
CString szPath;
//
// guard against property sheet open on this cookie
//
if (_WarningOnSheetsUp(pUINode))
{
return E_FAIL;
}
if (pUINode->IsSheetLocked())
{
ReportErrorEx (m_hwnd,IDS_SHEETS_UP_RENAME,hr,
MB_OK | MB_ICONINFORMATION, NULL, 0);
return hr;
}
if (IS_CLASS(*pUINode, CDSUINode))
{
pCookie = GetDSCookieFromUINode(pUINode);
if (pCookie == NULL)
{
return E_FAIL;
}
CDSRenameObject* pRenameObject = NULL;
CString strClass = pCookie->GetClass();
CString szDN = pCookie->GetPath();
GetBasePathsInfo()->ComposeADsIPath(szPath, szDN);
//
// Rename user object
//
if (strClass == L"user"
#ifdef INETORGPERSON
|| strClass == L"inetOrgPerson"
#endif
)
{
//
// Rename user
//
pRenameObject = new CDSRenameUser(pUINode, pCookie, NewName, m_hwnd, this);
}
else if (strClass == L"group")
{
//
// Rename group
//
pRenameObject = new CDSRenameGroup(pUINode, pCookie, NewName, m_hwnd, this);
}
else if (strClass == L"contact")
{
//
// rename contact
//
pRenameObject = new CDSRenameContact(pUINode, pCookie, NewName, m_hwnd, this);
}
else if (strClass == L"site")
{
//
// Rename site
//
pRenameObject = new CDSRenameSite(pUINode, pCookie, NewName, m_hwnd, this);
}
else if (strClass == L"subnet")
{
//
// Rename subnet
//
pRenameObject = new CDSRenameSubnet(pUINode, pCookie, NewName, m_hwnd, this);
}
else if (strClass == L"nTDSConnection")
{
//
// Rename nTDSConnection
//
pRenameObject = new CDSRenameNTDSConnection(pUINode, pCookie, NewName, m_hwnd, this);
}
else
{
//
// Rename other object
//
pRenameObject = new CDSRenameObject(pUINode, pCookie, NewName, m_hwnd, this);
}
if (pRenameObject != NULL)
{
hr = pRenameObject->DoRename();
}
else
{
hr = E_FAIL;
}
}
else // !CDSUINode
{
hr = pUINode->Rename(NewName, this);
}
if (SUCCEEDED(hr) && !szPath.IsEmpty())
{
CStringList pathList;
pathList.AddTail(szPath);
InvalidateSavedQueriesContainingObjects(pathList);
}
return hr;
}
void CDSComponentData::ClearSubtreeHelperForRename(CUINode* pUINode)
{
//
// Verify parameters
//
if (pUINode == NULL)
{
ASSERT(FALSE);
return;
}
HSCOPEITEM ItemID;
CUIFolderInfo* pFolderInfo = NULL;
pFolderInfo = pUINode->GetFolderInfo();
if (pFolderInfo != NULL)
{
//
// remove the folder subtree in the UI
//
ItemID = pFolderInfo->GetScopeItem();
m_pScope->DeleteItem(ItemID, /* this node*/FALSE);
//
// clear list of children
//
pFolderInfo->DeleteAllLeafNodes();
pFolderInfo->DeleteAllContainerNodes();
//
// remove the descendants from the pending query table
//
m_queryNodeTable.RemoveDescendants(pUINode);
pFolderInfo->ReSetExpanded();
// make sure MMC knows the + sign should show
SCOPEDATAITEM scopeItem;
ZeroMemory(&scopeItem, sizeof(SCOPEDATAITEM));
scopeItem.ID = ItemID;
scopeItem.mask = SDI_CHILDREN;
scopeItem.cChildren = 1;
m_pScope->SetItem(&scopeItem);
}
}
CUINode* CDSComponentData::MoveObjectInUI(CDSUINode* pDSUINode)
{
CUINode* pParentUINode = pDSUINode->GetParent();
HSCOPEITEM ParentItemID = NULL;
HRESULT hr = S_OK;
ASSERT(pParentUINode != NULL && pParentUINode->IsContainer());
//
// find the new parent node
//
CUINode* pNewParentNode = NULL;
hr = FindParentCookie(pDSUINode->GetCookie()->GetPath(), &pNewParentNode);
if (pDSUINode->IsContainer())
{
HSCOPEITEM ItemID = pDSUINode->GetFolderInfo()->GetScopeItem();
hr = m_pScope->GetParentItem(ItemID, &ParentItemID, (MMC_COOKIE *)&pParentUINode);
//
// remove node from MMC
//
m_pScope->DeleteItem(ItemID, TRUE);
if (SUCCEEDED(hr))
{
//
// remove it from the list of children
//
pParentUINode->GetFolderInfo()->RemoveNode(pDSUINode);
}
if ((hr == S_OK) && pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
{
//
// add to new child list
//
pDSUINode->ClearParent();
if (pNewParentNode != NULL)
{
pNewParentNode->GetFolderInfo()->AddNode(pDSUINode);
//
// add to MMC scope pane
//
_AddScopeItem(pDSUINode, pNewParentNode->GetFolderInfo()->GetScopeItem());
}
}
else
{
// will get it later on when enumerating
delete pDSUINode;
}
}
else // leaf node
{
if ((pNewParentNode) &&
(pNewParentNode->GetFolderInfo()->IsExpanded()))
{
pDSUINode->ClearParent();
pNewParentNode->GetFolderInfo()->AddNode(pDSUINode);
}
m_pFrame->UpdateAllViews(NULL, (LPARAM)pDSUINode, DS_MOVE_OCCURRED);
}
return pNewParentNode;
}
HRESULT CDSComponentData::_MoveObject(CDSUINode* pDSUINode)
{
// guard against property sheet open on this cookie
if (_WarningOnSheetsUp(pDSUINode))
return S_OK;
CWaitCursor cwait;
// call the backend to do the delete
HRESULT hr = m_ActiveDS->MoveObject(pDSUINode->GetCookie());
if (SUCCEEDED(hr) && (hr != S_FALSE))
{
// we actually moved the object, move in the folders and MMC
CUINode* pNewParentNode = MoveObjectInUI(pDSUINode);
if (pNewParentNode && pNewParentNode->GetFolderInfo()->IsExpanded())
{
Refresh(pNewParentNode);
}
}
return hr;
}
HRESULT CDSComponentData::Refresh(CUINode* pNode, BOOL bFlushCache, BOOL bFlushColumns)
{
HRESULT hr = S_OK;
TRACE(_T("CDSComponentData::Refresh: cookie is %s\n"),
pNode->GetName());
if (m_queryNodeTable.IsLocked(pNode))
{
// this might happen if MMC's verb management bent out of shape (BUG?)
// like in the case of the "*" (num keypad) command (expand the whole tree)
// just ignore the command
return S_OK;
}
if (_WarningOnSheetsUp(pNode))
return hr;
if ((pNode == &m_RootNode) && !m_InitSuccess)
{
hr = _InitRootFromCurrentTargetInfo();
if (FAILED(hr))
{
m_InitSuccess = FALSE;
TRACE(_T("in Refresh, set m_InitSuccess to false\n"));
return hr;
}
else
{
m_InitSuccess = TRUE;
TRACE(_T("in Refresh, set m_InitSuccess to true\n"));
}
}
// remove the folder subtree in the UI
HSCOPEITEM ItemID = NULL;
if (pNode->IsContainer())
{
ItemID = pNode->GetFolderInfo()->GetScopeItem();
}
if (ItemID == NULL)
{
// let's try the parent
CUINode* pParent = pNode->GetParent();
ASSERT(pParent != NULL);
ASSERT(pParent->IsContainer());
ItemID = pParent->GetFolderInfo()->GetScopeItem();
if (ItemID == NULL)
{
return S_OK;
}
else
{
pNode = pParent;
}
}
m_pScope->DeleteItem(ItemID, /* this node*/FALSE);
// delete result pane items in the UI
TIMER(_T("calling update all views..."));
m_pFrame->UpdateAllViews(NULL, (LPARAM)pNode, DS_REFRESH_REQUESTED);
// clear list of children
TIMER(_T("back from UpdateAllViews.\ncleaning up data structs..."));
if (pNode == &m_RootNode)
{
if (m_pFavoritesNodesHolder != NULL)
{
// do not remove the favorites, just detach them from tree
m_RootNode.GetFolderInfo()->RemoveNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
m_pFavoritesNodesHolder->GetFavoritesRoot()->ClearParent();
m_pFavoritesNodesHolder->GetFavoritesRoot()->GetFolderInfo()->ReSetExpanded();
// clean up all the query folders, but otherwise leave the
// subtree intact
m_pFavoritesNodesHolder->GetFavoritesRoot()->RemoveQueryResults();
}
// remove the remaining folders
m_RootNode.GetFolderInfo()->DeleteAllLeafNodes();
m_RootNode.GetFolderInfo()->DeleteAllContainerNodes();
if (m_pFavoritesNodesHolder != NULL)
{
// re-attach the favorites underneath the root
m_RootNode.GetFolderInfo()->AddNode(m_pFavoritesNodesHolder->GetFavoritesRoot());
// add the favorite queries subtree
_AddScopeItem(m_pFavoritesNodesHolder->GetFavoritesRoot(),
m_RootNode.GetFolderInfo()->GetScopeItem());
}
}
else if (IS_CLASS(*pNode, CFavoritesNode))
{
// recurse down to other query folders to do cleanup
dynamic_cast<CFavoritesNode*>(pNode)->RemoveQueryResults();
// just add the favorites subfolders and query folders
CUINodeList* pNodeList = pNode->GetFolderInfo()->GetContainerList();
for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
{
CUINode* pCurrChildNode = pNodeList->GetNext(pos);
_AddScopeItem(pCurrChildNode,
pNode->GetFolderInfo()->GetScopeItem());
}
}
else if (IS_CLASS(*pNode, CSavedQueryNode))
{
pNode->GetFolderInfo()->DeleteAllLeafNodes();
pNode->GetFolderInfo()->DeleteAllContainerNodes();
dynamic_cast<CSavedQueryNode*>(pNode)->SetValid(TRUE);
}
else
{
ASSERT(IS_CLASS(*pNode, CDSUINode) );
// standard DS container, just remove all sub objects
pNode->GetFolderInfo()->DeleteAllLeafNodes();
pNode->GetFolderInfo()->DeleteAllContainerNodes();
}
TIMER(_T("datastructs cleaned up\n"));
// remove the descendants from the pending query table
m_queryNodeTable.RemoveDescendants(pNode);
if ((pNode == &m_RootNode) && bFlushCache)
{
TRACE(L"CDSComponentData::Refresh: flushing the cache\n");
m_pClassCache->Initialize(QuerySnapinType(), GetBasePathsInfo(), bFlushColumns);
}
// post a query
TRACE(L"CDSComponentData::Refresh: posting query\n");
_PostQueryToBackgroundThread(pNode);
TRACE(L"CDSComponentData::Refresh: returning\n");
return hr;
}
#if (FALSE)
HRESULT CDSComponentData::_OnPropertyChange(LPDATAOBJECT pDataObject, BOOL bScope)
{
if (pDataObject == NULL)
{
return E_INVALIDARG;
}
CInternalFormatCracker dobjCracker;
VERIFY(SUCCEEDED(dobjCracker.Extract(pDataObject)));
CDSCookie* pCookie = NULL;
CUINode* pUINode = dobjCracker.GetCookie();
if (pUINode == NULL)
{
return E_INVALIDARG;
}
//
// Right now we are not supporting properties on other node types
//
if (IS_CLASS(*pUINode, CDSUINode))
{
pCookie = GetDSCookieFromUINode(pUINode);
}
if (pCookie == NULL)
{
// not a DS object
return S_OK;
}
{
//
// notify the extension that an object has changed
//
CDSNotifyHandlerTransaction transaction(this);
transaction.SetEventType(DSA_NOTIFY_PROP);
transaction.Begin(pDataObject, NULL, NULL, FALSE);
//
// we do not call Confirm() because this is an asynchrnous call after the fact
//
transaction.Notify(0);
transaction.End();
}
//
// update the data to be displayed
//
//
// update all the possible instances in the query namespace
//
if (m_pFavoritesNodesHolder != NULL)
{
// find the list of items to update
CUINodeList queryNamespaceNodeList;
m_pFavoritesNodesHolder->GetFavoritesRoot()->FindCookiesInQueries(pCookie->GetPath(), &queryNamespaceNodeList);
// update all of them
for (POSITION pos = queryNamespaceNodeList.GetHeadPosition(); pos != NULL; )
{
CUINode* pCurrUINode = queryNamespaceNodeList.GetNext(pos);
HRESULT hrCurr = UpdateFromDS(pCurrUINode);
if (SUCCEEDED(hrCurr))
{
UpdateItem(pCurrUINode);
}
}
}
//
// figure out if the notification cookie is in the query namespace or
// in the DS one
//
BOOL bNodeFromQueryNamespace = IS_CLASS(*(pUINode->GetParent()), CSavedQueryNode);
CUINode* pUINodeToUpdate = NULL;
if (bNodeFromQueryNamespace)
{
// find the item
FindCookieInSubtree(&m_RootNode, pCookie->GetPath(), QuerySnapinType(), &pUINodeToUpdate);
}
else
{
pUINodeToUpdate = pUINode;
}
if (pUINodeToUpdate != NULL)
{
HRESULT hr = UpdateFromDS(pUINodeToUpdate);
if (SUCCEEDED(hr))
{
return UpdateItem(pUINodeToUpdate);
}
}
return S_OK;
}
#endif
HRESULT CDSComponentData::_OnPropertyChange(LPDATAOBJECT pDataObject, BOOL)
{
if (pDataObject == NULL)
{
return E_INVALIDARG;
}
CInternalFormatCracker ifc;
if (FAILED(ifc.Extract(pDataObject)))
{
ASSERT(FALSE);
return E_INVALIDARG;
}
CUINode* pUINode = ifc.GetCookie();
if (pUINode != NULL)
{
if (!IS_CLASS(*pUINode, CDSUINode))
{
UpdateItem(pUINode);
return S_OK;
}
}
CObjectNamesFormatCracker objectNamesFormatCracker;
if (FAILED(objectNamesFormatCracker.Extract(pDataObject)))
{
ASSERT(FALSE);
return E_INVALIDARG;
}
{
//
// notify the extension that an object has changed
//
CDSNotifyHandlerTransaction transaction(this);
transaction.SetEventType(DSA_NOTIFY_PROP);
transaction.Begin(pDataObject, NULL, NULL, FALSE);
//
// we do not call Confirm() because this is an asynchrnous call after the fact
//
transaction.Notify(0);
transaction.End();
}
for (UINT idx = 0; idx < objectNamesFormatCracker.GetCount(); idx ++)
{
//
// update the data to be displayed, need the DN out of the ADSI path
//
CComBSTR bstrDN;
CPathCracker pathCracker;
pathCracker.Set((LPWSTR)objectNamesFormatCracker.GetName(idx), ADS_SETTYPE_FULL);
pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
//
// update all the possible instances in the query namespace
//
if (m_pFavoritesNodesHolder != NULL)
{
// find the list of items to update
CUINodeList queryNamespaceNodeList;
m_pFavoritesNodesHolder->GetFavoritesRoot()->FindCookiesInQueries(bstrDN, &queryNamespaceNodeList);
// update all of them
for (POSITION pos = queryNamespaceNodeList.GetHeadPosition(); pos != NULL; )
{
CUINode* pCurrUINode = queryNamespaceNodeList.GetNext(pos);
HRESULT hrCurr = UpdateFromDS(pCurrUINode);
if (SUCCEEDED(hrCurr))
{
UpdateItem(pCurrUINode);
}
}
}
//
// find node in the DS namespace and update it
//
CUINode* pUINodeToUpdate = NULL;
// find the item
FindCookieInSubtree(&m_RootNode, bstrDN, QuerySnapinType(), &pUINodeToUpdate);
if (pUINodeToUpdate != NULL)
{
HRESULT hr = UpdateFromDS(pUINodeToUpdate);
if (SUCCEEDED(hr))
{
UpdateItem(pUINodeToUpdate);
}
}
}
return S_OK;
}
/* ---------------------------------------------------------
Helper function to create an LDAP query string to retrieve
a single element inside a given container.
Input: the DN of the object to query for.
e.g.: "cn=foo,ou=bar,dc=mydom,dc=com"
Output: a query string containing the leaf node properly escaped,
(as per RFC 2254)
e.g.: "(cn=foo)"
NOTES:
* we do not deal with embedded NULLs (we have regular C/C++ strings)
* any \ character remaining after the path cracked full unescaping
has to be escaped along the other special characters by
using the \HexHex sequences.
------------------------------------------------------------*/
HRESULT _CreateLdapQueryFilterStringFromDN(IN LPCWSTR lpszDN,
OUT CString& szQueryString)
{
szQueryString.Empty();
CPathCracker pathCracker;
// remove any LDAP/ADSI escaping from the DN
pathCracker.Set((LPWSTR)lpszDN, ADS_SETTYPE_DN);
pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
// retrieve the leaf element
CString szNewElement;
CComBSTR bstrLeafElement;
HRESULT hr = pathCracker.GetElement(0, &bstrLeafElement);
if (FAILED(hr))
{
return hr;
}
LPCWSTR lpszTemp = bstrLeafElement;
TRACE(L"bstrLeafElement = %s\n", lpszTemp);
// do LDAP escaping (as per RFC 2254)
szQueryString = L"(";
for (WCHAR* pChar = bstrLeafElement; (*pChar) != NULL; pChar++)
{
switch (*pChar)
{
case L'*':
szQueryString += L"\\2a";
break;
case L'(':
szQueryString += L"\\28";
break;
case L')':
szQueryString += L"\\29";
break;
case L'\\':
szQueryString += L"\\5c";
break;
default:
szQueryString += (*pChar);
} // switch
} // for
// finish wrapping with parentheses,
// to get something like "(cn=foo)"
szQueryString += L")";
return S_OK;
}
HRESULT CDSComponentData::UpdateFromDS(CUINode* pUINode)
{
ASSERT(pUINode != NULL);
//
// get the node data
//
CDSCookie* pCookie = NULL;
if (IS_CLASS(*pUINode, CDSUINode))
{
pCookie = GetDSCookieFromUINode(pUINode);
}
if (pCookie == NULL)
{
ASSERT(FALSE); // should never happen
return E_FAIL;
}
//
// get the container node
//
CUINode* pParentUINode = pUINode->GetParent();
ASSERT(pParentUINode != NULL);
//
// get the distinguished name of the parent by using the path in the cookie
// and removing the leaf element using the path cracker.
// e.g., given a DN "cn=x,ou=foo,...", the parent DN will be "ou=foo,..."
//
CComBSTR bstrParentDN;
CPathCracker pathCracker;
HRESULT hr = pathCracker.Set((LPWSTR)pCookie->GetPath(), ADS_SETTYPE_DN);
ASSERT(SUCCEEDED(hr));
if (pParentUINode != GetRootNode())
{
hr = pathCracker.RemoveLeafElement();
ASSERT(SUCCEEDED(hr));
}
hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrParentDN);
ASSERT(SUCCEEDED(hr));
//
// get the LDAP path of the parent
//
CString szParentLdapPath;
GetBasePathsInfo()->ComposeADsIPath(szParentLdapPath, bstrParentDN);
//
// find a matching column set
//
CDSColumnSet* pColumnSet = pParentUINode->GetColumnSet(this);
if (pColumnSet == NULL)
{
return hr;
}
//
// create a search object and init it
//
CDSSearch ContainerSrch(m_pClassCache, this);
TRACE(L"ContainerSrch.Init(%s)\n", (LPCWSTR)szParentLdapPath);
hr = ContainerSrch.Init(szParentLdapPath);
if (FAILED(hr))
{
return hr;
}
//
// create a query string to look for the naming attribute
// eg, given a DN "cn=x,ou=foo,..." the search string
// will look like "(cn=x)"
//
CString szQueryString;
hr = _CreateLdapQueryFilterStringFromDN(pCookie->GetPath(), szQueryString);
if (FAILED(hr))
{
return hr;
}
TRACE(L"szQueryString = %s\n", (LPCWSTR)szQueryString);
ContainerSrch.SetAttributeListForContainerClass(pColumnSet);
ContainerSrch.SetFilterString((LPWSTR)(LPCWSTR)szQueryString);
if (pParentUINode == GetRootNode())
{
ContainerSrch.SetSearchScope(ADS_SCOPE_BASE);
}
else
{
ContainerSrch.SetSearchScope(ADS_SCOPE_ONELEVEL);
}
hr = ContainerSrch.DoQuery();
if (FAILED(hr))
{
return hr;
}
//
// get the only row
//
hr = ContainerSrch.GetNextRow();
if (hr == S_ADS_NOMORE_ROWS)
{
hr = E_INVALIDARG;
}
if (FAILED(hr))
{
return hr;
}
//
// update the cookie itself
//
hr = ContainerSrch.SetCookieFromData(pCookie, pColumnSet);
//
// special case if it is a domain DNS object,
// we want fo get the canonical name for display
//
if (wcscmp(pCookie->GetClass(), L"domainDNS") == 0)
{
ADS_SEARCH_COLUMN Column;
CString csCanonicalName;
int slashLocation;
LPWSTR canonicalNameAttrib = L"canonicalName";
ContainerSrch.SetAttributeList (&canonicalNameAttrib, 1);
hr = ContainerSrch.DoQuery();
if (FAILED(hr))
{
return hr;
}
hr = ContainerSrch.GetNextRow();
if (FAILED(hr))
{
return hr;
}
hr = ContainerSrch.GetColumn(canonicalNameAttrib, &Column);
if (FAILED(hr))
{
return hr;
}
ColumnExtractString (csCanonicalName, pCookie, &Column);
slashLocation = csCanonicalName.Find('/');
if (slashLocation != 0)
{
csCanonicalName = csCanonicalName.Left(slashLocation);
}
pCookie->SetName(csCanonicalName);
TRACE(L"canonical name pCookie->GetName() = %s\n", pCookie->GetName());
//
// Free column data
//
ContainerSrch.FreeColumn(&Column);
}
return hr;
}
BOOL CDSComponentData::CanRefreshAll()
{
return !_WarningOnSheetsUp(&m_RootNode);
}
void CDSComponentData::RefreshAll()
{
ASSERT(!m_RootNode.IsSheetLocked());
// need to refresh the tree (all containers below the root)
CUINodeList* pContainerNodeList = m_RootNode.GetFolderInfo()->GetContainerList();
for (POSITION pos = pContainerNodeList->GetHeadPosition(); pos != NULL; )
{
CUINode* pNode = pContainerNodeList->GetNext(pos);
ASSERT(pNode->IsContainer());
if (pNode->GetFolderInfo()->IsExpanded())
{
Refresh(pNode);
}
}
}
void CDSComponentData::ClearClassCacheAndRefreshRoot()
{
ASSERT(!m_RootNode.IsSheetLocked());
if (m_RootNode.GetFolderInfo()->IsExpanded())
{
Refresh(&m_RootNode, TRUE /*bFlushCache*/, FALSE );
}
}
// REVIEW_MARCOC_PORT: this function is not going to work with
// items that are of different types. Need to generalize as see fit.
BOOL _SearchList(CUINodeList* pContainers,
LPCWSTR lpszParentDN,
CUINode** ppParentUINode)
{
for (POSITION pos = pContainers->GetHeadPosition(); pos != NULL; )
{
CUINode* pCurrentNode = pContainers->GetNext(pos);
ASSERT(pCurrentNode->IsContainer());
if (!IS_CLASS(*pCurrentNode, CDSUINode))
{
// not a node with a cookie, just skip
continue;
}
/* is this the right cookie? */
CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentNode);
LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
TRACE (_T("--SearchList: Looking at: %s\n"), lpszCurrentPath);
if (_wcsicmp(lpszCurrentPath, lpszParentDN) == 0)
{
TRACE (_T("--SearchList: Found it!\n"));
*ppParentUINode = pCurrentNode;
return TRUE; // got it!!!
}
else
{
TRACE (L"--SearchList: not found...\n");
TRACE (_T("-- going down the tree: %s\n"), lpszCurrentPath);
CUINodeList* pSubContainers = pCurrentNode->GetFolderInfo()->GetContainerList();
if (_SearchList(pSubContainers, lpszParentDN, ppParentUINode))
{
return TRUE; // got it!!!
}
}
} // for
return FALSE; // not found
}
/*
given a cookie, find the cookie corresponding to its
parent node, if it exists. this is an expensive operation
this is used for figuring out where to refresh after having
moved an object. we know the new path to the object, but have
no idea where or if that parent cookie exists in the tree.
HUNT IT DOWN!!
*/
HRESULT
CDSComponentData::FindParentCookie(LPCWSTR lpszCookieDN, CUINode** ppParentUINode)
{
// init outout variable
*ppParentUINode = NULL;
// bind to the ADSI aobject
CString szPath;
GetBasePathsInfo()->ComposeADsIPath(szPath, lpszCookieDN);
CComPtr<IADs> spDSObj;
HRESULT hr = DSAdminOpenObject(szPath,
IID_IADs,
(void **)&spDSObj,
TRUE /*bServer*/);
if (FAILED(hr))
{
return hr; // could not bind
}
// get the LDAP path of the parent
CComBSTR ParentPath;
hr = spDSObj->get_Parent(&ParentPath);
if (FAILED(hr))
{
return hr;
}
CString szParentDN;
StripADsIPath(ParentPath, szParentDN);
TRACE(_T("goin on a cookie hunt.. (for %s)\n"), ParentPath);
// start a search from the root
CUINodeList* pContainers = m_RootNode.GetFolderInfo()->GetContainerList();
BOOL bFound = _SearchList(pContainers,
szParentDN,
ppParentUINode);
return bFound ? S_OK : S_FALSE;
}
//
// This is a recursive search of the currently expanded domain tree starting at
// the root looking at all CDSUINodes for a matching DN.
//
// NOTE : this may be an extremely expensive operation if a lot
// of containers have been expanded or they have a lot of
// children.
//
BOOL CDSComponentData::FindUINodeByDN(CUINode* pContainerNode,
PCWSTR pszDN,
CUINode** ppFoundNode)
{
if (ppFoundNode == NULL)
{
return FALSE;
}
*ppFoundNode = NULL;
if (pContainerNode == NULL || !pContainerNode->IsContainer())
{
return FALSE;
}
//
// First look through the leaf nodes
//
CUINodeList* pLeafList = pContainerNode->GetFolderInfo()->GetLeafList();
POSITION leafPos = pLeafList->GetHeadPosition();
while (leafPos != NULL)
{
CUINode* pCurrentLeaf = pLeafList->GetNext(leafPos);
if (pCurrentLeaf == NULL || !IS_CLASS(*pCurrentLeaf, CDSUINode))
{
//
// We can only search for DNs if the node is a CDSUINode
//
continue;
}
CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentLeaf);
LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
if (_wcsicmp(lpszCurrentPath, pszDN) == 0)
{
*ppFoundNode = pCurrentLeaf;
return TRUE;
}
}
//
// If not found in the leaf list then do a recursive search on the containers
//
CUINodeList* pContainerList = pContainerNode->GetFolderInfo()->GetContainerList();
POSITION containerPos = pContainerList->GetHeadPosition();
while (containerPos != NULL)
{
CUINode* pCurrentContainer = pContainerList->GetNext(containerPos);
if (pCurrentContainer == NULL || !IS_CLASS(*pCurrentContainer, CDSUINode))
{
//
// We can only search for DNs if the node is a CDSUINode
//
continue;
}
CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentContainer);
LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
if (_wcsicmp(lpszCurrentPath, pszDN) == 0)
{
*ppFoundNode = pCurrentContainer;
return TRUE;
}
else
{
//
// Start the recursion
//
if (FindUINodeByDN(pCurrentContainer, pszDN, ppFoundNode))
{
return TRUE;
}
}
}
return FALSE;
}
//
// This looks for nodes in the saved query tree that has the same DN as
// the any of the objects in the list and then invalidates the containing
// saved query node
//
void CDSComponentData::InvalidateSavedQueriesContainingObjects(const CUINodeList& refUINodeList)
{
if (QuerySnapinType() != SNAPINTYPE_SITE)
{
//
// Make a list of DNs
//
CStringList szDNList;
POSITION pos = refUINodeList.GetHeadPosition();
while (pos)
{
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(refUINodeList.GetNext(pos));
if (!pDSUINode)
{
//
// Ignore anything that is not a DS node
//
continue;
}
CDSCookie* pCookie = GetDSCookieFromUINode(pDSUINode);
if (!pCookie)
{
ASSERT(FALSE);
continue;
}
szDNList.AddTail(pCookie->GetPath());
}
if (szDNList.GetCount() > 0)
{
//
// Now search through saved query tree invalidating query nodes
// that contain items in the list
//
GetFavoritesNodeHolder()->InvalidateSavedQueriesContainingObjects(this, szDNList);
}
}
}
//
// This looks for nodes in the saved query tree that has the same DN as
// the any of the objects in the list and then invalidates the containing
// saved query node
//
void CDSComponentData::InvalidateSavedQueriesContainingObjects(const CStringList& refPathList)
{
if (QuerySnapinType() != SNAPINTYPE_SITE)
{
CStringList szDNList;
CPathCracker pathCracker;
//
// Convert all the paths to DNs
//
POSITION pos = refPathList.GetHeadPosition();
while (pos)
{
CString szPath = refPathList.GetNext(pos);
HRESULT hr = pathCracker.Set((PWSTR)(PCWSTR)szPath, ADS_SETTYPE_FULL);
if (SUCCEEDED(hr))
{
CComBSTR sbstrDN;
hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &sbstrDN);
if (SUCCEEDED(hr))
{
szDNList.AddTail(sbstrDN);
}
}
}
if (szDNList.GetCount() > 0)
{
//
// Now search through saved query tree invalidating query nodes
// that contain items in the list
//
GetFavoritesNodeHolder()->InvalidateSavedQueriesContainingObjects(this, szDNList);
}
}
}
void CDSComponentData::ReclaimCookies()
{
AddToLRUList (&m_RootNode);
CUINode* pUINode = NULL;
POSITION pos, pos2;
CUINodeList* pContainers = NULL;
#ifdef DBG
TRACE (_T("dumping LRU list...\n"));
pos = m_LRUList.GetHeadPosition();
while (pos)
{
pUINode = m_LRUList.GetNext(pos);
CUIFolderInfo* pFolderInfo = pUINode->GetFolderInfo();
if (pFolderInfo != NULL)
{
TRACE (_T("\tcontainer: %s (%d)\n"), pUINode->GetName(),
pFolderInfo->GetSerialNumber());
}
}
#endif
//
// Get Root folder info
//
CUIFolderInfo* pRootFolderInfo = m_RootNode.GetFolderInfo();
ASSERT(pRootFolderInfo != NULL);
TRACE (_T("-->total count is %d: reclaiming cookies from LRU list...\n"),
pRootFolderInfo->GetObjectCount());
UINT maxitems = m_pQueryFilter->GetMaxItemCount();
pos = m_LRUList.GetHeadPosition();
while (pos)
{
CUIFolderInfo* pUIFolderInfo = NULL;
pUINode = m_LRUList.GetNext(pos);
pUIFolderInfo = pUINode->GetFolderInfo();
if (pUIFolderInfo != NULL)
{
TRACE (_T("!!--!!container %s (sn:%d) containing %d objects is being reclaimed\n"),
pUINode->GetName(),
pUIFolderInfo->GetSerialNumber(),
pUIFolderInfo->GetObjectCount());
//
// clean all of the leaves out
//
pUIFolderInfo->DeleteAllLeafNodes();
//
// clean all of the containers here out of the tree view
//
pContainers = pUIFolderInfo->GetContainerList();
if (pContainers)
{
HSCOPEITEM ItemID;
CUINode* pUIContNode= NULL;
pos2 = pContainers->GetHeadPosition();
while (pos2)
{
pUIContNode = pContainers->GetNext(pos2);
CUIFolderInfo* pFolderInfo = pUIContNode->GetFolderInfo();
if (pFolderInfo != NULL)
{
ItemID = pFolderInfo->GetScopeItem();
m_pScope->DeleteItem (ItemID, TRUE);
}
}
}
pUIFolderInfo->DeleteAllContainerNodes();
pUIFolderInfo->ReSetExpanded();
if (pRootFolderInfo->GetObjectCount() < (maxitems * 5))
{
break;
}
}
}
TRACE (_T("--> done reclaiming cookies from LRU list. total count is now %d: ..\n"),
pRootFolderInfo->GetObjectCount());
//
// Empty the LRU list
//
while (!m_LRUList.IsEmpty())
{
m_LRUList.RemoveTail();
}
}
BOOL CDSComponentData::IsSelectionAnywhere(CUINode* pUINode)
{
ASSERT(pUINode->IsContainer());
UINODESELECTION nodeSelection;
nodeSelection.pUINode = pUINode;
nodeSelection.IsSelection = FALSE;
// if any view has this cookie selected, the IsSelection member
// will be TRUE when we return.
m_pFrame->UpdateAllViews (NULL,
(LPARAM)&nodeSelection,
DS_IS_COOKIE_SELECTION);
return nodeSelection.IsSelection;
}
void CDSComponentData::AddToLRUList (CUINode* pUINode)
{
HRESULT hr = S_OK;
CUIFolderInfo* pUIFolderInfo = pUINode->GetFolderInfo();
if (pUIFolderInfo != NULL)
{
CUINodeList* pContainers = pUIFolderInfo->GetContainerList();
CUINode* pUIContNode = NULL;
size_t cContainers = pContainers->GetCount();
BOOL foundSpot = FALSE;
POSITION pos;
if (cContainers > 0)
{
pos = pContainers->GetHeadPosition();
while (pos)
{
pUIContNode = pContainers->GetNext(pos);
if (pUIContNode != NULL)
{
AddToLRUList (pUIContNode);
}
}
}
//
// now we've taken care of the children, let's add
// this one to the list
//
//
// first, let's see if it is expanded
// this doesn't work currently - asking MMC guys why
//
SCOPEDATAITEM ScopeData;
ZeroMemory (&ScopeData, sizeof(SCOPEDATAITEM));
ScopeData.ID = pUIFolderInfo->GetScopeItem();
ScopeData.mask = SDI_STATE | SDI_PARAM;
hr = m_pScope->GetItem (&ScopeData);
if (!pUINode->IsSheetLocked()
&& (!IsSelectionAnywhere (pUINode))
&& (pUIFolderInfo->GetSerialNumber() != SERIALNUM_NOT_TOUCHED)
&& (!((ScopeData.nState & TVIS_EXPANDED) == TVIS_EXPANDED)))
{
pos = m_LRUList.GetHeadPosition();
if (!pos)
{
m_LRUList.AddHead(pUINode);
TRACE(_T("adding head: %s[%d]\n"), pUINode->GetName(),
pUIFolderInfo->GetSerialNumber);
}
else
{
CUINode* pLRUNode = NULL;
CUIFolderInfo* pLRUFolderInfo = NULL;
while (pos)
{
pLRUNode = m_LRUList.GetAt(pos);
pLRUFolderInfo = pLRUNode->GetFolderInfo();
if (pLRUFolderInfo != NULL)
{
if (pUIFolderInfo->GetSerialNumber() <
pLRUFolderInfo->GetSerialNumber())
{
foundSpot = TRUE;
break;
}
else
{
pLRUNode = m_LRUList.GetNext(pos);
}
}
}
if (!foundSpot)
{
m_LRUList.AddTail(pUINode);
TRACE(_T("adding tail: %s [%d]\n"), pUINode->GetName(),
pUIFolderInfo->GetSerialNumber());
}
else
{
m_LRUList.InsertBefore (pos, pUINode);
TRACE(_T("inserting: %s [%d]\n"), pUINode->GetName(),
pUIFolderInfo->GetSerialNumber());
}
}
}
}
}
HRESULT
CDSComponentData::_OnNamespaceExtensionExpand(LPDATAOBJECT, HSCOPEITEM hParent)
{
HRESULT hr = E_FAIL;
ASSERT(!m_bRunAsPrimarySnapin);
// namespace extension only for DS snapin
if (QuerySnapinType() != SNAPINTYPE_DSEX)
return hr;
// need to crack the data object to set the context
// retrieve the query string
m_pQueryFilter->SetExtensionFilterString(L"(objectClass=*)");
if (m_bAddRootWhenExtended)
{
hr = _AddScopeItem(&m_RootNode, hParent);
}
else
{
// need to directly expand the root and add children underneath
hr = _OnExpand(&m_RootNode, hParent, MMCN_EXPAND);
}
return hr;
}
//
// Right now this only checks adding group to group and user to group. Any other object class returns FALSE
//
BOOL CDSComponentData::CanAddCookieToGroup(CDSCookie* pCookie, INT iGroupType, BOOL bMixedMode)
{
BOOL bCanAdd = FALSE;
if (pCookie != NULL)
{
if (_wcsicmp(pCookie->GetClass(), L"group") == 0)
{
CDSCookieInfoGroup* pExtraInfo = dynamic_cast<CDSCookieInfoGroup*>(pCookie->GetExtraInfo());
if (pExtraInfo != NULL)
{
INT iAddGroupType = pExtraInfo->m_GroupType;
if (bMixedMode)
{
//
// Determine if the group can't be added
//
if (iGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - Builtin SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - LG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SE
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - Builtin SE
// Member - ? SD
//
bCanAdd = TRUE;
}
}
}
else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - GG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - GG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - GG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - GG SE
// Member - UG SD
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - GG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - LG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - LG SE
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - LG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - GG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - UG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - GG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - UG SE
// Member - UG SD
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - UG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else
{
//
// Mixed Mode
// Target - ? SE
// Member - ? ?
//
bCanAdd = FALSE;
}
}
else // Distribution group
{
if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - Builtin SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - Builtin SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - Builtin SD
// Member - ? SD
//
bCanAdd = TRUE;
}
}
}
else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - GG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - GG SD
// Member - UG SD
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - GG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - LG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - LG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - LG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - LG SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - LG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Mixed Mode
// Target - UG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Mixed Mode
// Target - UG SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Mixed Mode
// Target - UG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else
{
//
// Mixed Mode
// Target - ? SD
// Member - ? ?
//
bCanAdd = FALSE;
}
}
}
else // native mode
{
//
// Determine if the group can't be added
//
if (iGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Native Mode
// Target - Builtin SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - LG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - Builtin SE
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - Builtin SE
// Member - ? SD
//
bCanAdd = TRUE;
}
}
}
else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Native Mode
// Target - GG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - GG SE
// Member - UG SD
//
bCanAdd = FALSE;
}
else
{
//
// Native Mode
// Target - GG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - LG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - LG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - LG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - LG SE
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - LG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - UG SE
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - UG SE
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - UG SE
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else
{
//
// Native Mode
// Target - ? SE
// Member - ? ?
//
bCanAdd = FALSE;
}
}
else // Distribution group
{
if (iGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - Buitlin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - Builtin SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - Builtin SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - Builtin SD
// Member - ? SD
//
bCanAdd = TRUE;
}
}
}
else if (iGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - UG SE
//
bCanAdd = FALSE;
}
else
{
//
// Native Mode
// Target - GG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - GG SD
// Member - UG SD
//
bCanAdd = FALSE;
}
else
{
//
// Native Mode
// Target - GG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - LG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - LG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - LG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - LG SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - LG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else if (iGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
if (iAddGroupType & GROUP_TYPE_SECURITY_ENABLED)
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - Builtin SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - GG SE
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - LG SE
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - UG SE
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - UG SD
// Member - ? SE
//
bCanAdd = FALSE;
}
}
else // group to add is a distribution group
{
if (iAddGroupType & GROUP_TYPE_BUILTIN_LOCAL_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - Builtin SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_ACCOUNT_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - GG SD
//
bCanAdd = TRUE;
}
else if (iAddGroupType & GROUP_TYPE_RESOURCE_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - LG SD
//
bCanAdd = FALSE;
}
else if (iAddGroupType & GROUP_TYPE_UNIVERSAL_GROUP)
{
//
// Native Mode
// Target - UG SD
// Member - UG SD
//
bCanAdd = TRUE;
}
else
{
//
// Native Mode
// Target - UG SD
// Member - ? SD
//
bCanAdd = FALSE;
}
}
}
else
{
//
// Native Mode
// Target - ? SD
// Member - ? ?
//
bCanAdd = FALSE;
}
}
}
}
}
else if (_wcsicmp(pCookie->GetClass(), L"user") == 0 ||
#ifdef INETORGPERSON
_wcsicmp(pCookie->GetClass(), L"inetOrgPerson") == 0 ||
#endif
_wcsicmp(pCookie->GetClass(), L"contact") == 0 ||
_wcsicmp(pCookie->GetClass(), L"computer") == 0)
{
bCanAdd = TRUE;
}
else
{
BOOL bSecurity = (iGroupType & GROUP_TYPE_SECURITY_ENABLED) ? TRUE : FALSE;
bCanAdd = m_pClassCache->CanAddToGroup(GetBasePathsInfo(), pCookie->GetClass(), bSecurity);
}
}
else
{
bCanAdd = TRUE;
}
return bCanAdd;
}
////////////////////////////////////////////////////////////////////
// CDSComponentData thread API's
BOOL CDSComponentData::_StartBackgroundThread()
{
ASSERT(m_pHiddenWnd != NULL);
ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
if ((m_pHiddenWnd == NULL) || !::IsWindow(m_pHiddenWnd->m_hWnd) )
return FALSE;
CDispatcherThread* pThreadObj = new CDispatcherThread;
ASSERT(pThreadObj != NULL);
if (pThreadObj == NULL)
return FALSE;
// start the the thread
ASSERT(m_pBackgroundThreadInfo->m_nThreadID == 0);
ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle == NULL);
ASSERT(m_pBackgroundThreadInfo->m_state == notStarted);
ASSERT(pThreadObj->m_bAutoDelete);
if (!pThreadObj->Start(m_pHiddenWnd->m_hWnd, this))
return FALSE;
ASSERT(pThreadObj->m_nThreadID != 0);
ASSERT(pThreadObj->m_hThread != NULL);
// copy the thread info we need from the thread object
m_pBackgroundThreadInfo->m_hThreadHandle = pThreadObj->m_hThread;
m_pBackgroundThreadInfo->m_nThreadID = pThreadObj->m_nThreadID;
// wait for the thread to start and be ready to receive messages
_WaitForBackGroundThreadStartAck();
ASSERT(m_pBackgroundThreadInfo->m_state == running);
TRACE(L"dispatcher thread (HANDLE = 0x%x) running\n", m_pBackgroundThreadInfo->m_hThreadHandle);
return TRUE;
}
void CDSComponentData::_WaitForBackGroundThreadStartAck()
{
ASSERT(m_pHiddenWnd != NULL);
ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd));
ASSERT(m_pBackgroundThreadInfo->m_state == notStarted);
MSG tempMSG;
while(m_pBackgroundThreadInfo->m_state == notStarted)
{
if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadStartNotificationMessage,
CHiddenWnd::s_ThreadStartNotificationMessage,
PM_REMOVE))
{
DispatchMessage(&tempMSG);
}
}
ASSERT(m_pBackgroundThreadInfo->m_state == running);
}
void CDSComponentData::_ShutDownBackgroundThread()
{
TRACE(L"CDSComponentData::_ShutDownBackgroundThread()\n");
// set thread state to shutdown mode
// to avoid any spurious processing
ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
ASSERT(m_pBackgroundThreadInfo->m_state == running);
m_pBackgroundThreadInfo->m_state = shuttingDown;
// post a message to the dispatcher thread to signal shutdown
_PostMessageToBackgroundThread(THREAD_SHUTDOWN_MSG, 0,0);
// wait for the dispatcher thread to acknowledge
// (i.e. all worker threads have shut down)
TRACE(L"Waiting for CHiddenWnd::s_ThreadShutDownNotificationMessage\n");
MSG tempMSG;
while(m_pBackgroundThreadInfo->m_state == shuttingDown)
{
if (::PeekMessage(&tempMSG,m_pHiddenWnd->m_hWnd,CHiddenWnd::s_ThreadShutDownNotificationMessage,
CHiddenWnd::s_ThreadShutDownNotificationMessage,
PM_REMOVE))
{
DispatchMessage(&tempMSG);
}
}
ASSERT(m_pBackgroundThreadInfo->m_state == terminated);
// wait for the dispatcher thread handle to become signalled
TRACE(L"before WaitForThreadShutdown(0x%x) on dispatcher thread\n", m_pBackgroundThreadInfo->m_hThreadHandle);
WaitForThreadShutdown(&(m_pBackgroundThreadInfo->m_hThreadHandle), 1);
TRACE(L"after WaitForThreadShutdown() on dispatcher thread\n");
}
BOOL CDSComponentData::_PostQueryToBackgroundThread(CUINode* pUINode)
{
CThreadQueryInfo* pQueryInfo = NULL;
if (pUINode == &m_RootNode)
{
// enumerating the root of the namespace
CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
pDSQueryInfo->SetQueryDSQueryParameters(rootFolder,
m_RootNode.GetPath(),
NULL, // class
m_pQueryFilter->GetQueryString(),
m_pQueryFilter->GetMaxItemCount(),
TRUE, // bOneLevel
m_RootNode.GetColumnSet(this)->GetColumnID());
pQueryInfo = pDSQueryInfo;
}
else if (IS_CLASS(*pUINode, CDSUINode))
{
// enumerating regular DS folder
CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
CDSCookie* pCookie = GetDSCookieFromUINode(pUINode);
ASSERT(pCookie != NULL);
pDSQueryInfo->SetQueryDSQueryParameters(dsFolder,
pCookie->GetPath(),
pCookie->GetClass(),
m_pQueryFilter->GetQueryString(),
m_pQueryFilter->GetMaxItemCount(),
TRUE, // bOneLevel
pUINode->GetColumnSet(this)->GetColumnID());
pQueryInfo = pDSQueryInfo;
}
else if (IS_CLASS(*pUINode, CSavedQueryNode))
{
// enumerating a saved query folder
CDSThreadQueryInfo* pDSQueryInfo = new CDSThreadQueryInfo;
if (pDSQueryInfo != NULL)
{
CSavedQueryNode* pSavedQueryNode = dynamic_cast<CSavedQueryNode*>(pUINode);
ASSERT(pSavedQueryNode != NULL);
if (pSavedQueryNode != NULL)
{
if (pSavedQueryNode->IsFilterLastLogon())
{
if (GetBasePathsInfo()->GetDomainBehaviorVersion() == DS_BEHAVIOR_WIN2000)
{
CString szText, szCaption;
VERIFY(szText.LoadString(IDS_FILTER_LAST_LOGON_VERSION));
VERIFY(szCaption.LoadString(IDS_DSSNAPINNAME));
MessageBox(GetHWnd(), szText, szCaption, MB_OK | MB_ICONSTOP);
return FALSE;
}
}
pDSQueryInfo->SetQueryDSQueryParameters(queryFolder,
pSavedQueryNode->GetRootPath(),
NULL, // class
pSavedQueryNode->GetQueryString(),
UINT_MAX, // don't limit the number of items the query returns
pSavedQueryNode->IsOneLevel(),
pUINode->GetColumnSet(this)->GetColumnID());
pQueryInfo = pDSQueryInfo;
}
else
{
TRACE(_T("Failed to dynamically cast to CSavedQueryNode in CDSComponentData::_PostQueryToBackgroundThread()"));
ASSERT(FALSE);
}
}
else
{
TRACE(_T("Failed to allocate memory for CDSThreadQueryInfo in CDSComponentData::_PostQueryToBackgroundThread()"));
ASSERT(FALSE);
}
}
if (pQueryInfo == NULL)
{
return FALSE;
}
TRACE(_T("CDSComponentData::_PostQueryToBackgroundThread: cookie is %s\n"),
pUINode->GetName());
ASSERT(pUINode->IsContainer());
ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
ASSERT(m_pBackgroundThreadInfo->m_state == running);
m_queryNodeTable.Add(pUINode);
m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_VERB_UPDATE);
VERIFY(SUCCEEDED(ChangeScopeItemIcon(pUINode)));
TRACE(L"CDSComponentData::_PostQueryToBackgroundThread: posting DISPATCH_THREAD_RUN_MSG\n");
return _PostMessageToBackgroundThread(DISPATCH_THREAD_RUN_MSG,
(WPARAM)pUINode, (LPARAM)pQueryInfo);
}
BOOL CDSComponentData::_PostMessageToBackgroundThread(UINT Msg, WPARAM wParam, LPARAM lParam)
{
ASSERT(m_pBackgroundThreadInfo->m_nThreadID != 0);
ASSERT(m_pBackgroundThreadInfo->m_hThreadHandle != NULL);
return ::PostThreadMessage(m_pBackgroundThreadInfo->m_nThreadID, Msg, wParam, lParam);
}
void CDSComponentData::_OnTooMuchData(CUINode* pUINode)
{
if (!m_queryNodeTable.IsPresent(pUINode))
return; // cookie not found, node not there anymore
AFX_MANAGE_STATE(AfxGetStaticModuleState());
BOOL bHandledWithApproximation = FALSE;
CDSCookie* pDSCookie = GetDSCookieFromUINode(pUINode);
if (pDSCookie != NULL)
{
CString szPath;
GetBasePathsInfo()->ComposeADsIPath(szPath, pDSCookie->GetPath());
//
// Bind to the object and determine approximately how many
// objects are in the container
//
CComPtr<IDirectoryObject> spDirObject;
HRESULT hr = DSAdminOpenObject(szPath,
IID_IDirectoryObject,
(PVOID*)&spDirObject,
TRUE /*bServer*/);
if (SUCCEEDED(hr))
{
//
// Retrieve the approximation through the constructed attribute
//
const int iAttrCount = 1;
PWSTR pszAttribs[] = { L"msDS-Approx-Immed-Subordinates" };
PADS_ATTR_INFO pAttrInfo = NULL;
DWORD dwNumRet = 0;
CComVariant var;
hr = spDirObject->GetObjectAttributes(pszAttribs,
iAttrCount,
&pAttrInfo,
&dwNumRet);
if (SUCCEEDED(hr))
{
ASSERT(dwNumRet == 1);
ASSERT(pAttrInfo != NULL && pAttrInfo->pADsValues != NULL);
if (dwNumRet == 1 &&
pAttrInfo != NULL &&
pAttrInfo->pADsValues != NULL)
{
UINT nCount = static_cast<UINT>(pAttrInfo->pADsValues->Integer);
UINT nRetrieved = m_pQueryFilter->GetMaxItemCount();
UINT nApprox = __max(nCount, nRetrieved);
//
// Format the message
//
CString szMsg;
szMsg.Format(IDS_MSG_QUERY_TOO_MANY_ITEMS_WITH_APPROX, nRetrieved, nApprox, pUINode->GetName());
PVOID apv[1] = {(LPWSTR)(LPCWSTR)szMsg};
ReportErrorEx (m_hwnd,IDS_STRING,S_OK, MB_OK | MB_ICONINFORMATION, apv, 1);
//
// We were able to retrieve the approximation of the contained objects and post an error
// so we don't have to resort to the old message
//
bHandledWithApproximation = TRUE;
pUINode->GetFolderInfo()->SetTooMuchData(TRUE, nCount);
m_pFrame->UpdateAllViews (NULL, NULL, DS_UPDATE_OBJECT_COUNT);
}
if (pAttrInfo != NULL)
{
FreeADsMem(pAttrInfo);
pAttrInfo = NULL;
}
}
}
}
//
// Resort to using the old message if we are unable to retrieve the approximation
//
if (!bHandledWithApproximation)
{
CString szFmt;
szFmt.LoadString(IDS_MSG_QUERY_TOO_MANY_ITEMS);
CString szMsg;
szMsg.Format(szFmt, pUINode->GetName());
PVOID apv[1] = {(LPWSTR)(LPCWSTR)szMsg};
ReportErrorEx (m_hwnd,IDS_STRING,S_OK, MB_OK | MB_ICONINFORMATION, apv, 1);
}
}
void CDSComponentData::AddScopeItemToUI(CUINode* pUINode, BOOL bSetSelected)
{
if (pUINode->IsContainer())
{
CUIFolderInfo* pParentInfo = pUINode->GetFolderInfo()->GetParentNode()->GetFolderInfo();
if (pParentInfo != NULL)
{
_AddScopeItem(pUINode, pParentInfo->GetScopeItem(), bSetSelected);
}
}
}
void CDSComponentData::AddListOfNodesToUI(CUINode* pUINode, CUINodeList* pNodeList)
{
CComPtr<IDataObject> spDataObj;
HRESULT hr = QueryDataObject ((MMC_COOKIE)pUINode, CCT_SCOPE, &spDataObj);
ASSERT(SUCCEEDED(hr));
// add the icon just in case
m_pFrame->UpdateAllViews(spDataObj, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
TIMER(_T("adding containers to scope pane\n"));
// the cookie is good, add all the cookies
for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
{
CUINode* pNewUINode = pNodeList->GetNext(pos);
pUINode->GetFolderInfo()->AddNode(pNewUINode); // add to the linked lists
if (pNewUINode->IsContainer())
{
// add to the scope pane
_AddScopeItem(pNewUINode, pUINode->GetFolderInfo()->GetScopeItem());
}
} // for
// for the leaf nodes, do a bulk update on the result pane
TIMER(_T("sending have-data notification to views\n"));
m_pFrame->UpdateAllViews(spDataObj, (LPARAM)pNodeList, DS_HAVE_DATA);
}
HRESULT CDSComponentData::ReadUINodeFromLdapPath(IN CDSUINode* pContainerDSUINode,
IN LPCWSTR lpszLdapPath,
OUT CDSUINode** ppSUINodeNew)
{
CDSCookie* pNewCookie = NULL;
HRESULT hr = GetActiveDS()->ReadDSObjectCookie(pContainerDSUINode,
lpszLdapPath,
&pNewCookie);
if (SUCCEEDED(hr) && (hr != S_FALSE) && (pNewCookie != NULL))
{
// make sure we update the icon cache
m_pFrame->UpdateAllViews(/*unused*/NULL /*pDataObj*/, /*unused*/(LPARAM)0, DS_ICON_STRIP_UPDATE);
// create a UI node to hold the cookie
*ppSUINodeNew = new CDSUINode(NULL);
(*ppSUINodeNew)->SetCookie(pNewCookie);
if (pNewCookie->IsContainerClass())
{
(*ppSUINodeNew)->MakeContainer();
}
}
return hr;
}
void CDSComponentData::_OnHaveData(CUINode* pUINode, CThreadQueryResult* pResult)
{
ASSERT(pUINode != NULL);
ASSERT(pUINode->IsContainer());
TRACE(_T("CDSComponentData::_OnHaveData()\n"));
if ( m_queryNodeTable.IsPresent(pUINode) && (pResult != NULL) )
{
AddListOfNodesToUI(pUINode, &(pResult->m_nodeList));
pResult->m_bOwnMemory = FALSE; // relinquish ownership of pointers
}
if (m_RootNode.GetFolderInfo()->GetObjectCount() > (m_pQueryFilter->GetMaxItemCount() * 5)) {
ReclaimCookies();
}
if (pResult != NULL)
{
delete pResult;
}
}
void CDSComponentData::_OnDone(CUINode* pUINode, HRESULT hr)
{
ASSERT(pUINode != NULL);
ASSERT(pUINode->IsContainer());
if (!m_queryNodeTable.Remove(pUINode))
return; // cookie not found, node not there anymore
// change the icon state
pUINode->SetExtOp(SUCCEEDED(hr) ? 0 : OPCODE_ENUM_FAILED);
VERIFY(SUCCEEDED(ChangeScopeItemIcon(pUINode)));
m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_VERB_UPDATE);
// update serial number
pUINode->GetFolderInfo()->UpdateSerialNumber(this);
TIMER(_T("got on-done notification\n"));
if (SUCCEEDED(hr))
{
if (pUINode->GetExtOp() & OPCODE_EXPAND_IN_PROGRESS) {
m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_DELAYED_EXPAND);
}
}
else if (m_InitSuccess)
{
if (IS_CLASS(*pUINode, CSavedQueryNode))
{
CSavedQueryNode* pQueryNode = dynamic_cast<CSavedQueryNode*>(pUINode);
if (pQueryNode != NULL)
{
if (HRESULT_CODE(hr) == ERROR_DS_FILTER_UNKNOWN)
{
//
// Error message for an invalid query filter
//
PVOID apv[2] = {(PVOID)pQueryNode->GetQueryString()};
ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_FILTER_NOT_VALID, hr,
MB_OK | MB_ICONERROR, apv, 1);
}
else if (HRESULT_CODE(hr) == ERROR_DS_NO_SUCH_OBJECT)
{
//
// Error message for an invalid query root
//
PVOID apv[2] = {(PVOID)pQueryNode->GetRootPath(),
(PVOID)GetBasePathsInfo()->GetServerName()};
ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_ROOT_NOT_VALID, hr,
MB_OK | MB_ICONERROR, apv, 2);
}
else
{
//
// Error message for any other error
//
ReportErrorEx (m_hwnd,IDS_ERRMSG_QUERY_FAILED, hr,
MB_OK | MB_ICONERROR, NULL, 0);
}
}
}
else
{
PVOID apv[2] = {(PVOID)GetBasePathsInfo()->GetServerName(),
(PVOID)pUINode->GetName()};
ReportErrorEx (m_hwnd,IDS_12_CANT_GET_DATA, hr,
MB_OK | MB_ICONERROR, apv, 2);
}
}
SortResultPane(pUINode);
}
void CDSComponentData::_OnSheetClose(CUINode* /*pUINode*/)
{
/*
ASSERT(pUINode != NULL);
// REVIEW_MARCOC_PORT: sheet locking is skipped for
// DS nodes, because we let them float
CDSUINode* pDSUINode = dynamic_cast<CDSUINode*>(pUINode);
if (pDSUINode != NULL)
{
return;
}
// not a DS object, need too do the usual thing
_SheetUnlockCookie(pUINode);
*/
}
HRESULT CreateSecondarySheet(HWND hWndParent,
LPCONSOLE pIConsole,
IUnknown* pUnkComponentData,
CDSUINode* pCookie,
IDataObject* pDataObject,
LPCWSTR lpszTitle)
{
ASSERT(pIConsole != NULL);
ASSERT(pDataObject != NULL);
ASSERT(pUnkComponentData != NULL);
// get an interface to a sheet provider
CComPtr<IPropertySheetProvider> spSheetProvider;
HRESULT hr = pIConsole->QueryInterface(IID_IPropertySheetProvider,(void**)&spSheetProvider);
ASSERT(SUCCEEDED(hr));
ASSERT(spSheetProvider != NULL);
// get an interface to a sheet callback
CComPtr<IPropertySheetCallback> spSheetCallback;
hr = pIConsole->QueryInterface(IID_IPropertySheetCallback,(void**)&spSheetCallback);
ASSERT(SUCCEEDED(hr));
ASSERT(spSheetCallback != NULL);
ASSERT(pDataObject != NULL);
// get a sheet
MMC_COOKIE cookie = reinterpret_cast<MMC_COOKIE>(pCookie);
hr = spSheetProvider->CreatePropertySheet(lpszTitle, TRUE, cookie,
pDataObject, 0x0 /*dwOptions*/);
ASSERT(SUCCEEDED(hr));
hr = spSheetProvider->AddPrimaryPages(pUnkComponentData,
FALSE /*bCreateHandle*/,
hWndParent,
FALSE /* bScopePane*/);
hr = spSheetProvider->AddExtensionPages();
ASSERT(SUCCEEDED(hr));
hr = spSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWndParent), 0);
ASSERT(SUCCEEDED(hr));
return hr;
}
void CDSComponentData::_OnSheetCreate(PDSA_SEC_PAGE_INFO pDsaSecondaryPageInfo)
{
ASSERT(pDsaSecondaryPageInfo != NULL);
//
// get the info from the packed structure
//
HWND hwndParent = pDsaSecondaryPageInfo->hwndParentSheet;
LPCWSTR lpszTitle = (LPCWSTR)((BYTE*)pDsaSecondaryPageInfo + pDsaSecondaryPageInfo->offsetTitle);
DSOBJECTNAMES* pDsObjectNames = &(pDsaSecondaryPageInfo->dsObjectNames);
ASSERT(pDsObjectNames->cItems == 1);
DSOBJECT* pDsObject = &(pDsObjectNames->aObjects[0]);
LPCWSTR lpszName = (LPCWSTR)((BYTE*)pDsObject + pDsObject->offsetName);
LPCWSTR lpszClass = (LPCWSTR)((BYTE*)pDsObject + pDsObject->offsetClass);
CDSUINode* pDSUINode = 0;
CDSCookie* pNewCookie = 0;
try
{
//
// Create a node and cookie
//
pDSUINode = new CDSUINode(NULL);
if (!pDSUINode)
{
return;
}
pNewCookie = new CDSCookie();
if (!pNewCookie)
{
delete pDSUINode;
pDSUINode = 0;
return;
}
}
catch(CMemoryException *)
{
if (pDSUINode)
{
delete pDSUINode;
pDSUINode = 0;
}
if (pNewCookie)
{
delete pNewCookie;
pNewCookie = 0;
}
return;
}
//
// get the DN out of the LDAP path
//
CString szLdapPath = lpszName;
CString szDN;
StripADsIPath(szLdapPath, szDN);
pNewCookie->SetPath(szDN);
CDSClassCacheItemBase* pItem = m_pClassCache->FindClassCacheItem(this, lpszClass, szLdapPath);
ASSERT(pItem != NULL);
if (pItem == NULL)
{
delete pDSUINode;
pDSUINode = 0;
delete pNewCookie;
pNewCookie = 0;
return;
}
pNewCookie->SetCacheItem(pItem);
//
// Set the cookie in the node (from now on the node owns the cookie and its memory
//
pDSUINode->SetCookie(pNewCookie);
if (pNewCookie->IsContainerClass())
{
pDSUINode->MakeContainer();
}
//
// with the cookie, can call into ourselves to get a data object
//
CComPtr<IDataObject> spDataObject;
MMC_COOKIE cookie = reinterpret_cast<MMC_COOKIE>(pDSUINode);
HRESULT hr = QueryDataObject(cookie, CCT_UNINITIALIZED, &spDataObject);
if (FAILED(hr) || (spDataObject == NULL) || IsSheetAlreadyUp(spDataObject))
{
//
// we failed to create a data object (rare)
// or the sheet is already up
//
delete pDSUINode;
pDSUINode = 0;
return;
}
//
// Pass the parent sheet handle to the data object.
//
PROPSHEETCFG SheetCfg = {0};
SheetCfg.hwndParentSheet = hwndParent;
FORMATETC fe = {CDSDataObject::m_cfPropSheetCfg, NULL, DVASPECT_CONTENT,
-1, TYMED_HGLOBAL};
STGMEDIUM sm = {TYMED_HGLOBAL, NULL, NULL};
sm.hGlobal = (HGLOBAL)&SheetCfg;
hr = spDataObject->SetData(&fe, &sm, FALSE);
ASSERT(SUCCEEDED(hr));
//
// with the data object, call into MMC to get the sheet
//
hr = CreateSecondarySheet(GetHWnd(),
m_pFrame,
GetUnknown(),
pDSUINode,
spDataObject,
lpszTitle);
delete pDSUINode;
}
HRESULT CDSComponentData::SelectScopeNode(CUINode* pUINode)
{
if (!pUINode->IsContainer())
{
ASSERT(pUINode->IsContainer());
return E_INVALIDARG;
}
return m_pFrame->SelectScopeItem(pUINode->GetFolderInfo()->GetScopeItem());
}
void CDSComponentData::SortResultPane(CUINode* pUINode)
{
if(pUINode != NULL)
m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_SORT_RESULT_PANE);
}
HRESULT
CDSComponentData::QueryFromWorkerThread(CThreadQueryInfo* pQueryInfo,
CWorkerThread* pWorkerThread)
{
HRESULT hr = S_OK;
if (!m_InitSuccess)
return E_FAIL;
//if (IDYES == ::MessageBox (NULL, L"Fail Query ?", L"DS Admin", MB_YESNO))
//{
// return E_FAIL;
//}
// function called in the context of a worker thread
if (IS_CLASS(*pQueryInfo, CDSThreadQueryInfo))
{
CDSThreadQueryInfo* pDSQueryInfo = dynamic_cast<CDSThreadQueryInfo*>(pQueryInfo);
if (pDSQueryInfo != NULL)
{
ASSERT(pDSQueryInfo->GetType() != unk);
if (pDSQueryInfo->GetType() == rootFolder)
{
hr = m_ActiveDS->EnumerateRootContainer(pDSQueryInfo, pWorkerThread);
}
else if ((pDSQueryInfo->GetType() == dsFolder) || (pDSQueryInfo->GetType() == queryFolder))
{
hr = m_ActiveDS->EnumerateContainer(pDSQueryInfo, pWorkerThread);
}
}
else
{
TRACE(_T("Failed to dynamically cast to CDSThreadQueryInfo in CDSComponentData::QueryFromWorkerThread()"));
ASSERT(FALSE);
hr = E_OUTOFMEMORY;
}
}
return hr;
}
BOOL CDSComponentData::CanEnableVerb(CUINode* pUINode)
{
return !m_queryNodeTable.IsLocked(pUINode);
}
int CDSComponentData::GetImage(CUINode* pNode, BOOL bOpen)
{
ASSERT(pNode != NULL);
int imageIndex = -1;
if (m_queryNodeTable.IsPresent(pNode))
{
// executing a query, same icon across the board
imageIndex = m_iconManager.GetWaitIndex();
}
else if (pNode->GetExtOp() & OPCODE_ENUM_FAILED)
{
// error condition
if (pNode == GetRootNode())
imageIndex = m_iconManager.GetRootErrIndex();
else
imageIndex = m_iconManager.GetWarnIndex();
}
else
{
// normal state icon for the cookie
if (pNode == GetRootNode())
{
// this is the root
imageIndex = m_iconManager.GetRootIndex();
}
else if (IS_CLASS(*pNode, CFavoritesNode))
{
imageIndex = m_iconManager.GetFavoritesIndex();
}
else if (IS_CLASS(*pNode, CSavedQueryNode))
{
CSavedQueryNode* pSavedQueryNode = dynamic_cast<CSavedQueryNode*>(pNode);
if (pSavedQueryNode->IsValid())
{
imageIndex = m_iconManager.GetQueryIndex();
}
else
{
imageIndex = m_iconManager.GetQueryInvalidIndex();
}
}
else
{
imageIndex = pNode->GetImage(bOpen);
}
}
TRACE(_T("CDSComponentData::GetImage() returning: %d\n"), imageIndex);
return imageIndex;
}
void CDSComponentData::_SheetLockCookie(CUINode* pNode)
{
pNode->IncrementSheetLockCount();
m_sheetNodeTable.Add(pNode);
}
void CDSComponentData::_SheetUnlockCookie(CUINode* pNode)
{
pNode->DecrementSheetLockCount();
m_sheetNodeTable.Remove(pNode);
}
BOOL CDSComponentData::_WarningOnSheetsUp(CUINode* pNode, BOOL bShowMessage, BOOL bActivate)
{
if (!pNode->IsSheetLocked())
return FALSE; // no warning, all is cool
if (bShowMessage)
{
// warning to user that oeration cannot be performed
ReportErrorEx (m_hwnd,IDS_SHEETS_UP_DELETE,S_OK,
MB_OK | MB_ICONINFORMATION, NULL, 0);
}
// need to bring sheets on the foreground and activate it
m_sheetNodeTable.BringToForeground(pNode, this, bActivate);
return TRUE;
}
BOOL CDSComponentData::_WarningOnSheetsUp(CInternalFormatCracker* pInternalFormatCracker)
{
ASSERT(pInternalFormatCracker != NULL);
if (!pInternalFormatCracker->HasData())
{
return FALSE;
}
UINT cCookieTotalCount = pInternalFormatCracker->GetCookieCount();
//
// protect against operations with sheets up
//
BOOL bStop = FALSE;
BOOL bFirstOne = TRUE;
for (UINT cCount=0; cCount < cCookieTotalCount; cCount++)
{
CUINode* pUINode = pInternalFormatCracker->GetCookie(cCount);
if (_WarningOnSheetsUp(pUINode, bFirstOne, bFirstOne))
{
bStop = TRUE;
bFirstOne = FALSE;
}
} // for
return bStop;
}
HRESULT CDSComponentData::ColumnsChanged(CDSEvent* pDSEvent, CUINode* pUINode,
MMC_VISIBLE_COLUMNS* pVisibleColumns, BOOL bRefresh)
{
ASSERT(pUINode != NULL);
ASSERT(pUINode->IsContainer());
if (bRefresh && m_RootNode.IsSheetLocked())
{
// warning to user that oeration cannot be performed
ReportErrorEx (m_hwnd,IDS_SHEETS_UP_COLUMNS_CHANGED,S_OK,
MB_OK | MB_ICONINFORMATION, NULL, 0);
// need to bring sheets on the foreground and activate it
m_sheetNodeTable.BringToForeground(&m_RootNode, this, TRUE);
// tell MMC to discard the column changes
return E_UNEXPECTED;
}
CDSColumnSet* pColumnSet = pUINode->GetColumnSet(this);
pColumnSet->ClearVisibleColumns();
if (pVisibleColumns != NULL)
{
ASSERT(pDSEvent != NULL);
pDSEvent->SetUpdateAllViewsOrigin(TRUE);
pColumnSet->AddVisibleColumns(pVisibleColumns);
// set the dirty flag, need to save to stream to be in sync
m_bDirty = TRUE;
}
m_pFrame->UpdateAllViews(NULL, (LPARAM)pUINode, DS_UPDATE_VISIBLE_COLUMNS);
if (pDSEvent != NULL)
pDSEvent->SetUpdateAllViewsOrigin(FALSE);
if (IS_CLASS(*pUINode, CSavedQueryNode))
{
Refresh(pUINode);
}
else
{
if (bRefresh)
{
ASSERT(!m_RootNode.IsSheetLocked());
::PostMessage(m_pHiddenWnd->m_hWnd, CHiddenWnd::s_RefreshAllNotificationMessage, 0, 0);
}
}
return S_OK;
}
void CDSComponentData::ForceRefreshAll()
{
m_bDirty = TRUE;
RefreshAll();
}
HRESULT CDSComponentData::SetRenameMode(CUINode* pUINode)
{
HRESULT hr = S_OK;
if (pUINode->IsContainer())
{
CUIFolderInfo* pFolderInfo = pUINode->GetFolderInfo();
hr = m_pFrame->RenameScopeItem(pFolderInfo->GetScopeItem());
}
else
{
//
// REVIEW_JEFFJON : Codework to implement for result pane items
// Need to do an UpdateAllViews with new message and handler
//
}
return hr;
}
/////////////////////////////////////////////////////////////////////
// functionality for snapin CoClasses
SnapinType CDSSnapin::QuerySnapinType() {return SNAPINTYPE_DS;}
SnapinType CDSSnapinEx::QuerySnapinType() {return SNAPINTYPE_DSEX;}
SnapinType CSiteSnapin::QuerySnapinType() {return SNAPINTYPE_SITE;}
int ResourceIDForSnapinType[SNAPINTYPE_NUMTYPES] =
{
IDS_DSSNAPINNAME,
IDS_DS_MANAGER_EX,
IDS_SITESNAPINNAME
};
/////////////////////////////////////////////////////////////////////
// CDSSnapin (DS standalone)
CDSSnapin::CDSSnapin()
{
m_lpszSnapinHelpFile = L"dsadmin.chm";
}
/////////////////////////////////////////////////////////////////////
// CDSSnapinEx (DS namespace extension)
CDSSnapinEx::CDSSnapinEx()
{
m_bRunAsPrimarySnapin = FALSE;
m_bAddRootWhenExtended = TRUE;
m_lpszSnapinHelpFile = L"dsadmin.chm";
}
/////////////////////////////////////////////////////////////////////
// CSiteSnapin (Site manager standalone)
CSiteSnapin::CSiteSnapin()
{
m_lpszSnapinHelpFile = L"dssite.chm";
}
//////////////////////////////////////////////////////////////////////////
// CDSSnapinAbout
CDSSnapinAbout::CDSSnapinAbout()
{
m_uIdStrProvider = IDS_SNAPIN_PROVIDER;
m_uIdStrVersion = IDS_SNAPIN_VERSION;
m_uIdStrDestription = IDS_SNAPINABOUT_DESCRIPTION;
m_uIdIconImage = IDI_DSADMIN;
m_uIdBitmapSmallImage = IDB_DSADMIN;
m_uIdBitmapSmallImageOpen = IDB_DSADMIN;
m_uIdBitmapLargeImage = IDB_DSADMIN_LG;
m_crImageMask = RGB(255,0,255);
}
//////////////////////////////////////////////////////////////////////////
// CDSSnapinAbout
CSitesSnapinAbout::CSitesSnapinAbout()
{
m_uIdStrProvider = IDS_SNAPIN_PROVIDER;
m_uIdStrVersion = IDS_SNAPIN_VERSION;
m_uIdStrDestription = IDS_SITES_SNAPINABOUT_DESCRIPTION;
m_uIdIconImage = IDI_SITEREPL;
m_uIdBitmapSmallImage = IDB_SITEREPL;
m_uIdBitmapSmallImageOpen = IDB_SITEREPL;
m_uIdBitmapLargeImage = IDB_SITEREPL_LG;
m_crImageMask = RGB(255,0,255);
}