|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: cdomain.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
//#include "afxdlgs.h"
#include <lm.h>
#include "activeds.h"
#include <dnsapi.h> // for DnsFlushResolverCache()
#include "domobj.h"
#include "Cdomain.h"
#include "DataObj.h"
#include "notify.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#define DOMADMIN_LINKED_HELP_FILE L"ADconcepts.chm"
#define DOMADMIN_SNAPIN_HELP_FILE L"domadmin.chm"
int _MessageBox(HWND hWnd, // handle to owner window
LPCTSTR lpText, // pointer to text in message box
UINT uType); // style of message box
/////////////////////////////////////////////////////////////////////////////
// macros
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
/////////////////////////////////////////////////////////////////////////////
// constants
// {19B9A3F8-F975-11d1-97AD-00A0C9A06D2D}
static const GUID CLSID_DomainSnapinAbout = { 0x19b9a3f8, 0xf975, 0x11d1, { 0x97, 0xad, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x2d } };
const CLSID CLSID_DomainAdmin = { /* ebc53a38-a23f-11d0-b09b-00c04fd8dca6 */ 0xebc53a38, 0xa23f, 0x11d0, {0xb0, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xdc, 0xa6} };
const GUID cDefaultNodeType = { /* 4c06495e-a241-11d0-b09b-00c04fd8dca6 */ 0x4c06495e, 0xa241, 0x11d0, {0xb0, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xdc, 0xa6} };
const wchar_t* cszDefaultNodeType = _T("4c06495e-a241-11d0-b09b-00c04fd8dca6");
// Internal private format
const wchar_t* CCF_DS_DOMAIN_TREE_SNAPIN_INTERNAL = L"DS_DOMAIN_TREE_SNAPIN_INTERNAL";
/////////////////////////////////////////////////////////////////////////////
// global functions
//forward decl
void PrintColumn( PADS_SEARCH_COLUMN pColumn, LPWSTR pszColumnName );
BOOL IsMMCMultiSelectDataObject(IDataObject* pDataObject) { if (pDataObject == NULL) return FALSE;
static UINT s_cf = 0; if (s_cf == 0) { USES_CONVERSION; s_cf = RegisterClipboardFormat(W2T(CCF_MMC_MULTISELECT_DATAOBJECT)); }
FORMATETC fmt = {(CLIPFORMAT)s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return (pDataObject->QueryGetData(&fmt) == S_OK); }
#define NEXT_HELP_TABLE_ENTRY(p) ((p)+2)
#define TABLE_ENTRY_CTRL_ID(p) (*p)
#define TABLE_ENTRY_HELP_ID(p) (*(p+1))
#define IS_LAST_TABLE_ENTRY(p) (TABLE_ENTRY_CTRL_ID(p) == 0)
BOOL FindDialogContextTopic(/*IN*/ DWORD* pTable, /*IN*/ HELPINFO* pHelpInfo, /*OUT*/ ULONG* pnContextTopic) { ASSERT(pHelpInfo != NULL); *pnContextTopic = 0;
// look inside the table
while (!IS_LAST_TABLE_ENTRY(pTable)) { if (TABLE_ENTRY_CTRL_ID(pTable) == (DWORD)pHelpInfo->iCtrlId) { *pnContextTopic = TABLE_ENTRY_HELP_ID(pTable); return TRUE; } pTable = NEXT_HELP_TABLE_ENTRY(pTable); } return FALSE; }
void DialogContextHelp(DWORD* pTable, HELPINFO* pHelpInfo) { ULONG nContextTopic; if (FindDialogContextTopic(pTable, pHelpInfo, &nContextTopic)) { CString szHelpFilePath; LPTSTR lpszBuffer = szHelpFilePath.GetBuffer(2*MAX_PATH+1); UINT nLen = ::GetSystemWindowsDirectory(lpszBuffer, 2*MAX_PATH); if (nLen == 0) return; // NOTICE-2002/03/07-ericb - SecurityPush: using wcsncpy now. GetBuffer above null terminates the buffer.
wcsncpy(&lpszBuffer[nLen], L"\\HELP\\DOMADMIN.HLP", 2*MAX_PATH - nLen); szHelpFilePath.ReleaseBuffer(); ::WinHelp((HWND) pHelpInfo->hItemHandle, szHelpFilePath, HELP_CONTEXTPOPUP, nContextTopic); } }
LPCWSTR GetServerNameFromCommandLine() { const WCHAR szOverrideSrvCommandLine[] = L"/Server="; // Not subject to localization
const int cchOverrideSrvCommandLine = (sizeof(szOverrideSrvCommandLine)/sizeof(WCHAR)) - 1; static CString g_strOverrideServerName;
// retrieve the command line arguments
LPCWSTR* lpServiceArgVectors; // Array of pointers to string
int cArgs = 0; // Count of arguments
lpServiceArgVectors = (LPCWSTR *)CommandLineToArgvW(GetCommandLineW(), OUT &cArgs); if (lpServiceArgVectors == NULL) { return NULL; }
CString str; for (int i = 1; i < cArgs; i++) { ASSERT(lpServiceArgVectors[i] != NULL); str = lpServiceArgVectors[i]; // Copy the string
TRACE (_T("command line arg: %s\n"), lpServiceArgVectors[i]); str = str.Left(cchOverrideSrvCommandLine); if (str.CompareNoCase(szOverrideSrvCommandLine) == 0) { g_strOverrideServerName = lpServiceArgVectors[i] + cchOverrideSrvCommandLine; break; }
} // for
LocalFree(lpServiceArgVectors); TRACE(L"GetServerNameFromCommandLine() returning <%s>\n", (LPCWSTR)g_strOverrideServerName); return g_strOverrideServerName.IsEmpty() ? NULL : (LPCWSTR)g_strOverrideServerName; }
/////////////////////////////////////////////////////////////////////////////
// CInternalFormatCracker
BOOL CInternalFormatCracker::Extract(LPDATAOBJECT lpDataObject) { if (m_pInternalFormat != NULL) { FREE_INTERNAL(m_pInternalFormat); m_pInternalFormat = NULL; } if (lpDataObject == NULL) return FALSE;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)CDataObject::m_cfInternal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// Allocate memory for the stream
stgmedium.hGlobal = ::GlobalAlloc(GMEM_SHARE, sizeof(INTERNAL));
// Attempt to get data from the object
do { if (stgmedium.hGlobal == NULL) break;
if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium))) break;
m_pInternalFormat = reinterpret_cast<INTERNAL*>(stgmedium.hGlobal); if (m_pInternalFormat == NULL) return FALSE;
} while (FALSE);
return TRUE; }
BOOL CInternalFormatCracker::GetContext(LPDATAOBJECT pDataObject, // input
CFolderObject** ppFolderObject, // output
DATA_OBJECT_TYPES* pType // output
) { *ppFolderObject = NULL; *pType = CCT_UNINITIALIZED;
BOOL bRet = FALSE; if (!Extract(pDataObject)) return bRet; // have to figure out which kind of cookie we have
if ( (GetInternal()->m_type == CCT_RESULT) || (GetInternal()->m_type == CCT_SCOPE) ) { if (GetInternal()->m_cookie == 0) { // this is the root
*ppFolderObject = m_pCD->GetRootFolder(); bRet = TRUE; } else { // regular cookie (scope or result pane)
*ppFolderObject = reinterpret_cast<CFolderObject*>(GetInternal()->m_cookie); _ASSERTE(*ppFolderObject != NULL); *pType = GetInternal()->m_type; bRet = TRUE; } } else if (GetInternal()->m_type == CCT_UNINITIALIZED) { // no data in the object, just ignore
if(GetInternal()->m_cookie == -1) { bRet = TRUE; } else { // secondary page cookie
*ppFolderObject = reinterpret_cast<CFolderObject*>(GetInternal()->m_cookie); bRet = TRUE; } } else //CCT_SNAPIN_MANAGER
{ ASSERT(GetInternal()->m_type == CCT_SNAPIN_MANAGER); bRet = TRUE; *pType = GetInternal()->m_type; } return bRet; }
///////////////////////////////////////////////////////////////////////////////
////////////////////////// CComponentDataImpl (i.e. scope pane side) //////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// IComponentData implementation
DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
CComponentDataImpl::CComponentDataImpl() : m_rootFolder(this) { DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
m_bInitSuccess = FALSE;
m_hDomainIcon = NULL; m_pConsoleNameSpace = NULL; m_pConsole = NULL;
/* HACK WARNING: 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"); } }
}
HRESULT CComponentDataImpl::FinalConstruct() { // create and initialize hidden window
m_pHiddenWnd = new CHiddenWnd(this);
ASSERT(m_pHiddenWnd); if (!m_pHiddenWnd->Create()) { TRACE(_T("Failed to create hidden window\n")); ASSERT(FALSE); } return S_OK; }
CComponentDataImpl::~CComponentDataImpl() { DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
ASSERT(m_pConsoleNameSpace == NULL); }
void CComponentDataImpl::FinalRelease() { _DeleteHiddenWnd(); }
STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown) { ASSERT(pUnknown != NULL); HRESULT hr;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// MMC should only call ::Initialize once!
ASSERT(m_pConsoleNameSpace == NULL); pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast<void**>(&m_pConsoleNameSpace));
// add the images for the scope tree
CBitmap bmp16x16; LPIMAGELIST lpScopeImage;
hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole)); ASSERT(hr == S_OK); if (FAILED(hr)) { return hr; }
hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
ASSERT(hr == S_OK); if (FAILED(hr)) { return hr; }
// Load the bitmaps from the dll
bmp16x16.LoadBitmap(IDB_DOMAIN_SMALL);
// Set the images
lpScopeImage->ImageListSetStrip(reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)), reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)), 0, RGB(128, 0, 0));
lpScopeImage->Release();
// bind to the path info
hr = GetBasePathsInfo()->InitFromName(GetServerNameFromCommandLine()); m_bInitSuccess = SUCCEEDED(hr); if (FAILED(hr)) { HWND hWndParent; GetMainWindow(&hWndParent); ReportError(hWndParent, IDS_CANT_GET_PARTITIONS_INFORMATION, hr); // TODO: error handling, change icon
}
return S_OK; }
HWND CComponentDataImpl::GetHiddenWindow() { ASSERT(m_pHiddenWnd != NULL); ASSERT(::IsWindow(m_pHiddenWnd->m_hWnd)); return m_pHiddenWnd->m_hWnd; }
void CComponentDataImpl::_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; }
STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent) { ASSERT(ppComponent != NULL);
CComObject<CComponentImpl>* pObject; HRESULT hr = CComObject<CComponentImpl>::CreateInstance(&pObject);
if (FAILED(hr)) { ASSERT(FALSE && "CComObject<CComponentImpl>::CreateInstance(&pObject) failed"); return hr; }
ASSERT(pObject != NULL);
// Store IComponentData
pObject->SetIComponentData(this);
return pObject->QueryInterface(IID_IComponent, reinterpret_cast<void**>(ppComponent)); }
STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { ASSERT(m_pConsoleNameSpace != NULL); HRESULT hr = S_OK;
// 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 (event == MMCN_PROPERTY_CHANGE) { hr = OnPropertyChange(param); } else { if (lpDataObject == NULL) return S_OK;
CFolderObject* pFolderObject = NULL; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if (!dobjCracker.GetContext(lpDataObject, &pFolderObject, &type)) { // Extensions not supported.
ASSERT(FALSE); return S_OK; }
switch(event) { case MMCN_EXPAND: hr = OnExpand(pFolderObject, arg, param); break; case MMCN_REFRESH: OnRefreshVerbHandler(pFolderObject, NULL); break; default: break; }
}
return hr; }
STDMETHODIMP CComponentDataImpl::Destroy() {
SAFE_RELEASE(m_pConsoleNameSpace); SAFE_RELEASE(m_pConsole);
return S_OK; }
STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { ASSERT(ppDataObject != NULL); if (ppDataObject == NULL) return E_INVALIDARG;
// create data object
CComObject<CDataObject>* pObject = NULL; CComObject<CDataObject>::CreateInstance(&pObject); ASSERT(pObject != NULL); if ( !pObject ) return E_OUTOFMEMORY;
// Save cookie and type for delayed rendering
pObject->SetType(type); pObject->SetCookie(cookie); // set pointer to IComponentData
pObject->SetIComponentData(this);
if (cookie != NULL) { // object is not the root
CDomainObject * pDomain = (CDomainObject *)cookie; pObject->SetClass( pDomain->GetClass()); }
return pObject->QueryInterface(IID_IDataObject, reinterpret_cast<void**>(ppDataObject)); }
///////////////////////////////////////////////////////////////////////////////
//// Notify handlers for IComponentData
HRESULT CComponentDataImpl::OnExpand(CFolderObject* pFolderObject, LPARAM arg, LPARAM param) { if (arg == TRUE) { // Did Initialize get called?
ASSERT(m_pConsoleNameSpace != NULL); EnumerateScopePane(pFolderObject, param); }
return S_OK; }
HRESULT CComponentDataImpl::OnPropertyChange(LPARAM param) { return S_OK; }
void CComponentDataImpl::EnumerateScopePane(CFolderObject* pFolderObject, HSCOPEITEM pParent) { ASSERT(m_pConsoleNameSpace != NULL); // make sure we QI'ed for the interface
HRESULT hr = S_OK; HWND hWndParent; GetMainWindow(&hWndParent);
AFX_MANAGE_STATE(AfxGetStaticModuleState()); CWaitCursor cWait;
CRootFolderObject* pRootFolder = GetRootFolder(); if (pFolderObject == pRootFolder) // asked to enumerate the root
{ pRootFolder->SetScopeID(pParent); if (m_bInitSuccess && (!pRootFolder->HasData())) { hr = GetDsDisplaySpecOptionsCFHolder()->Init(GetBasePathsInfo()); ASSERT(SUCCEEDED(hr)); hr = pRootFolder->Bind(); if (FAILED(hr)) { ReportError(hWndParent, IDS_CANT_GET_PARTITIONS_INFORMATION, hr); // TODO: error handling, change icon
return; }
hr = pRootFolder->GetData(); if (FAILED(hr)) { ReportError(hWndParent, IDS_CANT_GET_PARTITIONS_INFORMATION, hr); return; } } pRootFolder->EnumerateRootFolder(this); } else // asked to enumerate a subfolder of the root
{ if (pRootFolder->HasData()) { pRootFolder->EnumerateFolder(pFolderObject, pParent, this); } } }
STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem) { ASSERT(pScopeDataItem != NULL); if (pScopeDataItem == NULL) return E_POINTER;
CDomainObject* pDomain = reinterpret_cast<CDomainObject*>(pScopeDataItem->lParam);
ASSERT(pScopeDataItem->mask & SDI_STR); pScopeDataItem->displayname = (LPWSTR)pDomain->GetDisplayString(0);
ASSERT(pScopeDataItem->displayname != NULL);
return S_OK; }
class CCompareDomainObjectByDN { public: CCompareDomainObjectByDN(LPCWSTR lpszDN) { m_lpszDN = lpszDN;}
bool operator()(CDomainObject* p) { // NOTICE-2002/03/07-ericb - SecurityPush: checking both strings for null before dereferencing.
if (!m_lpszDN || !p || !p->GetNCName()) { ASSERT(m_lpszDN); ASSERT(p); ASSERT(p->GetNCName()); return false; } return (_wcsicmp(m_lpszDN, p->GetNCName()) == 0); } private: LPCWSTR m_lpszDN; };
STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { if (lpDataObjectA == NULL || lpDataObjectB == NULL) return E_POINTER;
CFolderObject *pFolderObjectA, *pFolderObjectB; DATA_OBJECT_TYPES typeA, typeB; CInternalFormatCracker dobjCrackerA(this), dobjCrackerB(this); if ( (!dobjCrackerA.GetContext(lpDataObjectA, &pFolderObjectA, &typeA)) || (!dobjCrackerB.GetContext(lpDataObjectB, &pFolderObjectB, &typeB)) ) return E_INVALIDARG; // something went wrong
// must have valid cookies
if ( (pFolderObjectA == NULL) || (pFolderObjectB == NULL) ) { return S_FALSE; } if (pFolderObjectA == pFolderObjectB) { // same pointer, they are the same (either both from real nodes
// or both from secondary pages)
return S_OK; }
// the two cookies are different, but one of them might be from a secondary property page
// and another from a real node
CDomainObject* pA = dynamic_cast<CDomainObject*>(pFolderObjectA); CDomainObject* pB = dynamic_cast<CDomainObject*>(pFolderObjectB);
if ((pA == NULL) || (pB == NULL)) { return S_FALSE; }
BOOL bSecondaryA = m_secondaryPagesManager.IsCookiePresent(pA); BOOL bSecondaryB = m_secondaryPagesManager.IsCookiePresent(pB);
BOOL bTheSame = FALSE; if (bSecondaryA && !bSecondaryB) { bTheSame = m_secondaryPagesManager.FindCookie(CCompareDomainObjectByDN(pB->GetNCName())) != NULL; } else if (!bSecondaryA && bSecondaryB) { bTheSame = m_secondaryPagesManager.FindCookie(CCompareDomainObjectByDN(pA->GetNCName())) != NULL; }
return bTheSame ? S_OK : S_FALSE; }
HRESULT CComponentDataImpl::AddFolder(CFolderObject* pFolderObject, HSCOPEITEM pParentScopeItem, BOOL bHasChildren) { TRACE(L"CComponentDataImpl::AddFolder(%s)\n", pFolderObject->GetDisplayString(0));
SCOPEDATAITEM scopeItem; // NOTICE-2002/03/07-ericb - SecurityPush: zeroing a struct.
memset(&scopeItem, 0, sizeof(SCOPEDATAITEM));
// set parent scope item
scopeItem.mask |= SDI_PARENT; scopeItem.relativeID = pParentScopeItem;
// Add node name, we implement callback
scopeItem.mask |= SDI_STR; scopeItem.displayname = MMC_CALLBACK;
// Add the lParam
scopeItem.mask |= SDI_PARAM; scopeItem.lParam = reinterpret_cast<LPARAM>(pFolderObject); // Add close image
scopeItem.mask |= SDI_IMAGE; scopeItem.nImage = pFolderObject->GetImageIndex();
// Add open image
scopeItem.mask |= SDI_OPENIMAGE; scopeItem.nOpenImage = pFolderObject->GetImageIndex();
// Add button to node if the folder has children
if (bHasChildren == TRUE) { scopeItem.mask |= SDI_CHILDREN; scopeItem.cChildren = 1; }
pFolderObject->SetScopeID(0); HRESULT hr = m_pConsoleNameSpace->InsertItem(&scopeItem); if (SUCCEEDED(hr)) pFolderObject->SetScopeID(scopeItem.ID);
return hr; }
HRESULT CComponentDataImpl::AddDomainIcon() { if (m_hDomainIcon != NULL) return S_OK;
m_hDomainIcon = GetBasePathsInfo()->GetIcon(L"domainDNS", DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON, 0, 0); if (m_hDomainIcon == NULL) return S_OK;
LPIMAGELIST lpScopeImage; HRESULT hr = m_pConsole->QueryScopeImageList(&lpScopeImage); ASSERT(SUCCEEDED(hr)); if (FAILED(hr)) return hr; // Set the images
hr = lpScopeImage->ImageListSetIcon((LONG_PTR*)m_hDomainIcon,DOMAIN_IMAGE_IDX); lpScopeImage->Release(); return hr; }
HRESULT CComponentDataImpl::AddDomainIconToResultPane(LPIMAGELIST lpImageList) { if (m_hDomainIcon == NULL) return S_OK; return lpImageList->ImageListSetIcon((LONG_PTR*)m_hDomainIcon,DOMAIN_IMAGE_IDX); }
int CComponentDataImpl::GetDomainImageIndex() { return (m_hDomainIcon != NULL) ? DOMAIN_IMAGE_IDX : DOMAIN_IMAGE_DEFAULT_IDX; }
/////////////////////////////////////////////////////////////////////////////
// IExtendPropertySheet Implementation
//+----------------------------------------------------------------------------
//
// Function: AddPageProc
//
// Synopsis: The IShellPropSheetExt->AddPages callback.
//
//-----------------------------------------------------------------------------
BOOL CALLBACK AddPageProc(HPROPSHEETPAGE hPage, LPARAM pCall) { TRACE(_T("xx.%03x> AddPageProc()\n"), GetCurrentThreadId());
HRESULT hr;
hr = ((LPPROPERTYSHEETCALLBACK)pCall)->AddPage(hPage);
return hr == S_OK; } STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject) { TRACE(_T("xx.%03x> CComponentDataImpl::CreatePropertyPages()\n"), GetCurrentThreadId());
// Validate Inputs
if (lpProvider == NULL) { return E_INVALIDARG; }
AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; CWaitCursor wait;
CFolderObject* pFolderObject = NULL; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if ( (!dobjCracker.GetContext(lpIDataObject, &pFolderObject, &type)) || (pFolderObject == NULL)) return E_NOTIMPL; // unknown format
// special case the root
if (pFolderObject == GetRootFolder()) { return GetRootFolder()->OnAddPages(lpProvider, handle); }
// See if a sheet is already up for this object.
//
if (IsSheetAlreadyUp(lpIDataObject)) { return S_OK; }
if (pFolderObject->GetParentFolder() == GetRootFolder()) { TRACE(L"\t!!!!! This is the root domain\n"); }
// See if a PDC is available.
//
CDomainObject * pDomainObject = (CDomainObject *)pFolderObject;
PCWSTR wzDomain = pDomainObject->GetDomainName();
// If the domain name is null, then launching a secondary page. The domain
// object properties have already been set in _OnSheetCreate.
//
if (wzDomain && *wzDomain) { TRACE(L"Calling DsGetDcName on %s\n", wzDomain); CString strCachedPDC; PDOMAIN_CONTROLLER_INFOW pDCInfo = NULL;
// Get the cached PDC name for display later if the PDC can't be contacted.
//
DWORD dwRet = DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_PDC_REQUIRED, &pDCInfo);
int nID = IDS_NO_PDC_MSG;
if (ERROR_SUCCESS == dwRet) { strCachedPDC = pDCInfo->DomainControllerName + 2; NetApiBufferFree(pDCInfo); }
// Now do a NetLogon cache update (with the force flag) to see if the PDC
// is actually available.
//
dwRet = DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_PDC_REQUIRED | DS_FORCE_REDISCOVERY, &pDCInfo);
if (ERROR_SUCCESS == dwRet) { CString strPDC;
strPDC = pDCInfo->DomainControllerName + 2; // skip the UNC backslashes.
NetApiBufferFree(pDCInfo);
TRACE(L"PDC: %s\n", (PCWSTR)strPDC);
if (strPDC.IsEmpty()) { return E_OUTOFMEMORY; }
pDomainObject->SetPDC(strPDC);
pDomainObject->SetPdcAvailable(true); } else { pDomainObject->SetPdcAvailable(false);
CString strMsg;
if (strCachedPDC.IsEmpty()) { strMsg.LoadString(IDS_UNKNOWN_PDC_MSG); } else { strMsg.Format(IDS_NO_PDC_MSG, strCachedPDC); } HWND hWndParent; GetMainWindow(&hWndParent); _MessageBox(hWndParent, strMsg, MB_OK | MB_ICONEXCLAMATION); } }
//
// Pass the Notify Handle to the data object.
//
PROPSHEETCFG SheetCfg = {handle}; FORMATETC fe = {CDataObject::m_cfGetIPropSheetCfg, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM sm = {TYMED_HGLOBAL, NULL, NULL}; sm.hGlobal = (HGLOBAL)&SheetCfg;
lpIDataObject->SetData(&fe, &sm, FALSE);
//
// Initialize and create the pages.
//
// 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.
//
CComPtr<IShellExtInit> spShlInit; hr = CoCreateInstance(CLSID_DsPropertyPages, NULL, CLSCTX_INPROC_SERVER, IID_IShellExtInit, (void **)&spShlInit); if (FAILED(hr)) { TRACE(TEXT("CoCreateInstance on CLSID_DsPropertyPages failed, hr: 0x%x\n "), hr); return hr; }
hr = spShlInit->Initialize(NULL, lpIDataObject, 0);
if (FAILED(hr)) { TRACE(TEXT("spShlInit->Initialize failed, hr: 0x%x\n"), hr); return hr; }
CComPtr<IShellPropSheetExt> spSPSE;
hr = spShlInit->QueryInterface(IID_IShellPropSheetExt, (void **)&spSPSE);
if (FAILED(hr)) { TRACE(TEXT("spShlInit->QI for IID_IShellPropSheetExt failed, hr: 0x%x\n"), hr); return hr; }
hr = spSPSE->AddPages(AddPageProc, (LONG_PTR)lpProvider);
if (FAILED(hr)) { TRACE(TEXT("pSPSE->AddPages failed, hr: 0x%x\n"), hr); return hr; }
_SheetLockCookie(pFolderObject);
return hr; }
// Sheet locking and unlocking add by JEFFJON 1/26/99
//
void CComponentDataImpl::_OnSheetClose(CFolderObject* pCookie) { ASSERT(pCookie != NULL); _SheetUnlockCookie(pCookie);
CDomainObject* pDomObj = dynamic_cast<CDomainObject*>(pCookie); if (pDomObj != NULL) m_secondaryPagesManager.OnSheetClose(pDomObj); }
void CComponentDataImpl::_OnSheetCreate(PDSA_SEC_PAGE_INFO pDsaSecondaryPageInfo, PWSTR pwzDC) { 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); // with the given info, create a cookie and set it
CDomainObject* pNewCookie = new CDomainObject(); pNewCookie->InitializeForSecondaryPage(lpszName, lpszClass, GetDomainImageIndex());
// The parent sheet will be in read-only mode if a PDC is not available.
pNewCookie->SetPdcAvailable(!(pDsObject->dwFlags & DSOBJECT_READONLYPAGES));
if (pwzDC && !IsBadReadPtr(pwzDC, sizeof(PWSTR))) { pNewCookie->SetPDC(pwzDC); }
// with the cookie, can call into ourselves to get a data object
CComPtr<IDataObject> spDataObject; MMC_COOKIE cookie = reinterpret_cast<MMC_COOKIE>(pNewCookie); 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 pNewCookie; return; }
//
// Pass the parent sheet handle to the data object.
//
PROPSHEETCFG SheetCfg = {0}; SheetCfg.hwndParentSheet = hwndParent; FORMATETC fe = {CDataObject::m_cfGetIPropSheetCfg, 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 = m_secondaryPagesManager.CreateSheet(GetHiddenWindow(), m_pConsole, GetUnknown(), pNewCookie, spDataObject, lpszTitle);
// if failed, the cookie can be discarded,
// if succeeded, the cookie has been inserted into
// the secondary pages manager cookie list
if (FAILED(hr)) { delete pNewCookie; }
}
void CComponentDataImpl::_SheetLockCookie(CFolderObject* pCookie) { pCookie->IncrementSheetLockCount(); m_sheetCookieTable.Add(pCookie); }
void CComponentDataImpl::_SheetUnlockCookie(CFolderObject* pCookie) { pCookie->DecrementSheetLockCount(); m_sheetCookieTable.Remove(pCookie); }
STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject) { CFolderObject* pFolderObject; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if (!dobjCracker.GetContext(lpDataObject, &pFolderObject, &type)) { // not internal format, not ours
return S_FALSE; }
// this is the MMC snzpin wizard, we do not have one
if (type == CCT_SNAPIN_MANAGER) { return S_FALSE; }
// if NULL no pages
if (pFolderObject == NULL) { return S_FALSE; }
// secondary pages data objects have to be checked first,
// because they look like the root (no parents, but they
// have CCT_UNINITIALIZED
if ( (pFolderObject->GetParentFolder() == NULL) || (type == CCT_UNINITIALIZED) ) { return S_OK; }
// check if this is the root
if (GetRootFolder() == pFolderObject) { // this is the root
ASSERT(type == CCT_SCOPE); return S_OK; }
// default case, have DSPROP property pages
return S_OK; }
BOOL CComponentDataImpl::IsScopePaneNode(LPDATAOBJECT lpDataObject) { CFolderObject* pFolderObject; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if (!dobjCracker.GetContext(lpDataObject, &pFolderObject, &type)) return FALSE; return (dobjCracker.GetInternal()->m_type == CCT_SCOPE); }
///////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu implementation
//
STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { HRESULT hr = S_OK;
CFolderObject* pFolderObject; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if (!dobjCracker.GetContext(pDataObject, &pFolderObject, &type)) return E_FAIL;
return pFolderObject->OnAddMenuItems(pContextMenuCallback, pInsertionAllowed); }
STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT pDataObject) { // Note - snap-ins need to look at the data object and determine
// in what context the command is being called.
CFolderObject* pFolderObject; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(this); if (!dobjCracker.GetContext(pDataObject, &pFolderObject, &type)) return E_FAIL;
return pFolderObject->OnCommand(this, nCommandID); }
/////////////////////////////////////////////////////////////////////////////
// CComponentDataImpl::ISnapinHelp2 members
STDMETHODIMP CComponentDataImpl::GetHelpTopic(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 += DOMADMIN_SNAPIN_HELP_FILE;
UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR); *lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
if (NULL == *lpCompiledHelpFile) { return E_OUTOFMEMORY; }
// NOTICE-2002/03/07-ericb - SecurityPush: reviewed, usage is safe.
memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
return S_OK; }
// CODEWORK-2002/03/07-ericb - use a common helper for these two functions.
STDMETHODIMP CComponentDataImpl::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 += DOMADMIN_LINKED_HELP_FILE;
UINT nBytes = (szHelpFilePath.GetLength()+1) * sizeof(WCHAR); *lpCompiledHelpFile = (LPOLESTR)::CoTaskMemAlloc(nBytes);
if (NULL == *lpCompiledHelpFile) { return E_OUTOFMEMORY; }
// NOTICE-2002/03/07-ericb - SecurityPush: reviewed, usage is safe.
memcpy(*lpCompiledHelpFile, (LPCWSTR)szHelpFilePath, nBytes);
return S_OK; } /////////////////////////////////////////////////////////////////////
void CComponentDataImpl::HandleStandardVerbsHelper(CComponentImpl* pComponentImpl, LPCONSOLEVERB pConsoleVerb, BOOL bScope, BOOL bSelect, CFolderObject* pFolderObject, DATA_OBJECT_TYPES type) { // You should crack the data object and enable/disable/hide standard
// commands appropriately. The standard commands are reset everytime you get
// called. So you must reset them back.
ASSERT(pConsoleVerb != NULL); ASSERT(pComponentImpl != NULL); ASSERT(pFolderObject != NULL);
// reset the selection
pComponentImpl->SetSelection(NULL, CCT_UNINITIALIZED);
if (bSelect) { // special case the root
BOOL bIsRoot = (pFolderObject == GetRootFolder());
// setting the selection, if any
pComponentImpl->SetSelection(pFolderObject, type);
// the default just disables all the non implemented verbs
pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE); pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, FALSE);
pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE); pConsoleVerb->SetVerbState(MMC_VERB_PASTE, ENABLED, FALSE);
pConsoleVerb->SetVerbState(MMC_VERB_RENAME, HIDDEN, TRUE); pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, FALSE);
pConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE); pConsoleVerb->SetVerbState(MMC_VERB_PRINT, ENABLED, FALSE);
// handling of standard verbs
// MMC_VERB_DELETE (always disabled)
pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, FALSE); pConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
// MMC_VERB_REFRESH (enabled only for root)
if (bIsRoot) { pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE); pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); } else { pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, FALSE); pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, TRUE); }
// MMC_VERB_PROPERTIES
// passing NULL pFolderObject means multiple selection
BOOL bHasProperties = (pFolderObject != NULL); BOOL bHideProperties = !bHasProperties; pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, bHasProperties); pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, bHideProperties); // SET DEFAULT VERB
// assume only folders: only one default verb (i.e. will not have MMC_VERB_PROPERTIES)
pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
} }
void CComponentDataImpl::OnRefreshVerbHandler(CFolderObject* pFolderObject, CComponentImpl* pComponentImpl, BOOL bBindAgain) { TRACE(L"CComponentDataImpl::OnRefreshVerbHandler(...,..., %d)\n", bBindAgain); if (pFolderObject->_WarningOnSheetsUp(this)) return;
// make sure the DNS cache is flushed, in case a somain was added.
VERIFY(::DnsFlushResolverCache());
// NOTICE: only the root folder allows refresh
ASSERT(pFolderObject == GetRootFolder());
// remove all the children of the root from the UI
m_pConsoleNameSpace->DeleteItem(m_rootFolder.GetScopeID(), /*fDeleteThis*/ FALSE);
HRESULT hr = S_OK; if (bBindAgain) { // the server name has changed
hr = m_rootFolder.Bind(); TRACE(L"m_rootFolder.Bind() returned hr = 0x%x\n", hr); } if (SUCCEEDED(hr)) { // refresh the data from the server
hr = m_rootFolder.GetData(); TRACE(L"m_rootFolder.GetData() returned hr = 0x%x\n", hr); }
if (FAILED(hr)) { HWND hWndParent; GetMainWindow(&hWndParent); ReportError(hWndParent, IDS_CANT_GET_PARTITIONS_INFORMATION, hr); }
if (FAILED(hr)) return;
// re-enumerate
m_rootFolder.EnumerateRootFolder(this); }
//+---------------------------------------------------------------------------
//
// Function: LocaleStrCmp
//
// Synopsis: Do a case insensitive string compare that is safe for any
// locale.
//
// Arguments: [ptsz1] - strings to compare
// [ptsz2]
//
// Returns: -1, 0, or 1 just like lstrcmpi
//
// History: 10-28-96 DavidMun Created
//
// Notes: This is slower than lstrcmpi, but will work when sorting
// strings even in Japanese.
//
//----------------------------------------------------------------------------
int LocaleStrCmp(LPCTSTR ptsz1, LPCTSTR ptsz2) { int iRet = 0;
iRet = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH, ptsz1, -1, ptsz2, -1);
if (iRet) { iRet -= 2; // convert to lstrcmpi-style return -1, 0, or 1
if ( 0 == iRet ) { UNICODE_STRING unistr1; unistr1.Length = (USHORT)(::lstrlen(ptsz1)*sizeof(WCHAR)); unistr1.MaximumLength = unistr1.Length; unistr1.Buffer = (LPWSTR)ptsz1; UNICODE_STRING unistr2; unistr2.Length = (USHORT)(::lstrlen(ptsz2)*sizeof(WCHAR)); unistr2.MaximumLength = unistr2.Length; unistr2.Buffer = (LPWSTR)ptsz2; iRet = ::RtlCompareUnicodeString( &unistr1, &unistr2, FALSE ); } } else { DWORD dwErr = GetLastError (); if (dwErr != 0) { TRACE(L"CompareString (%s, %s) failed: 0x%x\n", ptsz1, ptsz2, dwErr); } } return iRet; }
///////////////////////////////////////////////////////////////////////////////
///////////////////// CComponentImpl (i.e. result pane side) //////////////////
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CComponentImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { return S_FALSE; }
//+---------------------------------------------------------------------------
//
// Function: CComponentImpl::IResultDataCompareEx::Compare
//
// Synopsis: This compare is used to sort the item's in the listview
//
// Note: Assume sort is ascending when comparing.
//
//----------------------------------------------------------------------------
STDMETHODIMP CComponentImpl::Compare(RDCOMPARE* prdc, int* pnResult) { if (pnResult == NULL) { ASSERT(FALSE); return E_POINTER; } if (prdc == NULL) { ASSERT(FALSE); return E_POINTER; }
*pnResult = 0;
LPCTSTR szStringA; LPCTSTR szStringB;
CDomainObject* pDataA = reinterpret_cast<CDomainObject*>(prdc->prdch1->cookie); CDomainObject* pDataB = reinterpret_cast<CDomainObject*>(prdc->prdch2->cookie);
ASSERT(pDataA != NULL && pDataB != NULL);
// Currently DomAdmin has just two columns, Name and Type. The value of
// the type column is always "DomainDNS", so there is nothing to compare
// for that column and the default *pnResult, set to zero above, is
// returned.
if (0 == prdc->nColumn) { szStringA = pDataA->GetDomainName(); szStringB = pDataB->GetDomainName();
ASSERT(szStringA != NULL); ASSERT(szStringB != NULL);
*pnResult = LocaleStrCmp(szStringA, szStringB); }
return S_OK; }
void CComponentImpl::HandleStandardVerbs(BOOL bScope, BOOL bSelect, CFolderObject* pFolderObject, DATA_OBJECT_TYPES type) { // delegate it to the IComponentData helper function
ASSERT(m_pCD != NULL); m_pCD->HandleStandardVerbsHelper( this, m_pConsoleVerb, bScope, bSelect, pFolderObject, type); }
void CComponentImpl::Refresh(CFolderObject* pFolderObject) { ASSERT(m_pComponentData != NULL); // delegate it to the IComponentData helper function
((CComponentDataImpl*)m_pComponentData)->OnRefreshVerbHandler(pFolderObject, this); }
// utility routines
////////////////////////////////////////////////////////////////////
//
// Print the data depending on its type.
//
#ifdef DBG
void PrintColumn( PADS_SEARCH_COLUMN pColumn, LPWSTR pszColumnName ) {
ULONG i, j, k;
if (!pColumn) { return; }
TRACE(_T( "%s = "), pszColumnName );
for (k=0; k < pColumn->dwNumValues; k++) { if (k > 0) TRACE(_T("# "));
switch(pColumn->dwADsType) { case ADSTYPE_DN_STRING : TRACE(_T( "%s "), (LPWSTR) pColumn->pADsValues[k].DNString ); break; case ADSTYPE_CASE_EXACT_STRING : TRACE(_T( "%s "), (LPWSTR) pColumn->pADsValues[k].CaseExactString ); break; case ADSTYPE_CASE_IGNORE_STRING: TRACE(_T( "%s "), (LPWSTR) pColumn->pADsValues[k].CaseIgnoreString ); break; case ADSTYPE_PRINTABLE_STRING : TRACE(_T( "%s "), (LPWSTR) pColumn->pADsValues[k].PrintableString ); break; case ADSTYPE_NUMERIC_STRING : TRACE(_T( "%s "), (LPWSTR) pColumn->pADsValues[k].NumericString ); break;
case ADSTYPE_BOOLEAN : TRACE(_T( "%s "), (DWORD) pColumn->pADsValues[k].Boolean ? L"TRUE" : L"FALSE" ); break;
case ADSTYPE_INTEGER : TRACE(_T( "%d "), (DWORD) pColumn->pADsValues[k].Integer ); break;
case ADSTYPE_OCTET_STRING : for (j=0; j<pColumn->pADsValues[k].OctetString.dwLength; j++) { TRACE(_T( "%02x"), ((BYTE *)pColumn->pADsValues[k].OctetString.lpValue)[j] ); } break;
case ADSTYPE_LARGE_INTEGER : TRACE(_T( "%e = "), (double) pColumn->pADsValues[k].Integer ); break;
case ADSTYPE_UTC_TIME : TRACE(_T( "(date value) " )); break; case ADSTYPE_PROV_SPECIFIC : TRACE(_T( "(provider specific value) " )); break;
} }
TRACE(_T("\n")); }
#endif
/////////////////////////////////////////////////////////////////////////////
// Return TRUE if we are enumerating our main folder
BOOL CComponentImpl::IsEnumerating(LPDATAOBJECT lpDataObject) { BOOL bResult = FALSE;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)CDataObject::m_cfNodeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// Allocate memory for the stream
stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(GUID));
// Attempt to get data from the object
do { if (stgmedium.hGlobal == NULL) break;
if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium))) break;
GUID* nodeType = reinterpret_cast<GUID*>(stgmedium.hGlobal);
if (nodeType == NULL) break;
// Is this my main node (static folder node type)
if (*nodeType == cDefaultNodeType) bResult = TRUE;
} while (FALSE);
// Free resources
if (stgmedium.hGlobal != NULL) GlobalFree(stgmedium.hGlobal);
return bResult; }
/////////////////////////////////////////////////////////////////////////////
// CComponentImpl's IComponent implementation
STDMETHODIMP CComponentImpl::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType, long *pViewOptions) { // Use default view
*pViewOptions = 0; return S_FALSE; }
STDMETHODIMP CComponentImpl::Initialize(LPCONSOLE lpConsole) { ASSERT(lpConsole != NULL);
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Save the IConsole pointer
m_pConsole = lpConsole; m_pConsole->AddRef();
// Load resource strings
LoadResources();
// QI for a IHeaderCtrl
HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl, reinterpret_cast<void**>(&m_pHeader));
// Give the console the header control interface pointer
if (SUCCEEDED(hr)) m_pConsole->SetHeader(m_pHeader);
m_pConsole->QueryInterface(IID_IResultData, reinterpret_cast<void**>(&m_pResult));
hr = m_pConsole->QueryResultImageList(&m_pImageResult); ASSERT(hr == S_OK);
hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb); ASSERT(hr == S_OK);
//InitializeHeaders(NULL);
//InitializeBitmaps(NULL);
return S_OK; }
STDMETHODIMP CComponentImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { HRESULT hr = S_OK; AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (event == MMCN_PROPERTY_CHANGE) { hr = OnPropertyChange(lpDataObject); } else if (event == MMCN_VIEW_CHANGE) { hr = OnUpdateView(lpDataObject); } else if (event == MMCN_CONTEXTHELP) { CComPtr<IDisplayHelp> spHelp; hr = m_pConsole->QueryInterface(IID_IDisplayHelp, (void **)&spHelp); ASSERT(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { TRACE(L"Setting the help topic to adconcepts.chm::/domadmin_top.htm\n"); spHelp->ShowTopic(L"adconcepts.chm::/domadmin_top.htm"); } } else { if (lpDataObject == NULL) return S_OK;
CFolderObject* pFolderObject = NULL; DATA_OBJECT_TYPES type; CInternalFormatCracker dobjCracker(m_pCD); if (!dobjCracker.GetContext(lpDataObject, &pFolderObject, &type)) { // Extensions not supported.
ASSERT(FALSE); return S_OK; } ASSERT(pFolderObject != NULL);
switch(event) { case MMCN_SHOW: hr = OnShow(pFolderObject, arg, param); break;
case MMCN_ADD_IMAGES: hr = OnAddImages(pFolderObject, arg, param); break;
case MMCN_SELECT: if (IsMMCMultiSelectDataObject(lpDataObject) == TRUE) pFolderObject = NULL; HandleStandardVerbs( (BOOL) LOWORD(arg)/*bScope*/, (BOOL) HIWORD(arg)/*bSelect*/, pFolderObject, type); break;
case MMCN_REFRESH: Refresh(pFolderObject); break;
default: break; } // switch
} // else
if (m_pResult) { // should put something here, someday?
; }
return hr; }
STDMETHODIMP CComponentImpl::Destroy(MMC_COOKIE cookie) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Release the interfaces that we QI'ed
if (m_pConsole != NULL) { // Tell the console to release the header control interface
m_pConsole->SetHeader(NULL); SAFE_RELEASE(m_pHeader);
SAFE_RELEASE(m_pResult); SAFE_RELEASE(m_pImageResult);
// Release the IConsole interface last
SAFE_RELEASE(m_pConsole); SAFE_RELEASE(m_pComponentData); // QI'ed in IComponentDataImpl::CreateComponent
SAFE_RELEASE(m_pConsoleVerb); }
return S_OK; }
STDMETHODIMP CComponentImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { // Delegate it to the IComponentData
ASSERT(m_pComponentData != NULL); return m_pComponentData->QueryDataObject(cookie, type, ppDataObject); }
/////////////////////////////////////////////////////////////////////////////
// CComponentImpl's implementation specific members
DEBUG_DECLARE_INSTANCE_COUNTER(CComponentImpl);
CComponentImpl::CComponentImpl() { DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentImpl); Construct(); }
CComponentImpl::~CComponentImpl() { #if DBG==1
ASSERT(dbg_cRef == 0); #endif
DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentImpl);
// Make sure the interfaces have been released
ASSERT(m_pConsole == NULL); ASSERT(m_pHeader == NULL); Construct(); }
void CComponentImpl::Construct() { #if DBG==1
dbg_cRef = 0; #endif
m_pConsole = NULL; m_pHeader = NULL;
m_pResult = NULL; m_pImageResult = NULL; m_pComponentData = NULL; m_pCD = NULL; m_pConsoleVerb = NULL;
m_selectedType = CCT_UNINITIALIZED; m_pSelectedFolderObject = NULL;
}
void CComponentImpl::LoadResources() { // Load strings from resources
m_column1.LoadString(IDS_NAME); m_column2.LoadString(IDS_TYPE); }
HRESULT CComponentImpl::InitializeHeaders(CFolderObject* pFolderObject) { HRESULT hr = S_OK; ASSERT(m_pHeader);
// NOTICE: we ignore the cookie, keep always the same columns
m_pHeader->InsertColumn(0, m_column1, LVCFMT_LEFT, 200); // Name
m_pHeader->InsertColumn(1, m_column2, LVCFMT_LEFT, 80); // Type
return hr; }
HRESULT CComponentImpl::InitializeBitmaps(CFolderObject* pFolderObject) { ASSERT(m_pImageResult != NULL); AFX_MANAGE_STATE(AfxGetStaticModuleState());
CBitmap bmp16x16; CBitmap bmp32x32;
// Load the bitmaps from the dll
VERIFY(bmp16x16.LoadBitmap(IDB_DOMAIN_SMALL)); VERIFY(bmp32x32.LoadBitmap(IDB_DOMAIN_LARGE));
// Set the images
HRESULT hr = m_pImageResult->ImageListSetStrip(reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)), reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp32x32)), 0, RGB(128, 0, 0)); if (FAILED(hr)) return hr; return ((CComponentDataImpl*)m_pComponentData)->AddDomainIconToResultPane(m_pImageResult); }
STDMETHODIMP CComponentImpl::GetDisplayInfo(LPRESULTDATAITEM pResult) { ASSERT(pResult != NULL);
CDomainObject* pDomain = reinterpret_cast<CDomainObject*>(pResult->lParam); if ( (pDomain != NULL) && (pResult->mask & RDI_STR) ) { pResult->str = (LPWSTR)pDomain->GetDisplayString(pResult->nCol); TRACE(L"pResult->str = %s\n", pResult->str); } if ((pResult->mask & RDI_IMAGE) && (pResult->nCol == 0)) { pResult->nImage = pDomain->GetImageIndex(); }
return S_OK; }
/////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu Implementation
STDMETHODIMP CComponentImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long * pInsertionAllowed) { return dynamic_cast<CComponentDataImpl*>(m_pComponentData)-> AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed); }
STDMETHODIMP CComponentImpl::Command(long nCommandID, LPDATAOBJECT pDataObject) { return dynamic_cast<CComponentDataImpl*>(m_pComponentData)-> Command(nCommandID, pDataObject); }
HRESULT CComponentImpl::OnShow(CFolderObject* pFolderObject, LPARAM arg, LPARAM param) { // Note - arg is TRUE when it is time to enumerate
if (arg == TRUE) { // Show the headers for this nodetype
InitializeHeaders(pFolderObject); Enumerate(pFolderObject, param); } return S_OK; }
HRESULT CComponentImpl::OnAddImages(CFolderObject* pFolderObject, LPARAM arg, LPARAM param) { return InitializeBitmaps(pFolderObject); }
HRESULT CComponentImpl::OnPropertyChange(LPDATAOBJECT lpDataObject) { return S_OK; }
HRESULT CComponentImpl::OnUpdateView(LPDATAOBJECT lpDataObject) { return S_OK; }
void CComponentImpl::Enumerate(CFolderObject* pFolderObject, HSCOPEITEM pParent) { }
//////////////////////////////////////////////////////////////////////////
// CDomainSnapinAbout
CDomainSnapinAbout::CDomainSnapinAbout(): CSnapinAbout(IDS_SNAPINABOUT_DESCRIPTION, IDI_DOMAIN, IDB_DOMAIN_SMALL, IDB_DOMAIN_SMALL, IDB_DOMAIN_LARGE, RGB(255,0,255)) { }
////////////////////////////////////////////////////////////////////
// CHiddenWnd
const UINT CHiddenWnd::s_SheetCloseNotificationMessage = WM_DSA_SHEET_CLOSE_NOTIFY; const UINT CHiddenWnd::s_SheetCreateNotificationMessage = WM_DSA_SHEET_CREATE_NOTIFY;
BOOL CHiddenWnd::Create() { RECT rcPos; // NOTICE-2002/03/07-ericb - SecurityPush: zeroing a struct
ZeroMemory(&rcPos, sizeof(RECT)); HWND hWnd = CWindowImpl<CHiddenWnd>::Create( NULL, //HWND hWndParent,
rcPos, //RECT& rcPos,
NULL, //LPCTSTR szWindowName = NULL,
WS_POPUP, //DWORD dwStyle = WS_CHILD | WS_VISIBLE,
0x0, //DWORD dwExStyle = 0,
0 //UINT nID = 0
); if (!hWnd) { TRACE(L"Hidden Window creation failed with error %d\n", GetLastError()); return FALSE; } return TRUE; }
LRESULT CHiddenWnd::OnSheetCloseNotification(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ASSERT(m_pCD != NULL); CFolderObject* pCookie = reinterpret_cast<CFolderObject*>(wParam); m_pCD->_OnSheetClose(pCookie); return 1; }
LRESULT CHiddenWnd::OnSheetCreateNotification(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ASSERT(m_pCD != NULL); PDSA_SEC_PAGE_INFO pDsaSecondaryPageInfo = reinterpret_cast<PDSA_SEC_PAGE_INFO>(wParam); ASSERT(pDsaSecondaryPageInfo != NULL); PWSTR pwzDC = (PWSTR)lParam;
m_pCD->_OnSheetCreate(pDsaSecondaryPageInfo, pwzDC);
::LocalFree(pDsaSecondaryPageInfo);
if (pwzDC && !IsBadReadPtr(pwzDC, sizeof(PWSTR))) { ::LocalFree(pwzDC); }
return 1; }
|