diff --git a/dll/shellext/netshell/enumlist.cpp b/dll/shellext/netshell/enumlist.cpp index 5f4b0fbef11..1cc62e79044 100644 --- a/dll/shellext/netshell/enumlist.cpp +++ b/dll/shellext/netshell/enumlist.cpp @@ -9,9 +9,13 @@ PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl) { - if (!pidl || !pidl->mkid.cb || pidl->mkid.abID[0] != 0x99) - return NULL; - return (PNETCONIDSTRUCT)(&pidl->mkid.abID[0]); + if (pidl && pidl->mkid.cb >= 2 + sizeof(NETCONIDSTRUCT)) + { + PNETCONIDSTRUCT pData = (PNETCONIDSTRUCT)pidl->mkid.abID; + if (pData->Signature == NETCONIDSTRUCT_SIG) + return pData; + } + return NULL; } PWCHAR ILGetConnName(PCITEMID_CHILD pidl) @@ -48,17 +52,21 @@ PITEMID_CHILD ILCreateNetConnectItem(INetConnection * pItem) /* Allocate enough memory for the trailing id which will indicate that this is a simple id */ pidl = static_cast(SHAlloc(size + sizeof(SHITEMID))); + if (!pidl) + goto end; pidl->mkid.cb = (WORD)size; - pidl->mkid.abID[0] = 0x99; + ((PNETCONIDSTRUCT)(pidl->mkid.abID))->Signature = NETCONIDSTRUCT_SIG; /* Copy the connection properties */ pnetid = ILGetConnData(pidl); + memset(pnetid->Unknown, 0, sizeof(pnetid->Unknown)); + pnetid->clsidThisObject = pProperties->clsidThisObject; pnetid->guidId = pProperties->guidId; pnetid->Status = pProperties->Status; pnetid->MediaType = pProperties->MediaType; pnetid->dwCharacter = pProperties->dwCharacter; pnetid->uNameOffset = sizeof(NETCONIDSTRUCT); - pnetid->uDeviceNameOffset = pnetid->uNameOffset + (wcslen(pProperties->pszwName) + 1) * sizeof(WCHAR); + pnetid->uDeviceNameOffset = ULONG(pnetid->uNameOffset + (wcslen(pProperties->pszwName) + 1) * sizeof(WCHAR)); pwchName = ILGetConnName(pidl); wcscpy(pwchName, pProperties->pszwName); @@ -68,7 +76,7 @@ PITEMID_CHILD ILCreateNetConnectItem(INetConnection * pItem) /* Set the trailing id to null */ memset((void*)((ULONG_PTR)pidl + size), 0, sizeof(SHITEMID)); - +end: NcFreeNetconProperties(pProperties); return pidl; diff --git a/dll/shellext/netshell/precomp.h b/dll/shellext/netshell/precomp.h index 7dc020ca442..1f6497c3862 100644 --- a/dll/shellext/netshell/precomp.h +++ b/dll/shellext/netshell/precomp.h @@ -55,16 +55,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); extern HINSTANCE netshell_hInstance; /* enumlist.c */ +#include +#define NETCONIDSTRUCT_SIG 0x4EFF typedef struct tagNETCONIDSTRUCT { - BYTE type; + WORD Signature; + BYTE Unknown[8]; + CLSID clsidThisObject; GUID guidId; - NETCON_STATUS Status; - NETCON_MEDIATYPE MediaType; DWORD dwCharacter; - ULONG_PTR uNameOffset; - ULONG_PTR uDeviceNameOffset; + NETCON_MEDIATYPE MediaType; + NETCON_STATUS Status; + ULONG uNameOffset; + ULONG uDeviceNameOffset; } NETCONIDSTRUCT, *PNETCONIDSTRUCT; +#include + +C_ASSERT(2 + FIELD_OFFSET(NETCONIDSTRUCT, clsidThisObject) == 2 + (2 + 8)); +C_ASSERT(2 + FIELD_OFFSET(NETCONIDSTRUCT, guidId) == 2 + (2 + 8 + 16)); +C_ASSERT(2 + FIELD_OFFSET(NETCONIDSTRUCT, dwCharacter) == 2 + (2 + 8 + 32)); +C_ASSERT(2 + FIELD_OFFSET(NETCONIDSTRUCT, MediaType) == 2 + (2 + 8 + 36)); PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl); PWCHAR ILGetConnName(PCITEMID_CHILD pidl); diff --git a/dll/shellext/netshell/shfldr_netconnect.cpp b/dll/shellext/netshell/shfldr_netconnect.cpp index 588f2c063e8..dca42527e7a 100644 --- a/dll/shellext/netshell/shfldr_netconnect.cpp +++ b/dll/shellext/netshell/shfldr_netconnect.cpp @@ -6,6 +6,7 @@ */ #include "precomp.h" +#include #define MAX_PROPERTY_SHEET_PAGE (10) @@ -99,11 +100,26 @@ HRESULT WINAPI CNetworkConnections::BindToStorage( /************************************************************************** * ISF_NetConnect_fnCompareIDs */ - HRESULT WINAPI CNetworkConnections::CompareIDs( LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) { - return E_NOTIMPL; + 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(this); + return ShellFolderImpl_CompareItemIDs(psf, lParam, (PCUITEMID_CHILD)pidl1, (PCUITEMID_CHILD)pidl2); } /************************************************************************** @@ -140,6 +156,7 @@ 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; @@ -156,6 +173,9 @@ HRESULT WINAPI CNetworkConnections::GetAttributesOf( if (*rgfInOut == 0) *rgfInOut = ~0; + if (cidl > 1) + *rgfInOut &= ~SFGAO_HASPROPSHEET; + if (cidl == 0) { *rgfInOut = dwNetConnectAttributes; @@ -610,20 +630,23 @@ ShowNetConnectionProperties( */ HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) { - UINT CmdId; + UINT CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE; /* We should get this when F2 is pressed in explorer */ - if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename")) - lpcmi->lpVerb = MAKEINTRESOURCEA(IDS_NET_RENAME); - - if (HIWORD(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7) + 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; } - CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE; - switch(CmdId) { case IDS_NET_RENAME: diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index eb4a85de725..ad9317d0a39 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -1290,15 +1290,29 @@ PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem) int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl) { - ASSERT(m_ListView); + ASSERT(m_ListView && m_pSFParent); int cItems = m_ListView.GetItemCount(); - - for (int i = 0; iCompareIDs(lParam, pidl, currentpidl); + if (SUCCEEDED(hr)) + { + if (hr == S_EQUAL) + return i; + } + else + { + for (i = 0; i < cItems; i++) + { + currentpidl = _PidlByItem(i); + if (ILIsEqual(pidl, currentpidl)) + return i; + } + break; + } } return -1; } diff --git a/dll/win32/shell32/debughlp.cpp b/dll/win32/shell32/debughlp.cpp index 388349c70a6..6778418c7a8 100644 --- a/dll/win32/shell32/debughlp.cpp +++ b/dll/win32/shell32/debughlp.cpp @@ -379,7 +379,6 @@ BOOL pcheck( LPCITEMIDLIST pidl ) case PT_YAGUID: case PT_IESPECIAL2: case PT_SHARE: - case 0x99: /* Network Connection pidl type */ break; default: ERR("unknown IDLIST %p [%p] size=%u type=%x\n", diff --git a/dll/win32/shell32/wine/pidl.c b/dll/win32/shell32/wine/pidl.c index e749d05125c..09b09112adb 100644 --- a/dll/win32/shell32/wine/pidl.c +++ b/dll/win32/shell32/wine/pidl.c @@ -557,7 +557,13 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) * so we can only check here */ if (!pcheck(pidl1) || !pcheck (pidl2)) +#ifdef __REACTOS__ + { + /* We don't understand the PIDL content but that does not mean it's invalid */ + } +#else return FALSE; +#endif pdump (pidl1); pdump (pidl2); diff --git a/sdk/include/reactos/shellfolderutils.h b/sdk/include/reactos/shellfolderutils.h new file mode 100644 index 00000000000..b3baa88f1f3 --- /dev/null +++ b/sdk/include/reactos/shellfolderutils.h @@ -0,0 +1,58 @@ +/* + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: Utility functions for IShellFolder implementations + * COPYRIGHT: Copyright 2024 Whindmar Saksit + */ + +#pragma once + +#include "shellutils.h" + +#ifdef __cplusplus + +template +static HRESULT ShellFolderImpl_CompareItemColumn(IShellFolder2 *psf, UINT column, PCUITEMID_CHILD pidl1, PCUITEMID_CHILD pidl2) +{ + SHELLDETAILS details1, details2; + LPWSTR str1, str2; + HRESULT hr; + if (SUCCEEDED(hr = psf->GetDetailsOf(pidl1, column, &details1)) && + SUCCEEDED(hr = StrRetToStrW(&details1.str, pidl1, &str1))) + { + if (SUCCEEDED(hr = psf->GetDetailsOf(pidl2, column, &details2)) && + SUCCEEDED(hr = StrRetToStrW(&details2.str, pidl2, &str2))) + { + int res = LOGICALCMP ? StrCmpLogicalW(str1, str2) : lstrcmpiW(str1, str2); + hr = MAKE_COMPARE_HRESULT(res); + SHFree(str2); + } + SHFree(str1); + } + return hr; +} + +template +static HRESULT ShellFolderImpl_CompareItemIDs(IShellFolder2 *psf, LPARAM lParam, PCUITEMID_CHILD pidl1, PCUITEMID_CHILD pidl2) +{ + HRESULT hr; + if (CANONICAL >= 0 && (lParam & SHCIDS_CANONICALONLY)) + { + hr = ShellFolderImpl_CompareItemColumn(psf, CANONICAL, pidl1, pidl2); + if (hr == S_EQUAL || !(lParam & SHCIDS_ALLFIELDS) || FAILED(hr)) + return hr; + } + if (lParam & SHCIDS_ALLFIELDS) + { + for (UINT i = 0; i < COLCOUNT; ++i) + { + hr = ShellFolderImpl_CompareItemColumn(psf, i, pidl1, pidl2); + if (hr && SUCCEEDED(hr)) // Only stop if we successfully found a difference + break; + } + return hr; + } + const UINT column = (UINT)(lParam & SHCIDS_COLUMNMASK); + return ShellFolderImpl_CompareItemColumn(psf, column, pidl1, pidl2); +} + +#endif // __cplusplus