mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:53:06 +00:00
[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.
This commit is contained in:
parent
5d96ba9217
commit
ea60890961
7 changed files with 144 additions and 26 deletions
|
@ -9,9 +9,13 @@
|
||||||
|
|
||||||
PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl)
|
PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl)
|
||||||
{
|
{
|
||||||
if (!pidl || !pidl->mkid.cb || pidl->mkid.abID[0] != 0x99)
|
if (pidl && pidl->mkid.cb >= 2 + sizeof(NETCONIDSTRUCT))
|
||||||
return NULL;
|
{
|
||||||
return (PNETCONIDSTRUCT)(&pidl->mkid.abID[0]);
|
PNETCONIDSTRUCT pData = (PNETCONIDSTRUCT)pidl->mkid.abID;
|
||||||
|
if (pData->Signature == NETCONIDSTRUCT_SIG)
|
||||||
|
return pData;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PWCHAR ILGetConnName(PCITEMID_CHILD pidl)
|
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 */
|
/* Allocate enough memory for the trailing id which will indicate that this is a simple id */
|
||||||
pidl = static_cast<LPITEMIDLIST>(SHAlloc(size + sizeof(SHITEMID)));
|
pidl = static_cast<LPITEMIDLIST>(SHAlloc(size + sizeof(SHITEMID)));
|
||||||
|
if (!pidl)
|
||||||
|
goto end;
|
||||||
pidl->mkid.cb = (WORD)size;
|
pidl->mkid.cb = (WORD)size;
|
||||||
pidl->mkid.abID[0] = 0x99;
|
((PNETCONIDSTRUCT)(pidl->mkid.abID))->Signature = NETCONIDSTRUCT_SIG;
|
||||||
|
|
||||||
/* Copy the connection properties */
|
/* Copy the connection properties */
|
||||||
pnetid = ILGetConnData(pidl);
|
pnetid = ILGetConnData(pidl);
|
||||||
|
memset(pnetid->Unknown, 0, sizeof(pnetid->Unknown));
|
||||||
|
pnetid->clsidThisObject = pProperties->clsidThisObject;
|
||||||
pnetid->guidId = pProperties->guidId;
|
pnetid->guidId = pProperties->guidId;
|
||||||
pnetid->Status = pProperties->Status;
|
pnetid->Status = pProperties->Status;
|
||||||
pnetid->MediaType = pProperties->MediaType;
|
pnetid->MediaType = pProperties->MediaType;
|
||||||
pnetid->dwCharacter = pProperties->dwCharacter;
|
pnetid->dwCharacter = pProperties->dwCharacter;
|
||||||
pnetid->uNameOffset = sizeof(NETCONIDSTRUCT);
|
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);
|
pwchName = ILGetConnName(pidl);
|
||||||
wcscpy(pwchName, pProperties->pszwName);
|
wcscpy(pwchName, pProperties->pszwName);
|
||||||
|
@ -68,7 +76,7 @@ PITEMID_CHILD ILCreateNetConnectItem(INetConnection * pItem)
|
||||||
|
|
||||||
/* Set the trailing id to null */
|
/* Set the trailing id to null */
|
||||||
memset((void*)((ULONG_PTR)pidl + size), 0, sizeof(SHITEMID));
|
memset((void*)((ULONG_PTR)pidl + size), 0, sizeof(SHITEMID));
|
||||||
|
end:
|
||||||
NcFreeNetconProperties(pProperties);
|
NcFreeNetconProperties(pProperties);
|
||||||
|
|
||||||
return pidl;
|
return pidl;
|
||||||
|
|
|
@ -55,16 +55,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
extern HINSTANCE netshell_hInstance;
|
extern HINSTANCE netshell_hInstance;
|
||||||
|
|
||||||
/* enumlist.c */
|
/* enumlist.c */
|
||||||
|
#include <pshpack1.h>
|
||||||
|
#define NETCONIDSTRUCT_SIG 0x4EFF
|
||||||
typedef struct tagNETCONIDSTRUCT
|
typedef struct tagNETCONIDSTRUCT
|
||||||
{
|
{
|
||||||
BYTE type;
|
WORD Signature;
|
||||||
|
BYTE Unknown[8];
|
||||||
|
CLSID clsidThisObject;
|
||||||
GUID guidId;
|
GUID guidId;
|
||||||
NETCON_STATUS Status;
|
|
||||||
NETCON_MEDIATYPE MediaType;
|
|
||||||
DWORD dwCharacter;
|
DWORD dwCharacter;
|
||||||
ULONG_PTR uNameOffset;
|
NETCON_MEDIATYPE MediaType;
|
||||||
ULONG_PTR uDeviceNameOffset;
|
NETCON_STATUS Status;
|
||||||
|
ULONG uNameOffset;
|
||||||
|
ULONG uDeviceNameOffset;
|
||||||
} NETCONIDSTRUCT, *PNETCONIDSTRUCT;
|
} 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);
|
PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl);
|
||||||
PWCHAR ILGetConnName(PCITEMID_CHILD pidl);
|
PWCHAR ILGetConnName(PCITEMID_CHILD pidl);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
#include <shellfolderutils.h>
|
||||||
|
|
||||||
#define MAX_PROPERTY_SHEET_PAGE (10)
|
#define MAX_PROPERTY_SHEET_PAGE (10)
|
||||||
|
|
||||||
|
@ -99,11 +100,26 @@ HRESULT WINAPI CNetworkConnections::BindToStorage(
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* ISF_NetConnect_fnCompareIDs
|
* ISF_NetConnect_fnCompareIDs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HRESULT WINAPI CNetworkConnections::CompareIDs(
|
HRESULT WINAPI CNetworkConnections::CompareIDs(
|
||||||
LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
|
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)
|
UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
|
||||||
{
|
{
|
||||||
//IGenericSFImpl *This = (IGenericSFImpl *)iface;
|
//IGenericSFImpl *This = (IGenericSFImpl *)iface;
|
||||||
|
// FIXME: Why are these reporting SFGAO_FILESYSTEM and SFGAO_FILESYSANCESTOR?
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
static const DWORD dwNetConnectAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
|
static const DWORD dwNetConnectAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
|
||||||
SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
|
SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
|
||||||
|
@ -156,6 +173,9 @@ HRESULT WINAPI CNetworkConnections::GetAttributesOf(
|
||||||
if (*rgfInOut == 0)
|
if (*rgfInOut == 0)
|
||||||
*rgfInOut = ~0;
|
*rgfInOut = ~0;
|
||||||
|
|
||||||
|
if (cidl > 1)
|
||||||
|
*rgfInOut &= ~SFGAO_HASPROPSHEET;
|
||||||
|
|
||||||
if (cidl == 0)
|
if (cidl == 0)
|
||||||
{
|
{
|
||||||
*rgfInOut = dwNetConnectAttributes;
|
*rgfInOut = dwNetConnectAttributes;
|
||||||
|
@ -610,20 +630,23 @@ ShowNetConnectionProperties(
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
|
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 */
|
/* We should get this when F2 is pressed in explorer */
|
||||||
if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
|
if (!IS_INTRESOURCE(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
|
||||||
lpcmi->lpVerb = MAKEINTRESOURCEA(IDS_NET_RENAME);
|
{
|
||||||
|
CmdId = IDS_NET_RENAME;
|
||||||
if (HIWORD(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7)
|
}
|
||||||
|
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");
|
FIXME("Got invalid command\n");
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE;
|
|
||||||
|
|
||||||
switch(CmdId)
|
switch(CmdId)
|
||||||
{
|
{
|
||||||
case IDS_NET_RENAME:
|
case IDS_NET_RENAME:
|
||||||
|
|
|
@ -1290,15 +1290,29 @@ PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem)
|
||||||
|
|
||||||
int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
|
int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
|
||||||
{
|
{
|
||||||
ASSERT(m_ListView);
|
ASSERT(m_ListView && m_pSFParent);
|
||||||
|
|
||||||
int cItems = m_ListView.GetItemCount();
|
int cItems = m_ListView.GetItemCount();
|
||||||
|
LPARAM lParam = m_pSF2Parent ? SHCIDS_CANONICALONLY : 0;
|
||||||
for (int i = 0; i<cItems; i++)
|
for (int i = 0; i < cItems; i++)
|
||||||
{
|
{
|
||||||
PCUITEMID_CHILD currentpidl = _PidlByItem(i);
|
PCUITEMID_CHILD currentpidl = _PidlByItem(i);
|
||||||
if (ILIsEqual(pidl, currentpidl))
|
HRESULT hr = m_pSFParent->CompareIDs(lParam, pidl, currentpidl);
|
||||||
return i;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,7 +379,6 @@ BOOL pcheck( LPCITEMIDLIST pidl )
|
||||||
case PT_YAGUID:
|
case PT_YAGUID:
|
||||||
case PT_IESPECIAL2:
|
case PT_IESPECIAL2:
|
||||||
case PT_SHARE:
|
case PT_SHARE:
|
||||||
case 0x99: /* Network Connection pidl type */
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("unknown IDLIST %p [%p] size=%u type=%x\n",
|
ERR("unknown IDLIST %p [%p] size=%u type=%x\n",
|
||||||
|
|
|
@ -557,7 +557,13 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||||||
* so we can only check here
|
* so we can only check here
|
||||||
*/
|
*/
|
||||||
if (!pcheck(pidl1) || !pcheck (pidl2))
|
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;
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
pdump (pidl1);
|
pdump (pidl1);
|
||||||
pdump (pidl2);
|
pdump (pidl2);
|
||||||
|
|
58
sdk/include/reactos/shellfolderutils.h
Normal file
58
sdk/include/reactos/shellfolderutils.h
Normal file
|
@ -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@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
|
Loading…
Add table
Add a link
Reference in a new issue