windows-nt/Source/XPSP1/NT/admin/snapin/filemgmt/cmponent.cpp
2020-09-26 16:20:57 +08:00

1825 lines
58 KiB
C++

// cmponent.cpp : Implementation of CFileMgmtComponent
#include "stdafx.h"
#include "cookie.h"
#include "safetemp.h"
#include "macros.h"
USE_HANDLE_MACROS("FILEMGMT(cmponent.cpp)")
#include "ShrProp.h" // Share Properties Pages
#include "FileSvc.h" // FileServiceProvider
#include "smb.h"
#include "fpnw.h"
#include "sfm.h"
#include "dataobj.h"
#include "cmponent.h" // CFileMgmtComponent
#include "compdata.h" // CFileMgmtComponentData
#include "stdutils.h" // SynchronousCreateProcess
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "stdcmpnt.cpp" // CComponent
UINT g_aColumns0[2] =
{IDS_ROOT_NAME, 0};
UINT g_aColumns1[6] =
{IDS_SHARES_SHARED_FOLDER, IDS_SHARES_SHARED_PATH, IDS_SHARES_TRANSPORT,
IDS_SHARES_NUM_SESSIONS, IDS_SHARES_COMMENT, 0};
UINT g_aColumns2[8] =
{IDS_CONN_USERNAME, IDS_CONN_COMPUTERNAME, IDS_CONN_TRANSPORT, IDS_CONN_NUM_FILES,
IDS_CONN_CONNECTED_TIME, IDS_CONN_IDLE_TIME, IDS_CONN_IS_GUEST, 0};
UINT g_aColumns3[6] =
{IDS_FILE_FILENAME, IDS_FILE_USERNAME, IDS_FILE_TRANSPORT, IDS_FILE_NUM_LOCKS,
IDS_FILE_OPEN_MODE, 0};
UINT g_aColumns4[6] =
{ IDS_SERVICE_SERVICENAME, IDS_SERVICE_DESCRIPTION, IDS_SERVICE_STATUS,
IDS_SERVICE_STARTUPTYPE, IDS_SERVICE_SECURITYCONTEXT, 0};
UINT* g_Columns[FILEMGMT_NUMTYPES] =
{ g_aColumns0, // FILEMGMT_ROOT
g_aColumns1, // FILEMGMT_SHARES
g_aColumns2, // FILEMGMT_SESSIONS
g_aColumns3, // FILEMGMT_RESOURCES
g_aColumns4, // FILEMGMT_SERVICES
NULL, // FILEMGMT_SHARE
NULL, // FILEMGMT_SESSION
NULL, // FILEMGMT_RESOURCE
NULL // FILEMGMT_SERVICE
};
UINT** g_aColumns = g_Columns;
/*
const UINT aColumns[STD_NODETYPE_NUMTYPES][STD_MAX_COLUMNS] =
{ {IDS_ROOT_NAME, 0,0,0,0,0,0},
{IDS_SHARES_SHARED_FOLDER, IDS_SHARES_SHARED_PATH, IDS_SHARES_TRANSPORT,
IDS_SHARES_NUM_SESSIONS, IDS_SHARES_COMMENT, 0,0},
{IDS_CONN_USERNAME, IDS_CONN_COMPUTERNAME, IDS_CONN_TRANSPORT, IDS_CONN_NUM_FILES,
IDS_CONN_CONNECTED_TIME, IDS_CONN_IDLE_TIME, IDS_CONN_IS_GUEST},
{IDS_FILE_FILENAME, IDS_FILE_USERNAME, IDS_FILE_TRANSPORT, IDS_FILE_NUM_LOCKS,
IDS_FILE_OPEN_MODE, 0,0},
{ IDS_SERVICE_SERVICENAME, IDS_SERVICE_DESCRIPTION, IDS_SERVICE_STATUS,
IDS_SERVICE_STARTUPTYPE, IDS_SERVICE_SECURITYCONTEXT, 0,0 },
{0,0,0,0,0,0},
{0,0,0,0,0,0},
{0,0,0,0,0,0},
{0,0,0,0,0,0}
};
*/
//
// CODEWORK this should be in a resource, for example code on loading data resources see
// D:\nt\private\net\ui\common\src\applib\applib\lbcolw.cxx ReloadColumnWidths()
// JonN 10/11/96
//
int g_aColumnWidths0[1] = {150};
int g_aColumnWidths1[5] = {AUTO_WIDTH,120 ,90 ,AUTO_WIDTH,150};
int g_aColumnWidths2[7] = {100 ,AUTO_WIDTH,90 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH};
int g_aColumnWidths3[5] = {120 ,AUTO_WIDTH,90 ,AUTO_WIDTH,AUTO_WIDTH};
int g_aColumnWidths4[5] = {130 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH};
int* g_ColumnWidths[FILEMGMT_NUMTYPES] =
{ g_aColumnWidths0, // FILEMGMT_ROOT
g_aColumnWidths1, // FILEMGMT_SHARES
g_aColumnWidths2, // FILEMGMT_SESSIONS
g_aColumnWidths3, // FILEMGMT_RESOURCES
g_aColumnWidths4, // FILEMGMT_SERVICES
NULL, // FILEMGMT_SHARE
NULL, // FILEMGMT_SESSION
NULL, // FILEMGMT_RESOURCE
NULL // FILEMGMT_SERVICE
};
int** g_aColumnWidths = g_ColumnWidths;
/*
const int aColumnWidths[STD_NODETYPE_NUMTYPES][STD_MAX_COLUMNS] =
{ {AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_ROOT
{AUTO_WIDTH,120 ,90 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_SHARES
{100 ,AUTO_WIDTH,90 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_SESSIONS
{120 ,AUTO_WIDTH,90 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_RESOURCES
{130 ,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_SERVICES
{AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_SHARE
{AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_SESSION
{AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH}, // FILEMGMT_RESOURCE
{AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH,AUTO_WIDTH} // FILEMGMT_SERVICE
};
*/
CString g_cstrClientName;
CString g_cstrGuest;
CString g_cstrYes;
CString g_cstrNo;
// Note that m_pFileMgmtData is still NULL during construction
CFileMgmtComponent::CFileMgmtComponent()
: m_pControlbar( NULL )
, m_pSvcMgmtToolbar( NULL )
, m_pFileMgmtToolbar( NULL )
, m_pViewedCookie( NULL )
, m_pSelectedCookie( NULL )
, m_iSortColumn(0)
, m_dwSortFlags(0)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
}
CFileMgmtComponent::~CFileMgmtComponent()
{
TRACE_METHOD(CFileMgmtComponent,ReleaseAll);
/* now in CFileMgmtComponentData
if (m_hScManager != NULL)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
CWaitCursor wait;
// Close the service control manager
(void)::CloseServiceHandle(m_hScManager);
} // if
*/
VERIFY( SUCCEEDED(ReleaseAll()) );
}
HRESULT CFileMgmtComponent::ReleaseAll()
{
MFC_TRY;
TRACE_METHOD(CFileMgmtComponent,ReleaseAll);
if ( NULL != m_pViewedCookie )
{
// We did not get an equal number of MMCN_SHOW(1) and
// MMCN_SHOW(0) notifications
// CODEWORK should assert here but MMC is currently broken
// ASSERT(FALSE);
m_pViewedCookie->ReleaseResultChildren();
m_pViewedCookie = NULL;
}
// We should get an equal number of MMCN_SELECT(1) and MMCN_SELECT(0) notifications
// CODEWORK should assert this but MMC is broken ASSERT( NULL == m_pSelectedCookie );
SAFE_RELEASE(m_pSvcMgmtToolbar);
SAFE_RELEASE(m_pFileMgmtToolbar);
SAFE_RELEASE(m_pControlbar);
return CComponent::ReleaseAll();
MFC_CATCH;
}
FileServiceProvider* CFileMgmtComponent::GetFileServiceProvider(
FILEMGMT_TRANSPORT transport )
{
return QueryComponentDataRef().GetFileServiceProvider(transport);
}
BOOL CFileMgmtComponent::IsServiceSnapin()
{
return QueryComponentDataRef().IsServiceSnapin();
}
/////////////////////////////////////////////////////////////////////////////
// IComponent Implementation
HRESULT CFileMgmtComponent::LoadStrings()
{
Service_LoadResourceStrings();
return S_OK;
}
HRESULT CFileMgmtComponent::LoadColumns( CFileMgmtCookie* pcookie )
{
TEST_NONNULL_PTR_PARAM(pcookie);
ASSERT(m_pHeader != NULL);
#ifdef SNAPIN_PROTOTYPER
(void)Prototyper_FInsertColumns(pcookie);
return S_OK;
#endif
if (g_cstrGuest.IsEmpty())
VERIFY(g_cstrGuest.LoadString(IDS_GUEST));
if (g_cstrYes.IsEmpty())
VERIFY(g_cstrYes.LoadString(IDS_YES));
if (g_cstrNo.IsEmpty())
VERIFY(g_cstrNo.LoadString(IDS_NO));
return LoadColumnsFromArrays( pcookie->QueryObjectType() );
}
// OnPropertyChange() is generated by MMCPropertyChangeNotify( param )
HRESULT CFileMgmtComponent::OnPropertyChange( LPARAM param )
{
LPDATAOBJECT pdataobject = reinterpret_cast<LPDATAOBJECT> (param);
VERIFY( SUCCEEDED( RefreshAllViews(pdataobject) ) );
// The recipient of this notification is required to release the data object
(void) pdataobject->Release();
return S_OK;
} // CFileMgmtComponent::OnPropertyChange()
//
// In case of multiselect, piDataObject may point to a composite data object (MMC_MS_DO).
// RefreshAllViewsOnSelectedObject will crack down MMC_MS_DO to retrieve SI_MS_DO, then call
// RefreshAllViews on one of the selected objects in the internal list.
//
HRESULT CFileMgmtComponent::RefreshAllViewsOnSelectedObject(LPDATAOBJECT piDataObject)
{
BOOL bMultiSelectObject = IsMultiSelectObject(piDataObject);
if (!bMultiSelectObject)
return RefreshAllViews(piDataObject);
//
// piDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
IDataObject *piSIMSDO = NULL;
HRESULT hr = GetSnapinMultiSelectDataObject(piDataObject, &piSIMSDO);
if (SUCCEEDED(hr))
{
CFileMgmtDataObject *pDataObj = NULL;
hr = ExtractData(piSIMSDO, CFileMgmtDataObject::m_CFInternal, &pDataObj, sizeof(pDataObj));
if (SUCCEEDED(hr))
{
//
// get the internal list of data objects of selected items, operate on one of them.
//
CDataObjectList* pMultiSelectObjList = pDataObj->GetMultiSelectObjList();
ASSERT(!pMultiSelectObjList->empty());
hr = RefreshAllViews(*(pMultiSelectObjList->begin()));
}
}
return hr;
}
// Forces all views of the specified data object to refresh
HRESULT CFileMgmtComponent::RefreshAllViews( LPDATAOBJECT pDataObject )
{
if ( NULL == pDataObject || NULL == m_pConsole )
{
ASSERT(FALSE);
return ERROR_INVALID_PARAMETER;
}
// This is new code for updating the Service list using a mark-and-sweep algorithm.
// Eventually this should be applied to all result cookies.
CCookie* pbasecookie = NULL;
HRESULT hr = ExtractData(
pDataObject,
CDataObject::m_CFRawCookie,
&pbasecookie,
sizeof(pbasecookie) );
RETURN_HR_IF_FAIL; // MMC shouldn't have given me someone else's cookie
pbasecookie = QueryBaseComponentDataRef().ActiveBaseCookie( pbasecookie );
CFileMgmtCookie* pUpdatedCookie = dynamic_cast<CFileMgmtCookie*>(pbasecookie);
RETURN_E_FAIL_IF_NULL(pUpdatedCookie);
FileMgmtObjectType objTypeForUpdatedCookie = pUpdatedCookie->QueryObjectType();
if ( FILEMGMT_SERVICE == objTypeForUpdatedCookie )
{
if ( NULL == m_pViewedCookie
|| FILEMGMT_SERVICES != m_pViewedCookie->QueryObjectType()
)
{
return S_OK; // not a service cookie update
}
pUpdatedCookie = dynamic_cast<CFileMgmtCookie*>(m_pViewedCookie);
RETURN_E_FAIL_IF_NULL(pUpdatedCookie);
objTypeForUpdatedCookie = FILEMGMT_SERVICES;
}
if ( FILEMGMT_SERVICES == objTypeForUpdatedCookie )
{
CFileMgmtScopeCookie* pScopeCookie = dynamic_cast<CFileMgmtScopeCookie*>(pUpdatedCookie);
RETURN_E_FAIL_IF_NULL(pScopeCookie);
// "Mark" -- Mark all existing list elements as "delete"
pScopeCookie->MarkResultChildren( NEWRESULTCOOKIE_DELETE );
// "Sweep" -- Read the new list. When a new element is the same object
// as an existing element not yet seen, mark the old element as "old"
// and update its fields. Otherwise, add it as a "new" element.
hr = QueryComponentDataRef().Service_PopulateServices(m_pResultData, pScopeCookie);
RETURN_HR_IF_FAIL;
// Refresh all views to conform with the new list.
hr = m_pConsole->UpdateAllViews( pDataObject, 2L, 0L );
RETURN_HR_IF_FAIL;
// UpdateToolbar if selected
hr = m_pConsole->UpdateAllViews( pDataObject, 3L, 0L );
RETURN_HR_IF_FAIL;
// Remove items which are still marked "delete".
pScopeCookie->RemoveMarkedChildren();
pScopeCookie->MarkResultChildren( NEWRESULTCOOKIE_OLD );
return S_OK;
}
//
// JonN 1/27/00: WinSE 5875: The refresh action is liable to delete pDataObject
// unless we keep an extra refcount. In practice, this only appears to happen
// when we delete a share in taskpad view.
//
CComPtr<IDataObject> spDataObject = pDataObject;
// clear all views of this data
hr = m_pConsole->UpdateAllViews( pDataObject, 0L, 0L );
RETURN_HR_IF_FAIL;
// reread all views of this data
hr = m_pConsole->UpdateAllViews( pDataObject, 1L, 0L );
RETURN_HR_IF_FAIL;
// UpdateToolbar if selected
hr = m_pConsole->UpdateAllViews( pDataObject, 3L, 0L );
return hr;
} // CFileMgmtComponent::RefreshAllViews()
// OnViewChange is generated by UpdateAllViews( lpDataObject, data, hint )
HRESULT CFileMgmtComponent::OnViewChange( LPDATAOBJECT lpDataObject, LPARAM data, LPARAM /*hint*/ )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CWaitCursor wait;
ASSERT( NULL != lpDataObject );
if (NULL == m_pViewedCookie) // skip this component if not being viewed
return S_OK;
CCookie* pbasecookie = NULL;
HRESULT hr = ExtractData( lpDataObject,
CDataObject::m_CFRawCookie,
&pbasecookie,
sizeof(pbasecookie) );
RETURN_HR_IF_FAIL; // MMC shouldn't have given me someone else's cookie
pbasecookie = QueryBaseComponentDataRef().ActiveBaseCookie( pbasecookie );
CFileMgmtCookie* pUpdatedCookie = dynamic_cast<CFileMgmtCookie*>(pbasecookie);
RETURN_E_FAIL_IF_NULL(pUpdatedCookie);
FileMgmtObjectType objTypeForUpdatedCookie = pUpdatedCookie->QueryObjectType();
switch (m_pViewedCookie->QueryObjectType())
{
case FILEMGMT_ROOT:
return S_OK; // there is never any need to refresh this
case FILEMGMT_RESOURCES:
if ( FILEMGMT_RESOURCE == objTypeForUpdatedCookie ||
FILEMGMT_RESOURCES == objTypeForUpdatedCookie)
break;
// fall through
case FILEMGMT_SESSIONS:
if ( FILEMGMT_SESSION == objTypeForUpdatedCookie ||
FILEMGMT_SESSIONS == objTypeForUpdatedCookie)
break;
// fall through
case FILEMGMT_SHARES:
if ( FILEMGMT_SHARE == objTypeForUpdatedCookie ||
FILEMGMT_SHARES == objTypeForUpdatedCookie)
break;
return S_OK;
case FILEMGMT_SERVICES:
if ( FILEMGMT_SERVICE == objTypeForUpdatedCookie ||
FILEMGMT_SERVICES == objTypeForUpdatedCookie)
break;
return S_OK;
case FILEMGMT_SHARE:
case FILEMGMT_SESSION:
case FILEMGMT_RESOURCE:
case FILEMGMT_SERVICE:
default:
ASSERT(FALSE); // this shouldn't be possible
return S_OK;
}
// There should be no need to compare machine name, since these are both from the
// same instance.
if ( 0L == data )
{
ASSERT( NULL != m_pResultData );
VERIFY( SUCCEEDED(m_pResultData->DeleteAllRsltItems()) );
m_pViewedCookie->ReleaseResultChildren();
//
// At this point, m_pViewedCookie is still the viewed cookie for this IComponent
// but (once this has happened to all of the views) its list of result children
// is empty and its m_nResultCookiesRefcount is zero. This must be followed
// promptly with PopulateListbox calls for these views since this is not a good
// state for the cookie.
//
}
else if ( 1L == data )
{
VERIFY( SUCCEEDED(PopulateListbox( m_pViewedCookie )) );
}
else if ( 2L == data )
{
VERIFY( SUCCEEDED(RefreshNewResultCookies( *m_pViewedCookie )) );
}
else if ( 3L == data )
{
if (m_pSelectedCookie == pbasecookie)
UpdateToolbar(lpDataObject, TRUE);
}
else
{
ASSERT(FALSE);
}
return S_OK;
} // CFileMgmtComponent::OnViewChange()
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponent::CComponent::OnNotifyRefresh()
//
// Virtual function called by CComponent::IComponent::Notify(MMCN_REFRESH)
// OnNotifyRefresh is generated by enabling the verb MMC_VERB_REFRESH.
HRESULT CFileMgmtComponent::OnNotifyRefresh( LPDATAOBJECT lpDataObject )
{
TRACE0("CFileMgmtComponent::OnNotifyRefresh()\n");
ASSERT(m_pResultData != NULL);
if ( !m_pResultData )
return E_POINTER;
if ( !m_pViewedCookie )
{
ASSERT(FALSE);
return S_OK;
}
// We used to use the cookie here from lpDataObject. However, if one node
// is selected and the user right clicks on a different one we an
// lpDataObject for a node that is not enumerated in the result pane.
// It results in bizarre behavior. So use the m_pViewedCookie, instead.
HRESULT hr = S_OK;
switch (m_pViewedCookie->QueryObjectType())
{
case FILEMGMT_SHARES:
case FILEMGMT_SESSIONS:
case FILEMGMT_RESOURCES:
case FILEMGMT_SERVICES:
(void) RefreshAllViews( lpDataObject );
break;
case FILEMGMT_ROOT:
case FILEMGMT_SERVICE: // Service was selected
case FILEMGMT_SHARE: // Share was selected
case FILEMGMT_SESSION: // Session was selected
case FILEMGMT_RESOURCE: // Open file was selected
default:
// This can happen if you select Shares, then select Shared Folders,
// then right-click Shares and choose Refresh. JonN 12/7/98
break; // no need to refresh
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////
// CFileMgmtComponent::RefreshNewResultCookies()
// 12/03/98 JonN Created
// In the mark-and-sweep refresh algorithm, we have already marked all cookies
// as "old", "new" or "delete". The view must now be made to conform with the list.
HRESULT CFileMgmtComponent::RefreshNewResultCookies( CCookie& refparentcookie )
{
ASSERT( NULL != m_pResultData );
RESULTDATAITEM tRDItem;
::ZeroMemory( &tRDItem, sizeof(tRDItem) );
tRDItem.nCol = 0;
tRDItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
tRDItem.str = MMC_CALLBACK;
// CODEWORK should use MMC_ICON_CALLBACK here
HRESULT hr = S_OK;
POSITION pos = refparentcookie.m_listResultCookieBlocks.GetHeadPosition();
while (NULL != pos)
{
CBaseCookieBlock* pblock = refparentcookie.m_listResultCookieBlocks.GetNext( pos );
ASSERT( NULL != pblock && 1 == pblock->QueryNumCookies() );
CCookie* pbasecookie = pblock->QueryBaseCookie(0);
CNewResultCookie* pcookie = dynamic_cast<CNewResultCookie*>(pbasecookie);
RETURN_E_FAIL_IF_NULL(pcookie);
if ( pcookie->IsMarkedOld() )
{
continue; // Leave this one alone
}
else if ( pcookie->IsMarkedNew() )
{ // This one was just added to the list, add it to the view
tRDItem.nImage = QueryBaseComponentDataRef().QueryImage( *pbasecookie, FALSE );
// WARNING cookie cast
tRDItem.lParam = reinterpret_cast<LPARAM>(pbasecookie);
hr = m_pResultData->InsertItem(&tRDItem);
if ( FAILED(hr) )
{
ASSERT(FALSE);
break;
}
}
else if ( pcookie->IsMarkedChanged() )
{ // This one was already in the list but its fields were altered, update
HRESULTITEM hItem = 0;
hr = m_pResultData->FindItemByLParam( reinterpret_cast<LPARAM>(pbasecookie), &hItem );
if ( FAILED(hr) || 0 == hItem )
{
ASSERT(FALSE);
continue;
}
VERIFY( SUCCEEDED(m_pResultData->UpdateItem( hItem )) );
}
else
{ // This one was just marked for deletion, remove it from the view
// CODEWORK This may be a performance problem when the list is long
// CODEWORK BryanWal doesn't trust FindItemByLParam! Test carefully!
ASSERT( pcookie->IsMarkedForDeletion() );
HRESULTITEM hItem = 0;
hr = m_pResultData->FindItemByLParam( reinterpret_cast<LPARAM>(pbasecookie), &hItem );
if ( FAILED(hr) || 0 == hItem )
{
ASSERT(FALSE);
continue;
}
VERIFY( SUCCEEDED(m_pResultData->DeleteItem( hItem, 0 )) );
}
}
VERIFY( SUCCEEDED(m_pResultData->Sort( m_iSortColumn , m_dwSortFlags, 0 )) );
return hr;
}
HRESULT CFileMgmtComponent::OnNotifySelect( LPDATAOBJECT lpDataObject, BOOL fSelected )
{
HRESULT hr = S_OK;
BOOL bMultiSelectObject = FALSE;
//
// MMC passes in SI_MS_DO in MMCN_SELECT in case of multiselection.
//
CFileMgmtDataObject *pDataObj = NULL;
hr = ExtractData(lpDataObject, CFileMgmtDataObject::m_CFInternal, &pDataObj, sizeof(pDataObj));
if (SUCCEEDED(hr))
{
CDataObjectList* pMultiSelectObjList = pDataObj->GetMultiSelectObjList();
bMultiSelectObject = !(pMultiSelectObjList->empty());
}
//
// no verbs to add for multi-selected SharedFolders items
//
if (!bMultiSelectObject)
{
CCookie* pbasecookie = NULL;
hr = ExtractData( lpDataObject,
CDataObject::m_CFRawCookie,
&pbasecookie,
sizeof(pbasecookie) );
RETURN_HR_IF_FAIL; // MMC shouldn't have given me someone else's cookie
pbasecookie = QueryBaseComponentDataRef().ActiveBaseCookie( pbasecookie );
CFileMgmtCookie* pUpdatedCookie = dynamic_cast<CFileMgmtCookie*>(pbasecookie);
RETURN_E_FAIL_IF_NULL(pUpdatedCookie);
m_pSelectedCookie = (fSelected) ? pUpdatedCookie : NULL;
UpdateDefaultVerbs();
}
return S_OK;
}
void CFileMgmtComponent::UpdateDefaultVerbs()
{
if (NULL == m_pSelectedCookie)
return;
FileMgmtObjectType objtypeSelected = m_pSelectedCookie->QueryObjectType();
if (NULL != m_pViewedCookie)
{
BOOL fEnableRefresh = FALSE;
FileMgmtObjectType objtypeViewed = m_pViewedCookie->QueryObjectType();
switch (objtypeViewed)
{
case FILEMGMT_SHARES:
if (FILEMGMT_SHARES == objtypeSelected || FILEMGMT_SHARE == objtypeSelected)
fEnableRefresh = TRUE;
break;
case FILEMGMT_SESSIONS:
if (FILEMGMT_SESSIONS == objtypeSelected || FILEMGMT_SESSION == objtypeSelected)
fEnableRefresh = TRUE;
break;
case FILEMGMT_RESOURCES:
if (FILEMGMT_RESOURCES == objtypeSelected || FILEMGMT_RESOURCE == objtypeSelected)
fEnableRefresh = TRUE;
break;
case FILEMGMT_SERVICES:
if (FILEMGMT_SERVICES == objtypeSelected || FILEMGMT_SERVICE == objtypeSelected)
fEnableRefresh = TRUE;
break;
}
if (fEnableRefresh)
{
// Enable the refresh menuitem
VERIFY( SUCCEEDED(m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE)) );
}
}
switch (objtypeSelected)
{
case FILEMGMT_SHARE: // Share was selected
//
// don't enable Properties on the menu whenever SimpleSharingUI appears in NT Explorer
//
if (QueryComponentDataRef().GetIsSimpleUI())
{
VERIFY( SUCCEEDED(m_pConsoleVerb->SetDefaultVerb(MMC_VERB_NONE)) );
break;
}
// fall through
case FILEMGMT_SERVICE: // Service was selected
// Set the default verb to display the properties of the selected object
VERIFY( SUCCEEDED(m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE)) );
VERIFY( SUCCEEDED(m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES)) );
break;
case FILEMGMT_SESSION: // Session was selected
case FILEMGMT_RESOURCE: // Open file was selected
VERIFY( SUCCEEDED(m_pConsoleVerb->SetDefaultVerb(MMC_VERB_NONE)) );
break;
case FILEMGMT_SHARES:
case FILEMGMT_SESSIONS:
case FILEMGMT_RESOURCES:
case FILEMGMT_SERVICES:
case FILEMGMT_ROOT: // Root node was selected
// set the default verb to open/expand the folder
VERIFY( SUCCEEDED(m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN)) );
break;
default: // shouldn't happen
ASSERT(FALSE);
break;
} // switch
} // CFileMgmtComponent::OnNotifySelect()
STDMETHODIMP CFileMgmtComponent::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
{
HRESULT hr = S_OK;
MFC_TRY;
//
// MMC queries us for a multiselect data object (SI_MS_DO) by
// passing the special cookie in this QueryDataObject call.
//
if (IS_SPECIAL_COOKIE(cookie) && MMC_MULTI_SELECT_COOKIE == cookie)
{
CComObject<CFileMgmtDataObject>* pDataObject = NULL;
hr = CComObject<CFileMgmtDataObject>::CreateInstance(&pDataObject);
if (SUCCEEDED(hr))
hr = pDataObject->InitMultiSelectDataObjects(QueryComponentDataRef());
if (SUCCEEDED(hr))
{
//
// We create a multiselect data object (SI_MS_DO), which contains
// an internal list of data objects of selected items.
//
RESULTDATAITEM rdi = {0};
int nIndex = -1;
do
{
ZeroMemory(&rdi, sizeof(RESULTDATAITEM));
rdi.mask = RDI_STATE;
rdi.nCol = 0;
rdi.nIndex = nIndex; // nIndex == -1 to start at first item
rdi.nState = LVIS_SELECTED; // only interested in selected items
hr = m_pResultData->GetNextItem(&rdi);
if (FAILED(hr))
break;
if (rdi.nIndex != -1)
{
//
// rdi is the RESULTDATAITEM of a selected item. its lParam contains the cookie.
// Add it to the internal data object list.
//
CCookie* pbasecookie = reinterpret_cast<CCookie*>(rdi.lParam);
CFileMgmtCookie* pUseThisCookie = QueryComponentDataRef().ActiveCookie((CFileMgmtCookie*)pbasecookie);
pDataObject->AddMultiSelectDataObjects(pUseThisCookie, type);
}
nIndex = rdi.nIndex;
} while (-1 != nIndex);
}
//
// return this SI_MS_DO to MMC
//
if (SUCCEEDED(hr))
hr = pDataObject->QueryInterface(IID_IDataObject, (void **)ppDataObject);
if (FAILED(hr))
delete pDataObject;
}
else
{
// Delegate it to the IComponentData
hr = QueryBaseComponentDataRef().QueryDataObject(cookie, type, ppDataObject);
}
MFC_CATCH;
return hr;
}
STDMETHODIMP CFileMgmtComponent::GetResultViewType(MMC_COOKIE cookie,
BSTR* ppViewType,
long* pViewOptions)
{
*ppViewType = NULL;
//
// we support multiselection in SharedFolders snapin
//
CCookie* pbasecookie = reinterpret_cast<CCookie*>(cookie);
CFileMgmtCookie* pUseThisCookie = QueryComponentDataRef().ActiveCookie((CFileMgmtCookie*)pbasecookie);
FileMgmtObjectType objecttype = pUseThisCookie->QueryObjectType();
if ( FILEMGMT_SHARES == objecttype ||
FILEMGMT_SESSIONS == objecttype ||
FILEMGMT_RESOURCES == objecttype )
{
*pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
} else
{
*pViewOptions = MMC_VIEW_OPTIONS_NONE;
}
return S_FALSE;
}
HRESULT CFileMgmtComponent::Show( CCookie* pcookie, LPARAM arg, HSCOPEITEM /*hScopeItem*/ )
{
TEST_NONNULL_PTR_PARAM(pcookie);
#ifndef SNAPIN_PROTOTYPER
if ( 0 == arg )
{
//
// This is a Hide notification
//
if ( NULL == m_pResultData )
{
ASSERT( FALSE );
return E_UNEXPECTED;
}
// We should not get a Hide notification if we are not currently showing
// CODEWORK see 287399: MMC: two MMCN_SHOW(0) notifications
// ASSERT( (CFileMgmtCookie*)pcookie == m_pViewedCookie );
if ( (CFileMgmtScopeCookie*)pcookie == m_pViewedCookie )
{
//
// Only delete the cookies if no other views are using them
//
pcookie->ReleaseResultChildren();
m_pViewedCookie = NULL;
UpdateDefaultVerbs();
}
return S_OK;
} // if
#else
CPrototyperScopeCookie* pScopeCookie = (CPrototyperScopeCookie*) pcookie;
if (pScopeCookie->m_ScopeType == HTML)
return S_OK;
#endif // SNAPIN_PROTOTYPER
// We should not get a Show notification if we are already showing
if ( NULL != m_pViewedCookie )
{
ASSERT(FALSE);
return S_OK;
}
//
// This is a Show notification
// Build new cookies and insert them into the cookie and the view
//
ASSERT( IsAutonomousObjectType( ((CFileMgmtCookie*)pcookie)->QueryObjectType() ) );
m_pViewedCookie = (CFileMgmtScopeCookie*)pcookie;
LoadColumns( m_pViewedCookie );
UpdateDefaultVerbs();
return PopulateListbox( m_pViewedCookie );
} // CFileMgmtComponent::Show()
HRESULT CFileMgmtComponent::OnNotifyAddImages( LPDATAOBJECT /*lpDataObject*/,
LPIMAGELIST lpImageList,
HSCOPEITEM /*hSelectedItem*/ )
{
return QueryComponentDataRef().LoadIcons(lpImageList,TRUE);
}
/////////////////////////////////////////////////////////////////////
// CODEWORK: Rather than repeating the FPNW calls every time, whether
// or not the FPNW server is running or even installed, I should
// remember whether the server is installed. Andy Herron has
// suggested an API which can determine whether FPNW is installed,
// but it has two drawbacks:
// -- It can only determine whether FPNW is installed anywhere on the
// domain, not on an individual server; and
// -- The API will fail if called by a non-administrator.
//
// JonN 11/1/96
//
HRESULT CFileMgmtComponent::PopulateListbox(CFileMgmtScopeCookie* pcookie)
{
TEST_NONNULL_PTR_PARAM(pcookie);
CWaitCursor cwait;
HRESULT hr = S_OK;
//
// If this is the second view on the same data, just insert the same cookies
// which are in the other views
//
if ( 1 < pcookie->AddRefResultChildren() )
{
hr = InsertResultCookies( *pcookie );
if ( SUCCEEDED(hr) )
hr = m_pResultData->Sort( m_iSortColumn , m_dwSortFlags, 0 );
return hr;
}
INT iTransport;
switch ( pcookie->QueryObjectType() )
{
case FILEMGMT_SHARES:
for (iTransport = FILEMGMT_FIRST_TRANSPORT;
iTransport < FILEMGMT_NUM_TRANSPORTS;
iTransport++)
{
hr = GetFileServiceProvider(iTransport)->PopulateShares(m_pResultData,pcookie);
if( FAILED(hr) )
return hr;
}
break;
case FILEMGMT_SESSIONS:
for (iTransport = FILEMGMT_FIRST_TRANSPORT;
iTransport < FILEMGMT_NUM_TRANSPORTS;
iTransport++)
{
ASSERT( NULL != m_pResultData ); // otherwise we close all sessions
hr = GetFileServiceProvider(iTransport)->EnumerateSessions (
m_pResultData, pcookie, true);
if( FAILED(hr) )
return hr;
}
break;
case FILEMGMT_RESOURCES:
for (iTransport = FILEMGMT_FIRST_TRANSPORT;
iTransport < FILEMGMT_NUM_TRANSPORTS;
iTransport++)
{
ASSERT( NULL != m_pResultData ); // otherwise we close all sessions
hr = GetFileServiceProvider(iTransport)->EnumerateResources(m_pResultData,pcookie);
if( FAILED(hr) )
return hr;
}
break;
case FILEMGMT_SERVICES:
//
// JonN 12/03/98 Service_PopulateServices no longer inserts items into the list
//
hr = QueryComponentDataRef().Service_PopulateServices(m_pResultData, pcookie);
if ( SUCCEEDED(hr) )
hr = InsertResultCookies( *pcookie );
if( FAILED(hr) )
return hr;
#ifdef SNAPIN_PROTOTYPER
case FILEMGMT_PROTOTYPER:
return Prototyper_HrPopulateResultPane(pcookie);
#endif
case FILEMGMT_ROOT:
// We no longer need to explicitly insert these
break;
default:
ASSERT( FALSE );
// fall through
}
return m_pResultData->Sort( m_iSortColumn , m_dwSortFlags, 0 );
} // CFileMgmtComponent::PopulateListbox()
HRESULT CFileMgmtComponent::GetSnapinMultiSelectDataObject(
LPDATAOBJECT i_pMMCMultiSelectDataObject,
LPDATAOBJECT *o_ppSnapinMultiSelectDataObject
)
{
if (!i_pMMCMultiSelectDataObject || !o_ppSnapinMultiSelectDataObject)
return E_INVALIDARG;
*o_ppSnapinMultiSelectDataObject = NULL;
//
// i_pMMCMultiSelectDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL, NULL};
FORMATETC formatetc = {CFileMgmtDataObject::m_CFMultiSelectSnapins, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hr = i_pMMCMultiSelectDataObject->GetData(&formatetc, &stgmedium);
if (SUCCEEDED(hr))
{
if (!stgmedium.hGlobal)
return E_FAIL;
//
// Locate the SI_MS_DO we have provided to MMC in QueryDataObject().
//
SMMCDataObjects *pMMCDO = (SMMCDataObjects*)::GlobalLock(stgmedium.hGlobal);
GUID guidSnapin = GUID_NULL;
VERIFY( SUCCEEDED(QueryComponentDataRef().GetClassID(&guidSnapin)) );
for (int i = 0; i < pMMCDO->count; i++)
{
GUID guid = GUID_NULL;
hr = ExtractData(pMMCDO->lpDataObject[i], CFileMgmtDataObject::m_CFSnapInCLSID, &guid, sizeof(GUID));
if (SUCCEEDED(hr) && guid == guidSnapin)
{
//
// pMMCDO->lpDataObject[i] is the SI_MS_DO we have provided to MMC in QueryDataObject().
//
*o_ppSnapinMultiSelectDataObject = pMMCDO->lpDataObject[i];
(*o_ppSnapinMultiSelectDataObject)->AddRef();
break;
}
}
::GlobalUnlock(stgmedium.hGlobal);
::GlobalFree(stgmedium.hGlobal);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu Implementation
STDMETHODIMP CFileMgmtComponent::AddMenuItems(
IDataObject* piDataObject,
IContextMenuCallback* piCallback,
long* pInsertionAllowed)
{
MFC_TRY;
TRACE_METHOD(CFileMgmtComponent,AddMenuItems);
TEST_NONNULL_PTR_PARAM(piDataObject);
TEST_NONNULL_PTR_PARAM(piCallback);
TEST_NONNULL_PTR_PARAM(pInsertionAllowed);
TRACE( "FileMgmt snapin: extending menu\n" );
HRESULT hr = S_OK;
FileMgmtObjectType objecttype = FILEMGMT_NUMTYPES;
//
// need to find out the object type in case of multiselection
//
BOOL bMultiSelectObject = IsMultiSelectObject(piDataObject);
if (!bMultiSelectObject)
{
objecttype = FileMgmtObjectTypeFromIDataObject(piDataObject);
} else
{
//
// piDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
IDataObject *piSIMSDO = NULL;
hr = GetSnapinMultiSelectDataObject(piDataObject, &piSIMSDO);
if (SUCCEEDED(hr))
{
//
// Note: we assume all multiselected items are of the same type.
//
// Now retrieve data type of the currently selected items
//
STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL, NULL};
FORMATETC formatetc = {CFileMgmtDataObject::m_CFObjectTypesInMultiSelect,
NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
hr = piSIMSDO->GetData(&formatetc, &stgmedium);
if (SUCCEEDED(hr) && stgmedium.hGlobal)
{
BYTE* pb = (BYTE*)::GlobalLock(stgmedium.hGlobal);
GUID* pguid = (GUID*)(pb + sizeof(DWORD)); // skip the 1st DWORD - count
objecttype = (FileMgmtObjectType)CheckObjectTypeGUID(pguid);
::GlobalUnlock(stgmedium.hGlobal);
::GlobalFree(stgmedium.hGlobal);
}
piSIMSDO->Release();
}
}
switch (objecttype)
{
case FILEMGMT_SHARE:
//
// don't add acl-related menu items whenever SimpleSharingUI appears in NT Explorer
//
if (QueryComponentDataRef().GetIsSimpleUI())
break;
if ( CCM_INSERTIONALLOWED_TOP & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_DELETE_SHARE_TOP, IDS_DELETE_SHARE_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
if ( CCM_INSERTIONALLOWED_TASK & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_DELETE_SHARE_TASK, IDS_DELETE_SHARE_TASK,
CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
if ( CCM_INSERTIONALLOWED_NEW & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_NEW_SHARE_NEW, IDS_NEW_SHARE_NEW,
CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
break;
case FILEMGMT_SESSION:
if ( CCM_INSERTIONALLOWED_TOP & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_CLOSE_SESSION_TOP, IDS_CLOSE_SESSION_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
if ( CCM_INSERTIONALLOWED_TASK & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_CLOSE_SESSION_TASK, IDS_CLOSE_SESSION_TASK,
CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
break;
case FILEMGMT_RESOURCE:
if ( CCM_INSERTIONALLOWED_TOP & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_CLOSE_RESOURCE_TOP, IDS_CLOSE_RESOURCE_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
if ( CCM_INSERTIONALLOWED_TASK & (*pInsertionAllowed) )
{
hr = LoadAndAddMenuItem( piCallback, IDS_CLOSE_RESOURCE_TASK, IDS_CLOSE_RESOURCE_TASK,
CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, AfxGetInstanceHandle() );
ASSERT( SUCCEEDED(hr) );
}
break;
case FILEMGMT_SERVICE:
QueryComponentDataRef().Service_FAddMenuItems(piCallback, piDataObject);
break;
#ifdef SNAPIN_PROTOTYPER
case FILEMGMT_PROTOTYPER_LEAF:
Prototyper_AddMenuItems(piCallback, piDataObject);
break;
#endif // SNAPIN_PROTOTYPER
default:
{
DATA_OBJECT_TYPES dataobjecttype = CCT_SCOPE;
hr = ExtractData( piDataObject,
CFileMgmtDataObject::m_CFDataObjectType,
&dataobjecttype,
sizeof(dataobjecttype) );
ASSERT( SUCCEEDED(hr) );
// perhaps this is a scope node in the result pane
hr = QueryComponentDataRef().DoAddMenuItems( piCallback,
objecttype,
dataobjecttype,
pInsertionAllowed,
piDataObject );
}
break;
} // switch
return hr;
MFC_CATCH;
} // CFileMgmtComponent::AddMenuItems()
STDMETHODIMP CFileMgmtComponent::Command(
LONG lCommandID,
IDataObject* piDataObject )
{
MFC_TRY;
TRACE_METHOD(CFileMgmtComponent,Command);
TEST_NONNULL_PTR_PARAM(piDataObject);
TRACE( "CFileMgmtComponent::Command: command %ld selected\n", lCommandID );
#ifdef SNAPIN_PROTOTYPER
Prototyper_ContextMenuCommand(lCommandID, piDataObject);
return S_OK;
#endif
BOOL fFSMRefresh = FALSE;
BOOL fSVCRefresh = FALSE;
switch (lCommandID)
{
case IDS_DELETE_SHARE_TASK:
case IDS_DELETE_SHARE_TOP:
fFSMRefresh = DeleteShare( piDataObject );
break;
case IDS_CLOSE_SESSION_TASK:
case IDS_CLOSE_SESSION_TOP:
fFSMRefresh = CloseSession( piDataObject );
break;
case IDS_CLOSE_RESOURCE_TASK:
case IDS_CLOSE_RESOURCE_TOP:
fFSMRefresh = CloseResource( piDataObject );
break;
case cmServiceStart:
case cmServiceStop:
case cmServicePause:
case cmServiceResume:
case cmServiceRestart:
case cmServiceStartTask:
case cmServiceStopTask:
case cmServicePauseTask:
case cmServiceResumeTask:
case cmServiceRestartTask:
fSVCRefresh = QueryComponentDataRef().Service_FDispatchMenuCommand(lCommandID, piDataObject);
break;
default:
return QueryComponentDataRef().Command(lCommandID, piDataObject);
} // switch
if (fFSMRefresh)
{
//
// In case of multiselect, piDataObject may point to a composite data object (MMC_MS_DO).
// RefreshAllViewsOnSelectedObject will crack down MMC_MS_DO to retrieve SI_MS_DO, then call
// RefreshAllViews on one of the selected objects in the internal list.
//
(void) RefreshAllViewsOnSelectedObject(piDataObject);
}
if (fSVCRefresh)
{
(void) RefreshAllViews( piDataObject );
}
return S_OK;
MFC_CATCH;
} // CFileMgmtComponent::Command()
BOOL CFileMgmtComponent::DeleteShare(LPDATAOBJECT piDataObject)
{
ASSERT( piDataObject != NULL );
BOOL bMultiSelectObject = IsMultiSelectObject(piDataObject);
if (!bMultiSelectObject)
return DeleteThisOneShare(piDataObject, FALSE);
BOOL bRefresh = FALSE;
if (IDYES == DoErrMsgBox(GetActiveWindow(), MB_YESNO, 0, IDS_s_CONFIRM_DELETEMULTISHARES))
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CWaitCursor wait;
//
// piDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
IDataObject *piSIMSDO = NULL;
HRESULT hr = GetSnapinMultiSelectDataObject(piDataObject, &piSIMSDO);
if (SUCCEEDED(hr))
{
CFileMgmtDataObject *pDataObj = NULL;
hr = ExtractData(piSIMSDO, CFileMgmtDataObject::m_CFInternal, &pDataObj, sizeof(pDataObj));
if (SUCCEEDED(hr))
{
//
// get the internal list of data objects of selected items, operate on each one of them.
//
CDataObjectList* pMultiSelectObjList = pDataObj->GetMultiSelectObjList();
for (CDataObjectList::iterator i = pMultiSelectObjList->begin(); i != pMultiSelectObjList->end(); i++)
{
BOOL bDeleted = DeleteThisOneShare(*i, TRUE);
if (bDeleted)
bRefresh = TRUE;
}
}
piSIMSDO->Release();
}
}
return bRefresh;
}
BOOL CFileMgmtComponent::DeleteThisOneShare(LPDATAOBJECT piDataObject, BOOL bQuietMode)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
ASSERT( piDataObject != NULL );
#ifdef DEBUG
{
FileMgmtObjectType objecttype = FileMgmtObjectTypeFromIDataObject(piDataObject);
ASSERT(FILEMGMT_SHARE == objecttype);
}
#endif
CString strServerName;
HRESULT hr = ExtractString( piDataObject, CFileMgmtDataObject::m_CFMachineName, &strServerName, MAX_PATH );
RETURN_FALSE_IF_FAIL;
CString strShareName;
hr = ExtractString( piDataObject, CFileMgmtDataObject::m_CFShareName, &strShareName, MAX_PATH );
RETURN_FALSE_IF_FAIL;
FILEMGMT_TRANSPORT transport;
hr = ExtractData( piDataObject,
CFileMgmtDataObject::m_CFTransport,
&transport,
sizeof(DWORD) );
RETURN_FALSE_IF_FAIL;
BOOL fNetLogonShare = (!lstrcmpi(strShareName, _T("SYSVOL")) || !lstrcmpi(strShareName, _T("NETLOGON")));
BOOL fIPC = FALSE;
BOOL fAdminShare = FALSE;
if (!fNetLogonShare && transport == FILEMGMT_SMB)
{
DWORD dwShareType = 0;
GetFileServiceProvider(transport)->ReadShareType(strServerName, strShareName, &dwShareType);
fAdminShare = (dwShareType & STYPE_SPECIAL);
fIPC = (STYPE_IPC == (dwShareType & STYPE_IPC));
}
if (fIPC)
{
DoErrMsgBox(
GetActiveWindow(),
MB_OK | MB_ICONEXCLAMATION,
0,
IDS_s_DELETE_IPCSHARE
);
return FALSE;
}
if ((fNetLogonShare || fAdminShare) &&
IDYES != DoErrMsgBox(
GetActiveWindow(),
MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2,
0,
(fAdminShare ? IDS_s_CONFIRM_DELETE_ADMINSHARE : IDS_s_CONFIRM_DELETE_NETLOGONSHARE),
strShareName) )
{
return FALSE;
}
if (!bQuietMode &&
IDYES != DoErrMsgBox(
GetActiveWindow(),
MB_YESNO,
0,
IDS_s_CONFIRM_DELETESHARE,
strShareName) )
{
return FALSE;
}
DWORD retval = 0L;
switch (transport)
{
case FILEMGMT_SMB:
case FILEMGMT_FPNW:
case FILEMGMT_SFM:
if (bQuietMode)
{
retval = GetFileServiceProvider(transport)->DeleteShare(strServerName, strShareName);
} else
{
CWaitCursor wait;
retval = GetFileServiceProvider(transport)->DeleteShare(strServerName, strShareName);
}
break;
default:
ASSERT(FALSE);
break;
}
if (0L != retval)
{
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_DELETE_SHARE, strShareName);
return FALSE;
}
return TRUE;
}
BOOL CFileMgmtComponent::CloseSession(LPDATAOBJECT piDataObject)
{
ASSERT( piDataObject != NULL );
BOOL bMultiSelectObject = IsMultiSelectObject(piDataObject);
if (!bMultiSelectObject)
return CloseThisOneSession(piDataObject, FALSE);
BOOL bRefresh = FALSE;
if (IDYES == DoErrMsgBox(GetActiveWindow(), MB_YESNO, 0, IDS_CONFIRM_CLOSEMULTISESSIONS))
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CWaitCursor wait;
//
// piDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
IDataObject *piSIMSDO = NULL;
HRESULT hr = GetSnapinMultiSelectDataObject(piDataObject, &piSIMSDO);
if (SUCCEEDED(hr))
{
CFileMgmtDataObject *pDataObj = NULL;
hr = ExtractData(piSIMSDO, CFileMgmtDataObject::m_CFInternal, &pDataObj, sizeof(pDataObj));
if (SUCCEEDED(hr))
{
//
// get the internal list of data objects of selected items, operate on each one of them.
//
CDataObjectList* pMultiSelectObjList = pDataObj->GetMultiSelectObjList();
for (CDataObjectList::iterator i = pMultiSelectObjList->begin(); i != pMultiSelectObjList->end(); i++)
{
BOOL bDeleted = CloseThisOneSession(*i, TRUE);
if (bDeleted)
bRefresh = TRUE;
}
}
piSIMSDO->Release();
}
}
return bRefresh;
}
BOOL CFileMgmtComponent::CloseThisOneSession(LPDATAOBJECT piDataObject, BOOL bQuietMode)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
ASSERT( piDataObject != NULL );
CCookie* pbasecookie = NULL;
FileMgmtObjectType objecttype = FILEMGMT_ROOT;
HRESULT hr = ExtractBaseCookie( piDataObject, &pbasecookie, &objecttype );
ASSERT( SUCCEEDED(hr) && NULL != pbasecookie && FILEMGMT_SESSION == objecttype );
CFileMgmtResultCookie* pcookie = (CFileMgmtResultCookie*)pbasecookie;
if ( !bQuietMode && IDYES != DoErrMsgBox(GetActiveWindow(), MB_YESNO, 0, IDS_CONFIRM_CLOSESESSION) )
{
return FALSE;
}
FILEMGMT_TRANSPORT transport = FILEMGMT_SMB;
VERIFY( SUCCEEDED( pcookie->GetTransport( &transport ) ) );
DWORD retval = 0;
if (bQuietMode)
{
retval = GetFileServiceProvider(transport)->CloseSession( pcookie );
} else
{
CWaitCursor wait;
retval = GetFileServiceProvider(transport)->CloseSession( pcookie );
}
if (0L != retval)
{
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_CLOSE_SESSION);
return FALSE;
}
return TRUE;
}
BOOL CFileMgmtComponent::CloseResource(LPDATAOBJECT piDataObject)
{
ASSERT( piDataObject != NULL );
BOOL bMultiSelectObject = IsMultiSelectObject(piDataObject);
if (!bMultiSelectObject)
return CloseThisOneResource(piDataObject, FALSE);
BOOL bRefresh = FALSE;
if (IDYES == DoErrMsgBox(GetActiveWindow(), MB_YESNO, 0, IDS_CONFIRM_CLOSEMULTIRESOURCES))
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CWaitCursor wait;
//
// piDataObject is the composite data object (MMC_MS_DO) created by MMC.
// We need to crack it to retrieve the multiselect data object (SI_MS_DO)
// we provided to MMC in QueryDataObject().
//
IDataObject *piSIMSDO = NULL;
HRESULT hr = GetSnapinMultiSelectDataObject(piDataObject, &piSIMSDO);
if (SUCCEEDED(hr))
{
CFileMgmtDataObject *pDataObj = NULL;
hr = ExtractData(piSIMSDO, CFileMgmtDataObject::m_CFInternal, &pDataObj, sizeof(pDataObj));
if (SUCCEEDED(hr))
{
//
// get the internal list of data objects of selected items, operate on each one of them.
//
CDataObjectList* pMultiSelectObjList = pDataObj->GetMultiSelectObjList();
for (CDataObjectList::iterator i = pMultiSelectObjList->begin(); i != pMultiSelectObjList->end(); i++)
{
BOOL bDeleted = CloseThisOneResource(*i, TRUE);
if (bDeleted)
bRefresh = TRUE;
}
}
piSIMSDO->Release();
}
}
return bRefresh;
}
BOOL CFileMgmtComponent::CloseThisOneResource(LPDATAOBJECT piDataObject, BOOL bQuietMode)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
ASSERT( piDataObject != NULL );
CCookie* pbasecookie = NULL;
FileMgmtObjectType objecttype;
HRESULT hr = ExtractBaseCookie( piDataObject, &pbasecookie, &objecttype );
ASSERT( SUCCEEDED(hr) && NULL != pbasecookie && FILEMGMT_RESOURCE == objecttype );
CFileMgmtResultCookie* pcookie = (CFileMgmtResultCookie*)pbasecookie;
if ( !bQuietMode && IDYES != DoErrMsgBox(GetActiveWindow(), MB_YESNO, 0, IDS_CONFIRM_CLOSERESOURCE) )
{
return FALSE;
}
FILEMGMT_TRANSPORT transport = FILEMGMT_SMB;
VERIFY( SUCCEEDED( pcookie->GetTransport( &transport ) ) );
DWORD retval = 0;
if (bQuietMode)
{
retval = GetFileServiceProvider(transport)->CloseResource( pcookie );
} else
{
CWaitCursor wait;
retval = GetFileServiceProvider(transport)->CloseResource( pcookie );
}
if (0L != retval)
{
(void) DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, retval, IDS_POPUP_CLOSE_RESOURCE);
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
/// IExtendPropertySheet
STDMETHODIMP CFileMgmtComponent::QueryPagesFor(LPDATAOBJECT pDataObject)
{
MFC_TRY;
if (NULL == pDataObject)
{
ASSERT(FALSE);
return E_POINTER;
}
HRESULT hr = S_OK;
DATA_OBJECT_TYPES dataobjecttype = CCT_SCOPE;
// extract data from data object
FileMgmtObjectType objecttype = FileMgmtObjectTypeFromIDataObject(pDataObject);
hr = ExtractData( pDataObject, CFileMgmtDataObject::m_CFDataObjectType, &dataobjecttype, sizeof(dataobjecttype) );
ASSERT( SUCCEEDED(hr) );
ASSERT( CCT_SCOPE == dataobjecttype ||
CCT_RESULT == dataobjecttype ||
CCT_SNAPIN_MANAGER == dataobjecttype );
// determine if it needs property pages
switch (objecttype)
{
case FILEMGMT_SESSION:
case FILEMGMT_RESOURCE:
ASSERT(CCT_SNAPIN_MANAGER != dataobjecttype);
return S_FALSE;
case FILEMGMT_SHARE: // now has a property page
{
CString strServerName;
CString strShareName;
FILEMGMT_TRANSPORT transport;
hr = ExtractString(pDataObject, CFileMgmtDataObject::m_CFMachineName, &strServerName, MAX_PATH);
if (SUCCEEDED(hr))
hr = ExtractString(pDataObject, CFileMgmtDataObject::m_CFShareName, &strShareName, MAX_PATH);
if (SUCCEEDED(hr))
hr = ExtractData(pDataObject, CFileMgmtDataObject::m_CFTransport, &transport, sizeof(DWORD));
if (SUCCEEDED(hr))
{
CString strDescription;
CString strPath;
DWORD dwRet = GetFileServiceProvider(transport)->ReadShareProperties(
strServerName,
strShareName,
NULL, // ppvPropertyBlock
strDescription,
strPath,
NULL, // pfEditDescription
NULL, // pfEditPath
NULL // pdwShareType
);
if (NERR_Success == dwRet)
{
return S_OK; // yes, we have a property page to display
} else
{
DoErrMsgBox(GetActiveWindow(), MB_OK | MB_ICONSTOP, dwRet, IDS_POPUP_QUERY_SHARE, strShareName);
if ((FILEMGMT_SMB == transport || FILEMGMT_FPNW == transport) && (NERR_NetNameNotFound == dwRet) ||
(FILEMGMT_SFM == transport) && (AFPERR_VolumeNonExist == dwRet))
{
RefreshAllViews(pDataObject);
}
}
}
return S_FALSE;
}
case FILEMGMT_SERVICE:
ASSERT(CCT_SNAPIN_MANAGER != dataobjecttype);
return S_OK;
#ifdef SNAPIN_PROTOTYPER
case FILEMGMT_PROTOTYPER_LEAF:
return S_OK;
#endif
default:
break;
}
ASSERT(FALSE);
return S_FALSE;
MFC_CATCH;
}
STDMETHODIMP CFileMgmtComponent::CreatePropertyPages(
LPPROPERTYSHEETCALLBACK pCallBack,
LONG_PTR handle, // This handle must be saved in the property page object to notify the parent when modified
LPDATAOBJECT pDataObject)
{
MFC_TRY;
if (NULL == pCallBack || NULL == pDataObject)
{
ASSERT(FALSE);
return E_POINTER;
}
HRESULT hr;
// extract data from data object
FileMgmtObjectType objecttype = FileMgmtObjectTypeFromIDataObject(pDataObject);
DATA_OBJECT_TYPES dataobjecttype = CCT_SCOPE;
hr = ExtractData( pDataObject, CFileMgmtDataObject::m_CFDataObjectType, &dataobjecttype, sizeof(dataobjecttype) );
ASSERT( SUCCEEDED(hr) );
ASSERT( CCT_SCOPE == dataobjecttype ||
CCT_RESULT == dataobjecttype ||
CCT_SNAPIN_MANAGER == dataobjecttype );
// determine if it needs property pages
switch (objecttype)
{
case FILEMGMT_SHARE:
{
CWaitCursor cwait;
if (CCT_SNAPIN_MANAGER == dataobjecttype)
{
ASSERT(FALSE);
return E_UNEXPECTED;
}
FILEMGMT_TRANSPORT transport;
hr = ExtractData( pDataObject,
CFileMgmtDataObject::m_CFTransport,
&transport,
sizeof(DWORD) );
if ( FAILED(hr) )
{
ASSERT( FALSE );
return E_UNEXPECTED;
}
// CODEWORK probably not necessary to split off transport at this point
GetFileServiceProvider(transport)->DisplayShareProperties(pCallBack, pDataObject, handle);
return S_OK;
}
case FILEMGMT_SESSION:
case FILEMGMT_RESOURCE:
ASSERT(FALSE);
return E_UNEXPECTED;
case FILEMGMT_SERVICE:
if (CCT_RESULT != dataobjecttype)
{
ASSERT(FALSE);
return E_UNEXPECTED;
}
if (!QueryComponentDataRef().Service_FInsertPropertyPages(OUT pCallBack, IN pDataObject, handle))
{
// Unable to open the service and query service info
return S_FALSE;
}
return S_OK;
default:
break;
}
ASSERT(FALSE);
return S_FALSE;
MFC_CATCH;
}
STDMETHODIMP CFileMgmtComponent::Compare(
LPARAM /*lUserParam*/, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* pnResult)
{
ASSERT(NULL != pnResult);
// WARNING cookie cast
CCookie* pBaseCookieA = reinterpret_cast<CCookie*>(cookieA);
CCookie* pBaseCookieB = reinterpret_cast<CCookie*>(cookieB);
ASSERT( NULL != pBaseCookieA && NULL != pBaseCookieB );
CFileMgmtCookie* pCookieA = QueryComponentDataRef().ActiveCookie(
(CFileMgmtCookie*)pBaseCookieA);
CFileMgmtCookie* pCookieB = QueryComponentDataRef().ActiveCookie(
(CFileMgmtCookie*)pBaseCookieB);
ASSERT( NULL != pCookieA && NULL != pCookieB );
FileMgmtObjectType objecttypeA = pCookieA->QueryObjectType();
FileMgmtObjectType objecttypeB = pCookieB->QueryObjectType();
ASSERT( IsValidObjectType(objecttypeA) && IsValidObjectType(objecttypeB) );
if (objecttypeA != objecttypeB)
{
// assign an arbitrary ordering to cookies with different nodetypes
*pnResult = ((int)objecttypeA) - ((int)objecttypeB);
return S_OK;
}
return pCookieA->CompareSimilarCookies( pBaseCookieB, pnResult);
}
STDMETHODIMP CFileMgmtComponent::GetProperty(
/* [in] */ LPDATAOBJECT pDataObject,
/* [in] */ BSTR szPropertyName,
/* [out] */ BSTR* pbstrProperty)
{
if ( IsBadReadPtr(pDataObject,sizeof(*pDataObject))
|| IsBadStringPtr(szPropertyName,0x7FFFFFFF)
|| IsBadWritePtr(pbstrProperty,sizeof(*pbstrProperty))
)
{
ASSERT(FALSE);
return E_POINTER;
}
CCookie* pbasecookie = NULL;
HRESULT hr = ExtractBaseCookie( pDataObject, &pbasecookie );
RETURN_HR_IF_FAIL;
ASSERT(NULL != pbasecookie);
CFileMgmtCookie* pcookie = (CFileMgmtCookie*)pbasecookie;
CString strProperty;
if (!_wcsicmp(L"CCF_HTML_DETAILS",szPropertyName))
{
if (FILEMGMT_SERVICE != pcookie->QueryObjectType())
return S_FALSE;
if (NULL == QueryComponentDataRef().m_hScManager)
{
ASSERT(FALSE);
return S_FALSE;
}
CString strServiceName;
if (!QueryComponentDataRef().Service_FGetServiceInfoFromIDataObject(
pDataObject,
NULL,
OUT &strServiceName,
NULL))
{
ASSERT(FALSE);
return S_FALSE;
}
BOOL rgfMenuFlags[iServiceActionMax];
::ZeroMemory(rgfMenuFlags,sizeof(rgfMenuFlags));
AFX_MANAGE_STATE(AfxGetStaticModuleState()); // required for CWaitCursor
CWaitCursor wait;
if (!Service_FGetServiceButtonStatus( // this will report errors itself
QueryComponentDataRef().m_hScManager,
strServiceName,
OUT rgfMenuFlags,
NULL, // pdwCurrentState
TRUE)) // fSilentError
{
return S_FALSE;
}
for (INT i = 0; i < iServiceActionMax; i++)
{
if (rgfMenuFlags[i])
{
CString strTemp;
VERIFY(strTemp.LoadString(IDS_HTML_DETAILS_START+i));
strProperty += strTemp;
}
}
}
else if (!_wcsicmp(L"CCF_DESCRIPTION",szPropertyName))
{
hr = pcookie->GetExplorerViewDescription( strProperty );
}
else
{
return S_FALSE; // unknown strPropertyName
}
*pbstrProperty = ::SysAllocString(strProperty);
return S_OK;
}
/////////////////////////////////////////////////////////////////////
// Virtual function called by CComponent::IComponent::Notify(MMCN_COLUMN_CLICK)
HRESULT CFileMgmtComponent::OnNotifyColumnClick( LPDATAOBJECT /*lpDataObject*/, LPARAM iColumn, LPARAM uFlags )
{
m_iSortColumn = (int)iColumn;
m_dwSortFlags = (DWORD) uFlags;
return m_pResultData->Sort ((int)iColumn, (DWORD)uFlags, 0);
}
HRESULT CFileMgmtComponent::OnNotifySnapinHelp (LPDATAOBJECT /*pDataObject*/)
{
return ShowHelpTopic( IsServiceSnapin()
? L"sys_srv_overview.htm"
: L"file_srv_overview.htm" );
}