reactos/dll/shellext/netshell/shfldr_netconnect.cpp
Whindmar Saksit ea60890961
[NETSHELL][SHELL32] Make NetShell PIDL format more Windows compatible (#7183)
- The PIDL format needs to be Windows compatible so that wlanwiz can get the connection GUID.
- SHELL32::ILIsEqual cannot deem PIDL formats it does not understand as invalid.
- DefView must ask the folder when comparing PIDLs.
2024-08-08 22:00:03 +02:00

893 lines
25 KiB
C++

/*
* PROJECT: ReactOS Shell
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: CNetworkConnections Shell Folder
* COPYRIGHT: Copyright 2008 Johannes Anderwald <johannes.anderwald@reactos.org>
*/
#include "precomp.h"
#include <shellfolderutils.h>
#define MAX_PROPERTY_SHEET_PAGE (10)
/***********************************************************************
* IShellFolder implementation
*/
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,
PCUITEMID_CHILD pidl,
HWND hwnd);
CNetworkConnections::CNetworkConnections() :
m_pidlRoot(NULL)
{
HRESULT hr;
hr = CoCreateInstance(CLSID_ConnectionTray, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IOleCommandTarget, &m_lpOleCmd));
if (FAILED_UNEXPECTEDLY(hr))
m_lpOleCmd = NULL;
}
CNetworkConnections::~CNetworkConnections()
{
if (m_pidlRoot)
SHFree(m_pidlRoot);
}
/**************************************************************************
* 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;
}
/**************************************************************************
* ISF_NetConnect_fnEnumObjects
*/
HRESULT WINAPI CNetworkConnections::EnumObjects(
HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
{
return CEnumIDList_CreateInstance(hwndOwner, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
}
/**************************************************************************
* 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)
{
const UINT colcount = NETCONNECTSHELLVIEWCOLUMNS;
if (ILGetNext(pidl1) || ILGetNext(pidl2))
return E_NOTIMPL; // FIXME: Can the connection folder have subfolders?
if (lParam & SHCIDS_CANONICALONLY)
{
PNETCONIDSTRUCT p1 = ILGetConnData(pidl1);
PNETCONIDSTRUCT p2 = ILGetConnData(pidl2);
if (p1 && p2)
{
int res = memcmp(&p1->guidId, &p2->guidId, sizeof(GUID));
return MAKE_COMPARE_HRESULT(res);
}
}
IShellFolder2 *psf = static_cast<IShellFolder2*>(this);
return ShellFolderImpl_CompareItemIDs<colcount, -1>(psf, lParam, (PCUITEMID_CHILD)pidl1, (PCUITEMID_CHILD)pidl2);
}
/**************************************************************************
* ISF_NetConnect_fnCreateViewObject
*/
HRESULT WINAPI CNetworkConnections::CreateViewObject(
HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
{
HRESULT hr = E_NOINTERFACE;
if (!ppvOut)
return hr;
*ppvOut = NULL;
if (IsEqualIID(riid, IID_IShellView))
{
CSFV cvf = {sizeof(cvf), this};
CComPtr<IShellView> pShellView;
hr = SHCreateShellFolderViewEx(&cvf, &pShellView);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return pShellView->QueryInterface(riid, ppvOut);
}
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnGetAttributesOf
*/
HRESULT WINAPI CNetworkConnections::GetAttributesOf(
UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
{
//IGenericSFImpl *This = (IGenericSFImpl *)iface;
// FIXME: Why are these reporting SFGAO_FILESYSTEM and SFGAO_FILESYSANCESTOR?
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 > 1)
*rgfInOut &= ~SFGAO_HASPROPSHEET;
if (cidl == 0)
{
*rgfInOut = dwNetConnectAttributes;
}
else
{
*rgfInOut = dwNetConnectItemAttributes;
while (cidl > 0 && *apidl)
{
PNETCONIDSTRUCT pdata = ILGetConnData(*apidl);
if (!pdata)
continue;
if (!(pdata->dwCharacter & NCCF_ALLOW_RENAME))
*rgfInOut &= ~SFGAO_CANRENAME;
apidl++;
cidl--;
}
}
/* 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 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 ShellObjectCreatorInit<CNetConUiObject>(apidl[0], m_lpOleCmd, riid, ppvOut);
}
else
hr = E_NOINTERFACE;
*ppvOut = pObj;
return hr;
}
/**************************************************************************
* ISF_NetConnect_fnGetDisplayNameOf
*
*/
HRESULT WINAPI CNetworkConnections::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
if (!strRet)
return E_INVALIDARG;
if (!pidl)
return SHSetStrRet(strRet, netshell_hInstance, IDS_NETWORKCONNECTION);
PWCHAR pwchName = ILGetConnName(pidl);
if (!pwchName)
{
ERR("Got invalid pidl\n");
return E_INVALIDARG;
}
return SHSetStrRet(strRet, pwchName);
}
/**************************************************************************
* 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)
{
HRESULT hr;
CComPtr<INetConnection> pCon;
hr = ILGetConnection(pidl, &pCon);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pCon->Rename(lpName);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (pPidlOut)
{
*pPidlOut = ILCreateNetConnectItem(pCon);
if (*pPidlOut == NULL)
return E_FAIL;
}
return S_OK;
}
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)
{
if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
return E_FAIL;
psd->fmt = NetConnectSFHeader[iColumn].fmt;
psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
if (pidl == NULL)
return SHSetStrRet(&psd->str, netshell_hInstance, NetConnectSFHeader[iColumn].colnameid);
PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
if (!pdata)
return E_FAIL;
switch (iColumn)
{
case COLUMN_NAME:
return SHSetStrRet(&psd->str, ILGetConnName(pidl));
case COLUMN_TYPE:
if (pdata->MediaType == NCM_LAN || pdata->MediaType == NCM_SHAREDACCESSHOST_RAS)
{
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_TYPE_ETHERNET);
}
else
{
return SHSetStrRet(&psd->str, "");
}
break;
case COLUMN_STATUS:
switch(pdata->Status)
{
case NCS_HARDWARE_DISABLED:
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_NON_OPERATIONAL);
case NCS_DISCONNECTED:
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_UNREACHABLE);
case NCS_MEDIA_DISCONNECTED:
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_DISCONNECTED);
case NCS_CONNECTING:
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTING);
case NCS_CONNECTED:
return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTED);
default:
return SHSetStrRet(&psd->str, "");
}
break;
case COLUMN_DEVNAME:
return SHSetStrRet(&psd->str, ILGetDeviceName(pidl));
case COLUMN_PHONE:
case COLUMN_OWNER:
return SHSetStrRet(&psd->str, "");
}
return E_FAIL;
}
HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
{
return E_NOTIMPL;
}
//IObjectWithSite
//IInternetSecurityManager
/**************************************************************************
* IContextMenu2 Implementation
*/
CNetConUiObject::CNetConUiObject()
: m_pidl(NULL)
{
}
CNetConUiObject::~CNetConUiObject()
{
}
HRESULT WINAPI CNetConUiObject::Initialize(PCUITEMID_CHILD pidl, IOleCommandTarget *lpOleCmd)
{
m_pidl = pidl;
m_lpOleCmd = lpOleCmd;
return S_OK;
}
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)
{
PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
if (!pdata)
{
ERR("Got invalid pidl\n");
return E_FAIL;
}
if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
else if (pdata->Status == NCS_CONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 4, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
if (pdata->dwCharacter & NCCF_ALLOW_REMOVAL)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
if (pdata->dwCharacter & NCCF_ALLOW_RENAME)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
_InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
if (pdata->Status == NCS_CONNECTED)
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
else
_InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_DEFAULT);
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,
PCUITEMID_CHILD pidl,
HWND hwnd)
{
if (!lpOleCmd)
return E_FAIL;
PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
if (!pdata)
{
ERR("Got invalid pidl\n");
return E_FAIL;
}
return lpOleCmd->Exec(&pdata->guidId, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
}
static int CALLBACK
PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
{
// NOTE: This callback is needed to set large icon correctly.
HICON hIcon;
switch (uMsg)
{
case PSCB_INITIALIZED:
{
hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER));
SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
break;
}
}
return 0;
}
HRESULT
ShowNetConnectionProperties(
INetConnection *pNetConnect,
HWND hwnd)
{
HRESULT hr;
CLSID ClassID;
PROPSHEETHEADERW pinfo;
HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
CComPtr<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 |
PSH_USEICONID | PSH_USECALLBACK;
pinfo.hInstance = netshell_hInstance;
pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER);
pinfo.phpage = hppages;
pinfo.hwndParent = hwnd;
pinfo.pfnCallback = PropSheetProc;
pinfo.pszCaption = pProperties->pszwName;
hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
if (SUCCEEDED(hr))
{
if (PropertySheetW(&pinfo) < 0)
hr = E_FAIL;
}
}
NcFreeNetconProperties(pProperties);
return hr;
}
/**************************************************************************
* ISF_NetConnect_IContextMenu_InvokeCommand()
*/
HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
UINT CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE;
/* We should get this when F2 is pressed in explorer */
if (!IS_INTRESOURCE(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
{
CmdId = IDS_NET_RENAME;
}
else if (!IS_INTRESOURCE(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "properties"))
{
CmdId = IDS_NET_PROPERTIES;
}
else if (!IS_INTRESOURCE(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7)
{
FIXME("Got invalid command\n");
return E_NOTIMPL;
}
switch(CmdId)
{
case IDS_NET_RENAME:
{
HRESULT hr;
CComPtr<IShellView> psv;
hr = IUnknown_QueryService(m_pUnknown, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
if (SUCCEEDED(hr))
{
SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
psv->SelectItem(m_pidl, selFlags);
}
return S_OK;
}
case IDS_NET_STATUS:
{
return ShowNetConnectionStatus(m_lpOleCmd, m_pidl, lpcmi->hwnd);
}
case IDS_NET_REPAIR:
case IDS_NET_CREATELINK:
case IDS_NET_DELETE:
FIXME("Command %u is not implemented\n", CmdId);
return E_NOTIMPL;
}
HRESULT hr;
CComPtr<INetConnection> pCon;
hr = ILGetConnection(m_pidl, &pCon);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
switch(CmdId)
{
case IDS_NET_ACTIVATE:
return pCon->Connect();
case IDS_NET_DEACTIVATE:
return pCon->Disconnect();
case IDS_NET_PROPERTIES:
return ShowNetConnectionProperties(pCon, lpcmi->hwnd);
}
return E_NOTIMPL;
}
/**************************************************************************
* 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)
{
if (!m_pUnknown)
{
*ppvSite = NULL;
return E_FAIL;
}
return m_pUnknown->QueryInterface(riid, ppvSite);
}
HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
{
m_pUnknown = pUnkSite;
return S_OK;
}
/************************************************************************
* ISF_NetConnect_IExtractIcon_GetIconLocation
*/
HRESULT WINAPI CNetConUiObject::GetIconLocation(
UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int *piIndex,
UINT *pwFlags)
{
*pwFlags = 0;
if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
{
ERR("GetModuleFileNameW failed\n");
return E_FAIL;
}
PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
if (!pdata)
{
ERR("Got invalid pidl\n");
return E_FAIL;
}
if (pdata->Status == NCS_CONNECTED || pdata->Status == NCS_CONNECTING)
*piIndex = -IDI_NET_IDLE;
else
*piIndex = -IDI_NET_OFF;
return S_OK;
}
/************************************************************************
* ISF_NetConnect_IExtractIcon_Extract
*/
HRESULT WINAPI CNetConUiObject::Extract(
LPCWSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize)
{
return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
}
/************************************************************************
* 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)
{
if (m_pidlRoot)
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)
{
PCUITEMID_CHILD pidl = ILFindLastID((ITEMIDLIST*)pei->lpIDList);
PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
if (!pdata)
{
ERR("Got invalid pidl\n");
return E_FAIL;
}
if (pdata->Status == NCS_CONNECTED)
{
return ShowNetConnectionStatus(m_lpOleCmd, pidl, pei->hwnd);
}
return S_OK;
}
HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
{
FIXME("CNetworkConnections::Initialize()\n");
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
FIXME("CNetworkConnections::Exec()\n");
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
{
FIXME("CNetworkConnections::QueryStatus()\n");
return E_NOTIMPL;
}
HRESULT WINAPI CNetworkConnections::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
FIXME("CNetworkConnections::MessageSFVCB()\n");
return E_NOTIMPL;
}
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;
}