reactos/dll/shellext/netshell/shfldr_netconnect.cpp

1206 lines
35 KiB
C++

/*
* Network Connections Shell Folder
*
* Copyright 2008 Johannes Anderwald <johannes.anderwald@reactos.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "precomp.h"
#define MAX_PROPERTY_SHEET_PAGE (10)
/***********************************************************************
* IShellFolder implementation
*/
class CNetworkConnections final :
public IPersistFolder2,
public IShellFolder2,
public IShellExecuteHookW
{
public:
CNetworkConnections();
/* IUnknown */
virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
virtual ULONG WINAPI AddRef();
virtual ULONG WINAPI Release();
// IShellFolder
virtual HRESULT WINAPI ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes);
virtual HRESULT WINAPI EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList);
virtual HRESULT WINAPI BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
virtual HRESULT WINAPI BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
virtual HRESULT WINAPI CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2);
virtual HRESULT WINAPI CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut);
virtual HRESULT WINAPI GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut);
virtual HRESULT WINAPI GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut);
virtual HRESULT WINAPI GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet);
virtual HRESULT WINAPI SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut);
/* IShellFolder2 */
virtual HRESULT WINAPI GetDefaultSearchGUID(GUID *pguid);
virtual HRESULT WINAPI EnumSearches(IEnumExtraSearch **ppenum);
virtual HRESULT WINAPI GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay);
virtual HRESULT WINAPI GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags);
virtual HRESULT WINAPI GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv);
virtual HRESULT WINAPI GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd);
virtual HRESULT WINAPI MapColumnToSCID(UINT column, SHCOLUMNID *pscid);
// IPersistFolder2
virtual HRESULT WINAPI GetClassID(CLSID *lpClassId);
virtual HRESULT WINAPI Initialize(PCIDLIST_ABSOLUTE pidl);
virtual HRESULT WINAPI GetCurFolder(PIDLIST_ABSOLUTE *pidl);
// IShellExecuteHookW
virtual HRESULT WINAPI Execute(LPSHELLEXECUTEINFOW pei);
private:
~CNetworkConnections();
LONG m_ref;
/* both paths are parsible from the desktop */
PIDLIST_ABSOLUTE m_pidlRoot;
IOleCommandTarget *m_lpOleCmd;
};
class CNetConUiObject final :
public IContextMenu3,
public IObjectWithSite,
public IQueryInfo,
public IExtractIconW
{
public:
CNetConUiObject(PCUITEMID_CHILD pidl, IOleCommandTarget *lpOleCmd);
// IUnknown
virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
virtual ULONG WINAPI AddRef();
virtual ULONG WINAPI Release();
// IContextMenu3
virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
virtual HRESULT WINAPI HandleMenuMsg( UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// IObjectWithSite
virtual HRESULT WINAPI SetSite(IUnknown *punk);
virtual HRESULT WINAPI GetSite(REFIID iid, void **ppvSite);
// IQueryInfo
virtual HRESULT WINAPI GetInfoFlags(DWORD *pdwFlags);
virtual HRESULT WINAPI GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip);
// IExtractIconW
virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
virtual HRESULT STDMETHODCALLTYPE Extract(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
private:
~CNetConUiObject();
LONG m_ref;
PCUITEMID_CHILD m_pidl;
IUnknown *m_pUnknown;
IOleCommandTarget *m_lpOleCmd;
};
static const shvheader NetConnectSFHeader[] = {
{IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 20},
{IDS_SHV_COLUMN_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 8},
{IDS_SHV_COLUMN_STATE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_DEVNAME, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
{IDS_SHV_COLUMN_PHONE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_OWNER, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
};
#define NETCONNECTSHELLVIEWCOLUMNS 6
#define COLUMN_NAME 0
#define COLUMN_TYPE 1
#define COLUMN_STATUS 2
#define COLUMN_DEVNAME 3
#define COLUMN_PHONE 4
#define COLUMN_OWNER 5
HRESULT ShowNetConnectionStatus(IOleCommandTarget * lpOleCmd, INetConnection * pNetConnect, HWND hwnd);
CNetworkConnections::CNetworkConnections() :
m_ref(0),
m_pidlRoot(_ILCreateNetConnect())
{
HRESULT hr;
hr = CoCreateInstance(CLSID_ConnectionTray, NULL, CLSCTX_INPROC_SERVER, IID_IOleCommandTarget, reinterpret_cast<PVOID*>(&m_lpOleCmd));
if (FAILED(hr))
{
ERR("CoCreateInstance failed with %lx\n", hr);
m_lpOleCmd = NULL;
}
}
CNetworkConnections::~CNetworkConnections()
{
if (m_lpOleCmd)
m_lpOleCmd->Release();
SHFree(m_pidlRoot);
}
/**************************************************************************
* ISF_NetConnect_fnQueryInterface
*
* NOTE
* supports not IPersist/IPersistFolder
*/
HRESULT WINAPI CNetworkConnections::QueryInterface(REFIID riid, LPVOID *ppvObj)
{
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID (riid, IID_IPersist) ||
IsEqualIID (riid, IID_IPersistFolder) ||
IsEqualIID (riid, IID_IPersistFolder2))
{
*ppvObj = static_cast<IPersistFolder2*>(this);
}
else if (IsEqualIID(riid, IID_IShellFolder) ||
IsEqualIID(riid, IID_IShellFolder2))
{
*ppvObj = static_cast<IShellFolder2*>(this);
}
else if (IsEqualIID(riid, IID_IShellExecuteHookW))
{
*ppvObj = static_cast<IShellExecuteHookW*>(this);
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
/* TODO:
* IID_IShellExtInit
* IID_IOleCommandTarget
* IID_IShellFolderViewCB
*/
return E_NOINTERFACE;
}
ULONG WINAPI CNetworkConnections::AddRef()
{
ULONG refCount = InterlockedIncrement(&m_ref);
return refCount;
}
ULONG WINAPI CNetworkConnections::Release()
{
ULONG refCount = InterlockedDecrement(&m_ref);
if (!refCount)
delete this;
return refCount;
}
/**************************************************************************
* ISF_NetConnect_fnParseDisplayName
*/
HRESULT WINAPI CNetworkConnections::ParseDisplayName (
HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
{
HRESULT hr = E_UNEXPECTED;
*ppidl = 0;
if (pchEaten)
*pchEaten = 0; /* strange but like the original */
return hr;
}
/**************************************************************************
* CreateNetConnectEnumList()
*/
static BOOL CreateNetConnectEnumList(CEnumIDList *list, DWORD dwFlags)
{
HRESULT hr;
INetConnectionManager *pNetConMan;
IEnumNetConnection *pEnumCon;
INetConnection *INetCon;
ULONG Count;
PITEMID_CHILD pidl;
/* get an instance to of IConnectionManager */
hr = INetConnectionManager_Constructor(NULL, IID_INetConnectionManager, (LPVOID*)&pNetConMan);
if (FAILED(hr))
return FALSE;
hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
if (FAILED(hr))
{
pNetConMan->Release();
return FALSE;
}
do
{
hr = pEnumCon->Next(1, &INetCon, &Count);
if (hr == S_OK)
{
pidl = ILCreateNetConnectItem(INetCon);
if (pidl)
{
list->AddToEnumList(pidl);
}
}
else
{
break;
}
} while (TRUE);
pEnumCon->Release();
pNetConMan->Release();
return TRUE;
}
/**************************************************************************
* ISF_NetConnect_fnEnumObjects
*/
HRESULT WINAPI CNetworkConnections::EnumObjects(
HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
{
CEnumIDList *pList = new CEnumIDList;
*ppEnumIDList = static_cast<LPENUMIDLIST>(pList);
if (!pList)
return E_OUTOFMEMORY;
pList->AddRef();
CreateNetConnectEnumList(pList, dwFlags);
return S_OK;
}
/**************************************************************************
* ISF_NetConnect_fnBindToObject
*/
HRESULT WINAPI CNetworkConnections::BindToObject (
PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
return E_NOTIMPL;
}
/**************************************************************************
* ISF_NetConnect_fnBindToStorage
*/
HRESULT WINAPI CNetworkConnections::BindToStorage(
PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
{
*ppvOut = NULL;
return E_NOTIMPL;
}
/**************************************************************************
* ISF_NetConnect_fnCompareIDs
*/
HRESULT WINAPI CNetworkConnections::CompareIDs(
LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
{
return E_NOTIMPL;
}
/**************************************************************************
* ISF_NetConnect_fnCreateViewObject
*/
HRESULT WINAPI CNetworkConnections::CreateViewObject(
HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
{
CSFV cvf;
HRESULT hr = E_NOINTERFACE;
if (!ppvOut)
return hr;
*ppvOut = NULL;
if (IsEqualIID(riid, IID_IShellView))
{
ZeroMemory(&cvf, sizeof(cvf));
cvf.cbSize = sizeof(cvf);
cvf.pshf = static_cast<IShellFolder*>(this);
IShellView* pShellView;
hr = SHCreateShellFolderViewEx(&cvf, &pShellView);
if (SUCCEEDED(hr))
{
hr = pShellView->QueryInterface(riid, ppvOut);
pShellView->Release();
}
}
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnGetAttributesOf
*/
HRESULT WINAPI CNetworkConnections::GetAttributesOf(
UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
{
//IGenericSFImpl *This = (IGenericSFImpl *)iface;
HRESULT hr = S_OK;
static const DWORD dwNetConnectAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
static const DWORD dwNetConnectItemAttributes = SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
SFGAO_FILESYSANCESTOR | SFGAO_CANRENAME;
if (!rgfInOut)
return E_INVALIDARG;
if (cidl && !apidl)
return E_INVALIDARG;
if (*rgfInOut == 0)
*rgfInOut = ~0;
if (cidl == 0)
*rgfInOut = dwNetConnectAttributes;
else
*rgfInOut = dwNetConnectItemAttributes;
/* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
*rgfInOut &= ~SFGAO_VALIDATE;
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnGetUIObjectOf
*
* PARAMETERS
* hwndOwner [in] Parent window for any output
* cidl [in] array size
* apidl [in] simple pidl array
* riid [in] Requested Interface
* prgfInOut [ ] reserved
* ppvObject [out] Resulting Interface
*
*/
HRESULT IContextMenuImpl_Constructor(REFIID riid, PCUITEMID_CHILD pidl, LPVOID * ppvOut, IOleCommandTarget * lpOleCmd)
{
CNetConUiObject *pMenu = new CNetConUiObject(pidl, lpOleCmd);
if (!pMenu)
return E_OUTOFMEMORY;
pMenu->AddRef();
HRESULT hr = pMenu->QueryInterface(riid, ppvOut);
pMenu->Release();
return hr;
}
HRESULT WINAPI CNetworkConnections::GetUIObjectOf(
HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
UINT * prgfInOut, LPVOID * ppvOut)
{
IUnknown *pObj = NULL;
HRESULT hr = E_INVALIDARG;
if (!ppvOut)
return hr;
*ppvOut = NULL;
if ((IsEqualIID(riid, IID_IContextMenu) || IsEqualIID (riid, IID_IContextMenu2) || IsEqualIID(riid, IID_IContextMenu3) ||
IsEqualIID(riid, IID_IQueryInfo) || IsEqualIID(riid, IID_IExtractIconW)) && cidl >= 1)
{
return IContextMenuImpl_Constructor(riid, apidl[0], ppvOut, m_lpOleCmd);
}
else
hr = E_NOINTERFACE;
*ppvOut = pObj;
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnGetDisplayNameOf
*
*/
HRESULT WINAPI CNetworkConnections::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
LPWSTR pszName;
HRESULT hr = E_FAIL;
NETCON_PROPERTIES * pProperties;
const VALUEStruct * val;
if (!strRet)
return E_INVALIDARG;
pszName = static_cast<LPWSTR>(CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR)));
if (!pszName)
return E_OUTOFMEMORY;
if (_ILIsNetConnect(pidl))
{
if (LoadStringW(netshell_hInstance, IDS_NETWORKCONNECTION, pszName, MAX_PATH))
{
pszName[MAX_PATH-1] = L'\0';
hr = S_OK;
}
}
else
{
val = _ILGetValueStruct(pidl);
if (val)
{
if (val->pItem->GetProperties(&pProperties) == S_OK)
{
if (pProperties->pszwName)
{
wcscpy(pszName, pProperties->pszwName);
hr = S_OK;
}
NcFreeNetconProperties(pProperties);
}
}
}
if (SUCCEEDED(hr))
{
strRet->uType = STRRET_WSTR;
strRet->pOleStr = pszName;
}
else
{
CoTaskMemFree(pszName);
}
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnSetNameOf
* Changes the name of a file object or subfolder, possibly changing its item
* identifier in the process.
*
* PARAMETERS
* hwndOwner [in] Owner window for output
* pidl [in] simple pidl of item to change
* lpszName [in] the items new display name
* dwFlags [in] SHGNO formatting flags
* ppidlOut [out] simple pidl returned
*/
HRESULT WINAPI CNetworkConnections::SetNameOf (
HWND hwndOwner, PCUITEMID_CHILD pidl, /*simple pidl */
LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD * pPidlOut)
{
const VALUEStruct * val;
val = _ILGetValueStruct(pidl);
if (!val)
return E_FAIL;
if (!val->pItem)
return E_FAIL;
return val->pItem->Rename(lpName);
}
HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
{
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
{
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::GetDefaultColumn(DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
{
if (pSort)
*pSort = 0;
if (pDisplay)
*pDisplay = 0;
return S_OK;
}
HRESULT WINAPI CNetworkConnections::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
{
if (!pcsFlags || iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
return E_INVALIDARG;
*pcsFlags = NetConnectSFHeader[iColumn].pcsFlags;
return S_OK;
}
HRESULT WINAPI CNetworkConnections::GetDetailsEx(
PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
{
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::GetDetailsOf(
PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS * psd)
{
WCHAR buffer[MAX_PATH] = {0};
HRESULT hr = E_FAIL;
const VALUEStruct * val;
NETCON_PROPERTIES * pProperties;
if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
return E_FAIL;
psd->fmt = NetConnectSFHeader[iColumn].fmt;
psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
if (pidl == NULL)
{
psd->str.uType = STRRET_WSTR;
if (LoadStringW(netshell_hInstance, NetConnectSFHeader[iColumn].colnameid, buffer, MAX_PATH))
hr = SHStrDupW(buffer, &psd->str.pOleStr);
return hr;
}
if (iColumn == COLUMN_NAME)
{
psd->str.uType = STRRET_WSTR;
return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
}
val = _ILGetValueStruct(pidl);
if (!val)
return E_FAIL;
if (!val->pItem)
return E_FAIL;
if (val->pItem->GetProperties(&pProperties) != S_OK)
return E_FAIL;
switch (iColumn)
{
case COLUMN_TYPE:
if (pProperties->MediaType == NCM_LAN || pProperties->MediaType == NCM_SHAREDACCESSHOST_RAS)
{
if (LoadStringW(netshell_hInstance, IDS_TYPE_ETHERNET, buffer, MAX_PATH))
{
psd->str.uType = STRRET_WSTR;
hr = SHStrDupW(buffer, &psd->str.pOleStr);
}
}
break;
case COLUMN_STATUS:
buffer[0] = L'\0';
if (pProperties->Status == NCS_HARDWARE_DISABLED)
LoadStringW(netshell_hInstance, IDS_STATUS_NON_OPERATIONAL, buffer, MAX_PATH);
else if (pProperties->Status == NCS_DISCONNECTED)
LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, buffer, MAX_PATH);
else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, buffer, MAX_PATH);
else if (pProperties->Status == NCS_CONNECTING)
LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, buffer, MAX_PATH);
else if (pProperties->Status == NCS_CONNECTED)
LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, buffer, MAX_PATH);
if (buffer[0])
{
buffer[MAX_PATH-1] = L'\0';
psd->str.uType = STRRET_WSTR;
hr = SHStrDupW(buffer, &psd->str.pOleStr);
}
break;
case COLUMN_DEVNAME:
if (pProperties->pszwDeviceName)
{
wcscpy(buffer, pProperties->pszwDeviceName);
buffer[MAX_PATH-1] = L'\0';
psd->str.uType = STRRET_WSTR;
hr = SHStrDupW(buffer, &psd->str.pOleStr);
}
else
{
psd->str.cStr[0] = '\0';
psd->str.uType = STRRET_CSTR;
}
break;
case COLUMN_PHONE:
case COLUMN_OWNER:
psd->str.cStr[0] = '\0';
psd->str.uType = STRRET_CSTR;
break;
}
NcFreeNetconProperties(pProperties);
return hr;
}
HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
{
return E_NOTIMPL;
}
//IObjectWithSite
//IInternetSecurityManager
/**************************************************************************
* IContextMenu2 Implementation
*/
CNetConUiObject::CNetConUiObject(PCUITEMID_CHILD pidl, IOleCommandTarget *lpOleCmd)
: m_ref(0),
m_pidl(pidl),
m_pUnknown(NULL),
m_lpOleCmd(lpOleCmd)
{
if (m_lpOleCmd)
m_lpOleCmd->AddRef();
}
CNetConUiObject::~CNetConUiObject()
{
if (m_lpOleCmd)
m_lpOleCmd->Release();
}
/************************************************************************
* ISF_NetConnect_IContextMenu_QueryInterface
*/
HRESULT WINAPI CNetConUiObject::QueryInterface(REFIID iid, LPVOID *ppvObject)
{
*ppvObject = NULL;
if (IsEqualIID(iid, IID_IContextMenu) || IsEqualIID(iid, IID_IContextMenu2) || IsEqualIID(iid, IID_IContextMenu3))
*ppvObject = static_cast<IContextMenu3*>(this);
else if (IsEqualIID(iid, IID_IObjectWithSite))
*ppvObject = static_cast<IObjectWithSite*>(this);
else if (IsEqualIID(iid, IID_IQueryInfo))
*ppvObject = static_cast<IQueryInfo*>(this);
else if (IsEqualIID(iid, IID_IExtractIconW))
*ppvObject = static_cast<IExtractIconW*>(this);
if (*ppvObject)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/************************************************************************
* ISF_NetConnect_IContextMenu_AddRef
*/
ULONG WINAPI CNetConUiObject::AddRef()
{
ULONG refCount;
refCount = InterlockedIncrement(&m_ref);
return refCount;
}
/************************************************************************
* ISF_NetConnect_IContextMenu_Release
*/
ULONG WINAPI CNetConUiObject::Release()
{
ULONG refCount;
refCount = InterlockedDecrement(&m_ref);
if (!refCount)
delete this;
return refCount;
}
void WINAPI _InsertMenuItemW (
HMENU hmenu,
UINT indexMenu,
BOOL fByPosition,
UINT wID,
UINT fType,
LPCWSTR dwTypeData,
UINT fState)
{
MENUITEMINFOW mii;
WCHAR szText[100];
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
if (fType == MFT_SEPARATOR)
{
mii.fMask = MIIM_ID | MIIM_TYPE;
}
else if (fType == MFT_STRING)
{
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
{
if (LoadStringW(netshell_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR)))
{
szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
mii.dwTypeData = szText;
}
else
{
return;
}
}
else
{
mii.dwTypeData = (LPWSTR) dwTypeData;
}
mii.fState = fState;
}
mii.wID = wID;
mii.fType = fType;
InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
}
/**************************************************************************
* ISF_NetConnect_IContextMenu_QueryContextMenu()
*/
HRESULT WINAPI CNetConUiObject::QueryContextMenu(
HMENU hMenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
const VALUEStruct * val;
NETCON_PROPERTIES * pProperties;
val = _ILGetValueStruct(m_pidl);
if (!val)
return E_FAIL;
if (val->pItem->GetProperties(&pProperties) != S_OK)
return E_FAIL;
if (pProperties->Status == NCS_HARDWARE_DISABLED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_ACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DEACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
else if (pProperties->Status == NCS_CONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
if (pProperties->dwCharacter & NCCF_ALLOW_REMOVAL)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
if (pProperties->dwCharacter & NCCF_ALLOW_RENAME)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
NcFreeNetconProperties(pProperties);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 9);
}
BOOL
CALLBACK
PropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
{
PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam;
if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE)
{
pinfo->phpage[pinfo->nPages++] = hPage;
return TRUE;
}
return FALSE;
}
HRESULT
ShowNetConnectionStatus(
IOleCommandTarget *lpOleCmd,
INetConnection *pNetConnect,
HWND hwnd)
{
NETCON_PROPERTIES *pProperties;
HRESULT hr;
if (!lpOleCmd)
return E_FAIL;
if (pNetConnect->GetProperties(&pProperties) != S_OK)
return E_FAIL;
hr = lpOleCmd->Exec(&pProperties->guidId, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
NcFreeNetconProperties(pProperties);
return hr;
}
HRESULT
ShowNetConnectionProperties(
INetConnection *pNetConnect,
HWND hwnd)
{
HRESULT hr;
CLSID ClassID;
PROPSHEETHEADERW pinfo;
HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
INetConnectionPropertyUi * pNCP;
NETCON_PROPERTIES * pProperties;
if (pNetConnect->GetProperties(&pProperties) != S_OK)
return E_FAIL;
hr = pNetConnect->GetUiObjectClassId(&ClassID);
if (FAILED(hr))
{
NcFreeNetconProperties(pProperties);
return hr;
}
hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
if (FAILED(hr))
{
NcFreeNetconProperties(pProperties);
return hr;
}
hr = pNCP->SetConnection(pNetConnect);
if (SUCCEEDED(hr))
{
ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
ZeroMemory(hppages, sizeof(hppages));
pinfo.dwSize = sizeof(PROPSHEETHEADERW);
pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
pinfo.phpage = hppages;
pinfo.hwndParent = hwnd;
pinfo.pszCaption = pProperties->pszwName;
hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
if (SUCCEEDED(hr))
{
if (PropertySheetW(&pinfo) < 0)
hr = E_FAIL;
}
}
pNCP->Release();
NcFreeNetconProperties(pProperties);
return hr;
}
/**************************************************************************
* ISF_NetConnect_IContextMenu_InvokeCommand()
*/
HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
const VALUEStruct * val;
val = _ILGetValueStruct(m_pidl);
if (!val)
return E_FAIL;
if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS) ||
lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS-1)) //HACK for Windows XP
{
return ShowNetConnectionStatus(m_lpOleCmd, val->pItem, lpcmi->hwnd);
}
else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_PROPERTIES) ||
lpcmi->lpVerb == MAKEINTRESOURCEA(10099)) //HACK for Windows XP
{
/* FIXME perform version checks */
return ShowNetConnectionProperties(val->pItem, lpcmi->hwnd);
}
return S_OK;
}
/**************************************************************************
* ISF_NetConnect_IContextMenu_GetCommandString()
*
*/
HRESULT WINAPI CNetConUiObject::GetCommandString(
UINT_PTR idCommand,
UINT uFlags,
UINT* lpReserved,
LPSTR lpszName,
UINT uMaxNameLen)
{
return E_FAIL;
}
/**************************************************************************
* ISF_NetConnect_IContextMenu_HandleMenuMsg()
*/
HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return E_NOTIMPL;
}
HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
LRESULT *plResult)
{
return E_NOTIMPL;
}
HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
{
HRESULT hr;
IUnknown *pUnknown;
if (!m_pUnknown)
{
*ppvSite = NULL;
return E_FAIL;
}
hr = m_pUnknown->QueryInterface(riid, reinterpret_cast<PVOID*>(&pUnknown));
if (SUCCEEDED(hr))
{
pUnknown->AddRef();
*ppvSite = pUnknown;
return S_OK;
}
*ppvSite = NULL;
return hr;
}
HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
{
if (!pUnkSite)
{
if (m_pUnknown)
{
m_pUnknown->Release();
m_pUnknown = NULL;
}
}
else
{
pUnkSite->AddRef();
if (m_pUnknown)
m_pUnknown->Release();
m_pUnknown = pUnkSite;
}
return S_OK;
}
/************************************************************************
* ISF_NetConnect_IExtractIcon_GetIconLocation
*/
HRESULT WINAPI CNetConUiObject::GetIconLocation(
UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int *piIndex,
UINT *pwFlags)
{
const VALUEStruct *val;
NETCON_PROPERTIES *pProperties;
*pwFlags = 0;
if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
{
ERR("GetModuleFileNameW failed\n");
return E_FAIL;
}
val = _ILGetValueStruct(m_pidl);
if (!val)
{
ERR("_ILGetValueStruct failed\n");
return E_FAIL;
}
if (val->pItem->GetProperties(&pProperties) != NOERROR)
{
ERR("INetConnection_GetProperties failed\n");
return E_FAIL;
}
if (pProperties->Status == NCS_CONNECTED || pProperties->Status == NCS_CONNECTING)
*piIndex = -IDI_NET_IDLE;
else
*piIndex = -IDI_NET_OFF;
NcFreeNetconProperties(pProperties);
return NOERROR;
}
/************************************************************************
* ISF_NetConnect_IExtractIcon_Extract
*/
HRESULT WINAPI CNetConUiObject::Extract(
LPCWSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize)
{
//IContextMenuImpl * This = impl_from_IExtractIcon(iface);
if (nIconIndex == IDI_NET_IDLE)
{
*phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
*phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
return NOERROR;
}
else if (nIconIndex == IDI_NET_OFF)
{
*phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
*phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
return NOERROR;
}
return S_FALSE;
}
/************************************************************************
* ISF_NetConnect_PersistFolder2_GetClassID
*/
HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
{
if (!lpClassId)
return E_POINTER;
*lpClassId = CLSID_ConnectionFolder;
return S_OK;
}
/************************************************************************
* ISF_NetConnect_PersistFolder2_Initialize
*
* NOTES: it makes no sense to change the pidl
*/
HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidl)
{
SHFree(m_pidlRoot);
m_pidlRoot = ILClone(pidl);
return S_OK;
}
/**************************************************************************
* ISF_NetConnect_PersistFolder2_GetCurFolder
*/
HRESULT WINAPI CNetworkConnections::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
{
if (!pidl)
return E_POINTER;
*pidl = ILClone(m_pidlRoot);
return S_OK;
}
/************************************************************************
* ISF_NetConnect_ShellExecuteHookW_Execute
*/
HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
{
const VALUEStruct *val;
NETCON_PROPERTIES * pProperties;
val = _ILGetValueStruct(ILFindLastID((ITEMIDLIST*)pei->lpIDList));
if (!val)
return E_FAIL;
if (val->pItem->GetProperties(&pProperties) != NOERROR)
return E_FAIL;
if (pProperties->Status == NCS_CONNECTED)
{
NcFreeNetconProperties(pProperties);
return ShowNetConnectionStatus(m_lpOleCmd, val->pItem, pei->hwnd);
}
NcFreeNetconProperties(pProperties);
return S_OK;
}
HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
{
*pdwFlags = 0;
return S_OK;
}
/************************************************************************
* ISF_NetConnect_PersistFolder2_Initialize
*
* NOTES: it makes no sense to change the pidl
*/
HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
{
*ppwszTip = NULL;
return S_OK;
}
/**************************************************************************
* ISF_NetConnect_Constructor
*/
HRESULT WINAPI ISF_NetConnect_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
{
TRACE("ISF_NetConnect_Constructor\n");
if (!ppv)
return E_POINTER;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
CNetworkConnections *pnc = new CNetworkConnections;
if (!pnc)
return E_OUTOFMEMORY;
pnc->AddRef();
HRESULT hr = pnc->QueryInterface(riid, ppv);
pnc->Release();
return hr;
}