https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ea60890961dcdda7356a3…
commit ea60890961dcdda7356a3c6cfed919fd20905f88
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Thu Aug 8 22:00:03 2024 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Aug 8 22:00:03 2024 +0200
[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.
---
dll/shellext/netshell/enumlist.cpp | 20 +++++++---
dll/shellext/netshell/precomp.h | 20 +++++++---
dll/shellext/netshell/shfldr_netconnect.cpp | 41 +++++++++++++++-----
dll/win32/shell32/CDefView.cpp | 24 +++++++++---
dll/win32/shell32/debughlp.cpp | 1 -
dll/win32/shell32/wine/pidl.c | 6 +++
sdk/include/reactos/shellfolderutils.h | 58 +++++++++++++++++++++++++++++
7 files changed, 144 insertions(+), 26 deletions(-)
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<LPITEMIDLIST>(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 <pshpack1.h>
+#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 <poppack.h>
+
+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 <shellfolderutils.h>
#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<IShellFolder2*>(this);
+ return ShellFolderImpl_CompareItemIDs<colcount, -1>(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; i<cItems; i++)
+ LPARAM lParam = m_pSF2Parent ? SHCIDS_CANONICALONLY : 0;
+ for (int i = 0; i < cItems; i++)
{
PCUITEMID_CHILD currentpidl = _PidlByItem(i);
- if (ILIsEqual(pidl, currentpidl))
- return i;
+ HRESULT hr = m_pSFParent->CompareIDs(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 <whindsaks(a)proton.me>
+ */
+
+#pragma once
+
+#include "shellutils.h"
+
+#ifdef __cplusplus
+
+template <BOOL LOGICALCMP = TRUE>
+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 <UINT COLCOUNT, int CANONICAL, BOOL LOGICALCMP = TRUE>
+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<LOGICALCMP>(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<LOGICALCMP>(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<LOGICALCMP>(psf, column, pidl1,
pidl2);
+}
+
+#endif // __cplusplus