Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

494 lines
16 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N O T I F Y . C P P
//
// Contents: Implementation of INetConnectionNotifySink
//
// Notes:
//
// Author: shaunco 21 Aug 1998
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "foldinc.h"
#include "webview.h"
#include "foldres.h" // Folder resource IDs
#include "nsres.h" // Netshell strings
#include "cfutils.h" // Connection folder utility functions
#include "wininet.h"
#include "cmdtable.h"
// WVTI_ENTRY - Use for tasks that want to be displayed when something is selected, where the UI is
// independent of the selection
// WVTI_ENTRY_NOSELECTION - Use for tasks that want to be displayed when nothing is selected
// WVTI_ENTRY_FILE - Use for tasks that want to be displayed when a file is selected
// WVTI_ENTRY_TITLE - Use for tasks that want to be displayed when something is selected,
// and you want different UI depending on the selection or if you want to control the title,
// but the tooltip is constant
// WVTI_ENTRY_ALL - Use this one if you want the same text everywhere
// WVTI_ENTRY_ALL_TITLE - Use this one if you want to control everything
// WVTI_HEADER - Use this one for a header
// WVTI_HEADER_ENTRY - Use this one for a header that changes with the selection
const WVTASKITEM c_ConnFolderGlobalTaskHeader =
WVTI_HEADER(L"netshell.dll", // module where the resources are
IDS_WV_TITLE_NETCONFOLDERTASKS, // static header for all cases
IDS_WV_TITLE_NETCONFOLDERTASKS_TT // tooltip
);
const WVTASKITEM c_ConnFolderItemTaskHeader =
WVTI_HEADER(L"netshell.dll", // module where the resources are
IDS_WV_TITLE_NETCONITEMTASKS, // static header for all cases
IDS_WV_TITLE_NETCONITEMTASKS_TT // tooltip
);
const WVTASKITEM c_ConnFolderIntro =
WVTI_HEADER(L"netshell.dll", // module where the resources are
IDS_WV_NETCON_INTRO, // static header for all cases
IDS_WV_NETCON_INTRO // tooltip
);
// Use for tasks that want to be displayed when a file is selected
//#define WVTI_ENTRY_FILE(g, d, t, p, i, s, k) {&(g), (d), (0), (t), (0), (0), (p), (i), (s), (k)}
#define NCWVIEW_ENTRY_FILE(t, mt, i, cmd) \
{&GUID_NULL, L"netshell.dll", (0), (t), (0), (mt), (IDS_##cmd), (i), (CNCWebView::CanShow##cmd), (CNCWebView::On##cmd) }
const WVTASKITEM c_ConnFolderGlobalTaskList[] =
{
WVTI_ENTRY_ALL(
GUID_NULL, // command GUID
// Future thinking - something like this is the way Context Menus are done.
// Be a way to get access to DefView implementation of functions - IUICmdTarget.
L"netshell.dll", // module
IDS_WV_MNCWIZARD, // text
IDS_CMIDM_NEW_CONNECTION, // tooltip
IDI_WV_MNCWIZARD, // icon
CANSHOW_HANDLER_OF(CMIDM_NEW_CONNECTION),
INVOKE_HANDLER_OF(CMIDM_NEW_CONNECTION)),
WVTI_ENTRY_ALL(
GUID_NULL, // command GUID
L"netshell.dll", // module
IDS_WV_HOMENET, // text
IDS_CMIDM_HOMENET_WIZARD, // tooltip
IDI_WV_HOMENET, // icon
CANSHOW_HANDLER_OF(CMIDM_HOMENET_WIZARD),
INVOKE_HANDLER_OF(CMIDM_HOMENET_WIZARD)),
// Single-select Name ,Multi-select name ,Icon , Verb
NCWVIEW_ENTRY_FILE(IDS_WV_CONNECT ,IDS_WM_CONNECT ,IDI_WV_CONNECT , CMIDM_CONNECT),
NCWVIEW_ENTRY_FILE(IDS_WV_DISCONNECT ,IDS_WM_DISCONNECT ,IDI_WV_DISCONNECT , CMIDM_DISCONNECT),
NCWVIEW_ENTRY_FILE(IDS_WV_ENABLE ,IDS_WM_ENABLE ,IDI_WV_ENABLE , CMIDM_ENABLE),
NCWVIEW_ENTRY_FILE(IDS_WV_DISABLE ,IDS_WM_DISABLE ,IDI_WV_DISABLE , CMIDM_DISABLE),
NCWVIEW_ENTRY_FILE(IDS_WV_REPAIR ,IDS_WM_REPAIR ,IDI_WV_REPAIR , CMIDM_FIX),
NCWVIEW_ENTRY_FILE(IDS_WV_RENAME ,IDS_WM_RENAME ,IDI_WV_RENAME , CMIDM_RENAME),
NCWVIEW_ENTRY_FILE(IDS_WV_STATUS ,IDS_WM_STATUS ,IDI_WV_STATUS , CMIDM_STATUS),
NCWVIEW_ENTRY_FILE(IDS_WV_DELETE ,IDS_WM_DELETE ,IDI_WV_DELETE , CMIDM_DELETE),
NCWVIEW_ENTRY_FILE(IDS_WV_PROPERTIES ,IDS_WM_PROPERTIES ,IDI_WV_PROPERTIES , CMIDM_PROPERTIES)
};
DWORD c_aOtherPlaces[] =
{
CSIDL_CONTROLS,
CSIDL_NETWORK,
CSIDL_PERSONAL,
CSIDL_DRIVES
};
extern const DWORD c_dwCountOtherPlaces = celems(c_aOtherPlaces);
const WVTASKITEM c_ConnFolderItemTaskList[] =
{
WVTI_ENTRY_ALL(
GUID_NULL, // command GUID
L"netshell.dll", // module
IDS_WV_TROUBLESHOOT, // text
IDS_CMIDM_NET_TROUBLESHOOT, // tooltip
IDI_WV_TROUBLESHOOT, // icon
CANSHOW_HANDLER_OF(CMIDM_NET_TROUBLESHOOT),
INVOKE_HANDLER_OF(CMIDM_NET_TROUBLESHOOT))
};
CNCWebView::CNCWebView(IN CConnectionFolder* pConnectionFolder) throw()
{
Assert(pConnectionFolder);
Assert(c_dwCountOtherPlaces <= MAXOTHERPLACES);
m_pConnectionFolder = pConnectionFolder;
// zero the PIDLs array to other places section in the webview
ZeroMemory(m_apidlOtherPlaces, sizeof(m_apidlOtherPlaces));
}
CNCWebView::~CNCWebView() throw()
{
// check to destroy the other places PIDLs
DestroyOtherPlaces();
}
IMPLEMENT_WEBVIEW_HANDLERS(TOPLEVEL, CNCWebView, CMIDM_NEW_CONNECTION);
IMPLEMENT_WEBVIEW_HANDLERS(TOPLEVEL, CNCWebView, CMIDM_HOMENET_WIZARD);
IMPLEMENT_WEBVIEW_HANDLERS(TOPLEVEL, CNCWebView, CMIDM_NET_TROUBLESHOOT);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_FIX);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_CONNECT);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_DISCONNECT);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_ENABLE);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_DISABLE);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_RENAME);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_DELETE);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_STATUS);
IMPLEMENT_WEBVIEW_HANDLERS(TASKLEVEL, CNCWebView, CMIDM_PROPERTIES);
HRESULT CNCWebView::OnNull(IN IUnknown* pv, OUT IShellItemArray *psiItemArray, OUT IBindCtx *pbc)
{
return S_OK;
}
STDMETHODIMP CNCWebView::RealMessage(IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
{
switch (uMsg)
{
HANDLE_MSG(0, SFVM_GETWEBVIEWLAYOUT, OnGetWebViewLayout);
HANDLE_MSG(0, SFVM_GETWEBVIEWCONTENT, OnGetWebViewContent);
HANDLE_MSG(0, SFVM_GETWEBVIEWTASKS, OnGetWebViewTasks);
default:
return E_FAIL;
}
}
STDMETHODIMP CNCWebView::CreateOtherPlaces(OUT LPDWORD pdwCount)
{
TraceFileFunc(ttidMenus);
// first verify if created already
HRESULT hr = S_OK;
Assert(pdwCount);
if (!pdwCount)
{
return E_INVALIDARG;
}
if( NULL == m_apidlOtherPlaces[0] )
{
*pdwCount = 0;
// create the PIDLs to other places section in the webview
ZeroMemory(m_apidlOtherPlaces, sizeof(m_apidlOtherPlaces));
for (int dwPlaces = 0; dwPlaces < c_dwCountOtherPlaces; dwPlaces++)
{
if (SUCCEEDED(hr = SHGetSpecialFolderLocation(NULL, c_aOtherPlaces[dwPlaces], &(m_apidlOtherPlaces[*pdwCount]))))
{
(*pdwCount)++;
}
else
{
m_apidlOtherPlaces[*pdwCount] = NULL;
TraceHr(ttidError, FAL, hr, FALSE, "CNCWebView::CreateOtherPlaces : 0x%04x", c_aOtherPlaces[dwPlaces]);
}
}
if (FAILED(hr) && (*pdwCount))
{
hr = S_FALSE; // not a big deal if at least one worked.
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CNCWebView::CreateOtherPlaces - all places failed");
return hr;
}
STDMETHODIMP CNCWebView::DestroyOtherPlaces()
{
for (ULONG i = 0; i < c_dwCountOtherPlaces; i++)
{
if (m_apidlOtherPlaces[i])
{
LPMALLOC pMalloc;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
pMalloc->Free(m_apidlOtherPlaces[i]);
}
}
}
ZeroMemory(m_apidlOtherPlaces, sizeof(m_apidlOtherPlaces));
return S_OK;
}
STDMETHODIMP CNCWebView::OnGetWebViewLayout(IN DWORD pv, IN UINT uViewMode, OUT SFVM_WEBVIEW_LAYOUT_DATA* pData)
{
ZeroMemory(pData, sizeof(*pData));
pData->dwLayout = SFVMWVL_NORMAL | SFVMWVL_DETAILS;
return S_OK;
}
STDMETHODIMP CNCWebView::OnGetWebViewTasks(IN DWORD pv, OUT SFVM_WEBVIEW_TASKSECTION_DATA* pTasks)
{
TraceFileFunc(ttidShellViewMsgs);
HRESULT hr = S_OK;
ZeroMemory(pTasks, sizeof(*pTasks));
CComPtr<IUnknown> pUnk;
hr = reinterpret_cast<LPSHELLFOLDER>(m_pConnectionFolder)->QueryInterface(IID_IUnknown, reinterpret_cast<LPVOID *>(&pUnk));
if (SUCCEEDED(hr))
{
if (FAILED(hr = Create_IEnumUICommand(pUnk, c_ConnFolderItemTaskList, celems(c_ConnFolderItemTaskList), &pTasks->penumFolderTasks)) ||
FAILED(hr = Create_IEnumUICommand(pUnk, c_ConnFolderGlobalTaskList, celems(c_ConnFolderGlobalTaskList), &pTasks->penumSpecialTasks)) )
{
// something has failed - cleanup
IUnknown_SafeReleaseAndNullPtr(pTasks->penumFolderTasks);
IUnknown_SafeReleaseAndNullPtr(pTasks->penumSpecialTasks);
}
}
Assert(S_OK == hr);
TraceHr(ttidError, FAL, hr, FALSE, "HrOnGetWebViewTasks");
return hr;
}
STDMETHODIMP CNCWebView::OnGetWebViewContent(IN DWORD pv, OUT SFVM_WEBVIEW_CONTENT_DATA* pData)
{
TraceFileFunc(ttidShellViewMsgs);
HRESULT hr = S_OK;
ZeroMemory(pData, sizeof(*pData));
DWORD dwCountOtherPlaces;
hr = CreateOtherPlaces(&dwCountOtherPlaces);
if (SUCCEEDED(hr))
{
hr = E_OUTOFMEMORY;
LPCITEMIDLIST *papidl = reinterpret_cast<LPCITEMIDLIST*>(LocalAlloc(LPTR, sizeof(m_apidlOtherPlaces)));
if (papidl)
{
// CEnumArray::CreateInstance is taking the ownership of the array of PIDLs passed
// this function requires 2 things:
//
// 1. the caller should allocate the passed array with LocalAlloc
// 2. the lifetime of the PIDLs passed should span the folder's lifetime
//
CopyMemory(papidl, &m_apidlOtherPlaces, sizeof(m_apidlOtherPlaces));
hr = CEnumArray::CreateInstance(&pData->penumOtherPlaces, papidl, dwCountOtherPlaces);
if (FAILED(hr))
{
LocalFree(papidl);
}
}
if (FAILED(hr) ||
FAILED(hr = Create_IUIElement(&c_ConnFolderGlobalTaskHeader, &pData->pSpecialTaskHeader)) ||
FAILED(hr = Create_IUIElement(&c_ConnFolderItemTaskHeader, &pData->pFolderTaskHeader)) ||
FAILED(hr = Create_IUIElement(&c_ConnFolderIntro, &pData->pIntroText)) )
{
// something has failed - cleanup
DestroyOtherPlaces();
IUnknown_SafeReleaseAndNullPtr(pData->pIntroText);
IUnknown_SafeReleaseAndNullPtr(pData->pSpecialTaskHeader);
IUnknown_SafeReleaseAndNullPtr(pData->pFolderTaskHeader);
IUnknown_SafeReleaseAndNullPtr(pData->penumOtherPlaces);
}
}
Assert(S_OK == hr);
TraceHr(ttidError, FAL, hr, FALSE, "HrOnGetWebViewContent");
return hr;
}
HRESULT CNCWebView::WebviewVerbInvoke(IN DWORD dwVerbID, IN IUnknown* pv, IN IShellItemArray *psiItemArray)
{
HRESULT hr = E_NOINTERFACE;
CComPtr<IShellFolderViewCB> pShellFolderViewCB;
hr = pv->QueryInterface(IID_IShellFolderViewCB, reinterpret_cast<LPVOID *>(&pShellFolderViewCB));
if (SUCCEEDED(hr))
{
hr = pShellFolderViewCB->MessageSFVCB(DVM_INVOKECOMMAND, dwVerbID, NULL);
}
Assert(S_OK == hr);
return hr;
}
HRESULT CNCWebView::WebviewVerbCanInvoke(IN DWORD dwVerbID, IN IUnknown* pv, OUT IShellItemArray *psiItemArray, IN BOOL fOkToBeSlow, OUT UISTATE* puisState, BOOL bLevel)
{
HRESULT hr = E_NOINTERFACE;
CComPtr<IShellFolderViewCB> pShellFolderViewCB;
hr = pv->QueryInterface(IID_IShellFolderViewCB, reinterpret_cast<LPVOID *>(&pShellFolderViewCB));
if (SUCCEEDED(hr))
{
NCCS_STATE nccsState;
hr = pShellFolderViewCB->MessageSFVCB(bLevel ? MYWM_QUERYINVOKECOMMAND_TOPLEVEL : MYWM_QUERYINVOKECOMMAND_ITEMLEVEL, dwVerbID, reinterpret_cast<LPARAM>(&nccsState) );
if (S_OK != hr)
{
*puisState = UIS_HIDDEN;
}
else
{
switch (nccsState)
{
case NCCS_DISABLED:
*puisState = UIS_DISABLED;
break;
case NCCS_ENABLED:
*puisState = UIS_ENABLED;
break;
case NCCS_NOTSHOWN:
*puisState = UIS_HIDDEN;
break;
default:
AssertSz(FALSE, "Invalid value for NCCS_STATE");
}
}
}
Assert(S_OK == hr);
return hr;
}
HRESULT CEnumArray::CreateInstance(
OUT IEnumIDList** ppv,
IN TAKEOWNERSHIP LPCITEMIDLIST *ppidl,
IN UINT cItems)
{
TraceFileFunc(ttidShellViewMsgs);
HRESULT hr = E_OUTOFMEMORY;
CEnumArray * pObj = NULL;
pObj = new CComObject<CEnumArray>;
if (pObj)
{
// Do the standard CComCreator::CreateInstance stuff.
//
pObj->SetVoid (NULL);
pObj->InternalFinalConstructAddRef ();
hr = pObj->FinalConstruct ();
pObj->InternalFinalConstructRelease ();
if (SUCCEEDED(hr))
{
pObj->_cRef = 1;
pObj->_ppidl = ppidl; // takes ownership of ppidl!
pObj->_cItems = cItems;
pObj->Reset();
hr = pObj->QueryInterface (IID_IEnumIDList, reinterpret_cast<LPVOID *>(ppv));
}
if (FAILED(hr))
{
delete pObj;
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CEnumArray::CreateInstance");
return hr;
}
CEnumArray::CEnumArray()
{
_ppidl = NULL;
}
CEnumArray::~CEnumArray()
{
if (_ppidl)
{
LocalFree(_ppidl);
}
}
STDMETHODIMP CEnumArray::Next(IN ULONG celt, OUT LPITEMIDLIST *ppidl, OUT ULONG *pceltFetched)
{
HRESULT hr = S_FALSE;
if (_ppidl && (_ulIndex < _cItems))
{
*ppidl = ILClone(_ppidl[_ulIndex++]);
if (ppidl)
{
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (pceltFetched)
{
*pceltFetched = (hr == S_OK) ? 1 : 0;
}
return hr;
}
STDMETHODIMP CEnumArray::Skip(IN ULONG celt)
{
_ulIndex = min(_cItems, _ulIndex+celt);
return S_OK;
}
STDMETHODIMP CEnumArray::Reset()
{
_ulIndex = 0;
return S_OK;
}
STDMETHODIMP CEnumArray::Clone(OUT IEnumIDList **ppenum)
{
// We can not clone this array, since we don't own references to the pidls
*ppenum = NULL;
return E_NOTIMPL;
}
HRESULT HrIsWebViewEnabled()
{
SHELLSTATE ss={0};
// SSF_HIDDENFILEEXTS and SSF_SORTCOLUMNS don't work with
// the SHELLFLAGSTATE struct, make sure they are off
// (because the corresponding SHELLSTATE fields don't
// exist in SHELLFLAGSTATE.)
//
DWORD dwMask = SSF_WEBVIEW;
SHGetSetSettings(&ss, dwMask, FALSE);
if (ss.fWebView)
{
return S_OK;
}
else
{
return S_FALSE;
}
}