[PATCH 2/2] shell32: Add security property tab.

Zebediah Figura z.figura12 at gmail.com
Wed Feb 17 23:32:17 CST 2021


From: Michael Müller <michael at fds-team.de>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/shell32/Makefile.in     |   2 +-
 dlls/shell32/shell32.rc      |  20 +++
 dlls/shell32/shlview_cmenu.c | 302 +++++++++++++++++++++++++++++++++++
 dlls/shell32/shresdef.h      |  20 +++
 4 files changed, 343 insertions(+), 1 deletion(-)

diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in
index fe49bf09f98..f6fcf2e18eb 100644
--- a/dlls/shell32/Makefile.in
+++ b/dlls/shell32/Makefile.in
@@ -1,7 +1,7 @@
 EXTRADEFS = -D_SHELL32_
 MODULE    = shell32.dll
 IMPORTLIB = shell32
-IMPORTS   = uuid shlwapi user32 gdi32 advapi32
+IMPORTS   = uuid shlwapi user32 gdi32 advapi32 aclui
 DELAYIMPORTS = ole32 oleaut32 shdocvw version comctl32 gdiplus
 # AUTHORS file is in the top-level directory
 EXTRAINCL = -I$(top_srcdir)
diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc
index f19b09f8c21..ce5daea1e8b 100644
--- a/dlls/shell32/shell32.rc
+++ b/dlls/shell32/shell32.rc
@@ -197,6 +197,26 @@ the folder?"
         IDS_RUNDLG_BROWSE_FILTER_EXE "Executable files (*.exe)"
         IDS_RUNDLG_BROWSE_FILTER_ALL "All files (*.*)"
 
+        IDS_SECURITY_ADD_FILE           "Add File"
+        IDS_SECURITY_ADD_SUBDIRECTORY   "Add Subdirectory"
+        IDS_SECURITY_ALL_ACCESS         "All Access"
+        IDS_SECURITY_APPEND_DATA        "Append Data"
+        IDS_SECURITY_DELETE             "Delete"
+        IDS_SECURITY_DELETE_CHILD       "Delete Child"
+        IDS_SECURITY_EXECUTE            "Execute"
+        IDS_SECURITY_LIST_DIRECTORY     "List Directory Contents"
+        IDS_SECURITY_READ_ATTRIBUTES    "Read Attributes"
+        IDS_SECURITY_READ_CONTROL       "Read Security Descriptor"
+        IDS_SECURITY_READ_DATA          "Read Data"
+        IDS_SECURITY_READ_EA            "Read Extended Attributes"
+        IDS_SECURITY_SYNCHRONIZE        "Synchronize"
+        IDS_SECURITY_TRAVERSE           "Traverse"
+        IDS_SECURITY_WRITE_ATTRIBUTES   "Write Attributes"
+        IDS_SECURITY_WRITE_DAC          "Write DACL"
+        IDS_SECURITY_WRITE_DATA         "Write Data"
+        IDS_SECURITY_WRITE_EA           "Write Extended Attributes"
+        IDS_SECURITY_WRITE_OWNER        "Write Owner"
+
         /* shell folder path default values */
 	/* FIXME: Some will be unused until desktop.ini support is implemented */
 	IDS_PROGRAMS                "Programs"
diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c
index 04ac0b6fd3c..86b84a3ca67 100644
--- a/dlls/shell32/shlview_cmenu.c
+++ b/dlls/shell32/shlview_cmenu.c
@@ -39,12 +39,68 @@
 
 #include "shresdef.h"
 #include "shlwapi.h"
+#include "initguid.h"
+#include "aclui.h"
+#include "aclapi.h"
 
 #include "wine/heap.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
+#define X(a, b) {&GUID_NULL, a, MAKEINTRESOURCEW(b), SI_ACCESS_GENERAL},
+
+static const SI_ACCESS access_rights_file[] =
+{
+    X(FILE_ALL_ACCESS,          IDS_SECURITY_ALL_ACCESS)
+    X(FILE_READ_DATA,           IDS_SECURITY_READ_DATA)
+    X(FILE_WRITE_DATA,          IDS_SECURITY_WRITE_DATA)
+    X(FILE_APPEND_DATA,         IDS_SECURITY_APPEND_DATA)
+    X(FILE_READ_EA,             IDS_SECURITY_READ_EA)
+    X(FILE_WRITE_EA,            IDS_SECURITY_WRITE_EA)
+    X(FILE_EXECUTE,             IDS_SECURITY_EXECUTE)
+    X(FILE_READ_ATTRIBUTES,     IDS_SECURITY_READ_ATTRIBUTES)
+    X(FILE_WRITE_ATTRIBUTES,    IDS_SECURITY_WRITE_ATTRIBUTES)
+    X(DELETE,                   IDS_SECURITY_DELETE)
+    X(READ_CONTROL,             IDS_SECURITY_READ_CONTROL)
+    X(WRITE_DAC,                IDS_SECURITY_WRITE_DAC)
+    X(WRITE_OWNER,              IDS_SECURITY_WRITE_OWNER)
+    X(SYNCHRONIZE,              IDS_SECURITY_SYNCHRONIZE)
+};
+
+static const SI_ACCESS access_rights_directory[] =
+{
+    X(FILE_ALL_ACCESS,          IDS_SECURITY_ALL_ACCESS)
+    X(FILE_LIST_DIRECTORY,      IDS_SECURITY_LIST_DIRECTORY)
+    X(FILE_ADD_FILE,            IDS_SECURITY_ADD_FILE)
+    X(FILE_ADD_SUBDIRECTORY,    IDS_SECURITY_ADD_SUBDIRECTORY)
+    X(FILE_READ_EA,             IDS_SECURITY_READ_EA)
+    X(FILE_WRITE_EA,            IDS_SECURITY_WRITE_EA)
+    X(FILE_TRAVERSE,            IDS_SECURITY_TRAVERSE)
+    X(FILE_DELETE_CHILD,        IDS_SECURITY_DELETE_CHILD)
+    X(FILE_READ_ATTRIBUTES,     IDS_SECURITY_READ_ATTRIBUTES)
+    X(FILE_WRITE_ATTRIBUTES,    IDS_SECURITY_WRITE_ATTRIBUTES)
+    X(DELETE,                   IDS_SECURITY_DELETE)
+    X(READ_CONTROL,             IDS_SECURITY_READ_CONTROL)
+    X(WRITE_DAC,                IDS_SECURITY_WRITE_DAC)
+    X(WRITE_OWNER,              IDS_SECURITY_WRITE_OWNER)
+    X(SYNCHRONIZE,              IDS_SECURITY_SYNCHRONIZE)
+};
+#undef X
+
+struct security_info
+{
+    ISecurityInformation ISecurityInformation_iface;
+    LONG refcount;
+    WCHAR *path;
+    BOOL directory;
+};
+
+static inline struct security_info *impl_from_ISecurityInformation(ISecurityInformation *iface)
+{
+    return CONTAINING_RECORD(iface, struct security_info, ISecurityInformation_iface);
+}
+
 typedef struct
 {
     IContextMenu3 IContextMenu3_iface;
@@ -615,6 +671,251 @@ error:
     heap_free(props);
 }
 
+static HRESULT WINAPI security_info_QueryInterface(ISecurityInformation *iface, REFIID iid, void **out)
+{
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+    if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_ISecurityInformation))
+    {
+        IUnknown_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+    else
+    {
+        *out = NULL;
+        WARN("%s is not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+        return E_NOINTERFACE;
+    }
+}
+
+static ULONG WINAPI security_info_AddRef(ISecurityInformation *iface)
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+    ULONG refcount = InterlockedIncrement(&info->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI security_info_Release(ISecurityInformation *iface)
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+    ULONG refcount = InterlockedIncrement(&info->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        HeapFree(GetProcessHeap(), 0, info->path);
+        HeapFree(GetProcessHeap(), 0, info);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI security_info_GetObjectInformation(ISecurityInformation *iface, SI_OBJECT_INFO *out)
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+
+    TRACE("iface %p, out %p.\n", iface, out);
+
+    memset(out, 0, sizeof(*out));
+    out->dwFlags = SI_ADVANCED;
+    out->hInstance = shell32_hInstance;
+    out->pszObjectName = info->path;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI security_info_GetSecurity(ISecurityInformation *iface,
+        SECURITY_INFORMATION mask, PSECURITY_DESCRIPTOR *sd, BOOL default_sd)
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+
+    TRACE("iface %p, mask %#x, sd %p, default_sd %d.\n", iface, mask, sd, default_sd);
+
+    if (default_sd)
+        FIXME("Returning a default security descriptor is not implemented.\n");
+
+    return HRESULT_FROM_WIN32(GetNamedSecurityInfoW(info->path, SE_FILE_OBJECT,
+            mask, NULL, NULL, NULL, NULL, sd));
+}
+
+static HRESULT WINAPI security_info_SetSecurity(ISecurityInformation *iface,
+        SECURITY_INFORMATION mask, PSECURITY_DESCRIPTOR sd)
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+    BOOL present, defaulted;
+    PSID owner, group;
+    ACL *dacl, *sacl;
+
+    TRACE("iface %p, mask %#x, sd %p.\n", iface, mask, sd);
+
+    if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted))
+        return HRESULT_FROM_WIN32(GetLastError());
+
+    if (!GetSecurityDescriptorGroup(sd, &group, &defaulted))
+        return HRESULT_FROM_WIN32(GetLastError());
+
+    if (!GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted))
+        return HRESULT_FROM_WIN32(GetLastError());
+    if (!present) dacl = NULL;
+
+    if (!GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted))
+        return HRESULT_FROM_WIN32(GetLastError());
+    if (!present) sacl = NULL;
+
+    return HRESULT_FROM_WIN32(SetNamedSecurityInfoW(info->path, SE_FILE_OBJECT,
+            mask, owner, group, dacl, sacl));
+}
+
+static HRESULT WINAPI security_info_GetAccessRights(ISecurityInformation *iface,
+        const GUID *type, DWORD flags, SI_ACCESS **access, ULONG *count, ULONG *default_access )
+{
+    struct security_info *info = impl_from_ISecurityInformation(iface);
+
+    TRACE("info %p, type %s, flags %#x, access %p, count %p, default_access %p.\n",
+            info, debugstr_guid(type), flags, access, count, default_access);
+
+    if (info->directory)
+    {
+        *access = (SI_ACCESS *)access_rights_directory;
+        *count = ARRAY_SIZE(access_rights_directory);
+    }
+    else
+    {
+        *access = (SI_ACCESS *)access_rights_file;
+        *count = ARRAY_SIZE(access_rights_file);
+    }
+
+    *default_access = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI security_info_MapGeneric(ISecurityInformation *iface,
+        const GUID *type, UCHAR *ace_flags, ACCESS_MASK *mask)
+{
+    GENERIC_MAPPING map =
+    {
+        FILE_GENERIC_READ,
+        FILE_GENERIC_WRITE,
+        FILE_GENERIC_EXECUTE,
+        FILE_ALL_ACCESS
+    };
+
+    TRACE("iface %p, type %s, ace_flags %p, mask %p.\n", iface, debugstr_guid(type), ace_flags, mask);
+
+    MapGenericMask(mask, &map);
+    return S_OK;
+}
+
+static HRESULT WINAPI security_info_GetInheritTypes(ISecurityInformation *iface,
+        SI_INHERIT_TYPE **types, ULONG *count)
+{
+    FIXME("iface %p, types %p, count %p, stub!\n", iface, types, count);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI security_info_PropertySheetPageCallback(ISecurityInformation *iface,
+        HWND hwnd, UINT msg, SI_PAGE_TYPE page)
+{
+    TRACE("iface %p, hwnd %p, msg %#x, page %#x.\n", iface, hwnd, msg, page);
+    return S_OK;
+}
+
+static const struct ISecurityInformationVtbl security_info_vtbl =
+{
+    security_info_QueryInterface,
+    security_info_AddRef,
+    security_info_Release,
+    security_info_GetObjectInformation,
+    security_info_GetSecurity,
+    security_info_SetSecurity,
+    security_info_GetAccessRights,
+    security_info_MapGeneric,
+    security_info_GetInheritTypes,
+    security_info_PropertySheetPageCallback,
+};
+
+static ISecurityInformation *create_security_info(WCHAR *path, BOOL directory)
+{
+    struct security_info *security;
+    DWORD len;
+
+    if (!(security = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*security))))
+        return NULL;
+
+    security->ISecurityInformation_iface.lpVtbl = &security_info_vtbl;
+    security->refcount = 1;
+    security->directory = directory;
+
+    len = (strlenW(path) + 1) * sizeof(WCHAR);
+    security->path = HeapAlloc(GetProcessHeap(), 0, len);
+    if (!security->path)
+    {
+        HeapFree(GetProcessHeap(), 0, security);
+        return NULL;
+    }
+
+    memcpy(security->path, path, len);
+    return &security->ISecurityInformation_iface;
+}
+
+static void init_security_properties_pages(IDataObject *pDo, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
+{
+    ISecurityInformation *security;
+    HPROPSHEETPAGE security_page;
+    FORMATETC format;
+    STGMEDIUM stgm;
+    DWORD attrib;
+    WCHAR *path;
+    UINT len;
+
+    format.cfFormat = CF_HDROP;
+    format.ptd      = NULL;
+    format.dwAspect = DVASPECT_CONTENT;
+    format.lindex   = -1;
+    format.tymed    = TYMED_HGLOBAL;
+
+    if (FAILED(IDataObject_GetData(pDo, &format, &stgm)))
+        return;
+
+    if (!(len = DragQueryFileW((HDROP)stgm.DUMMYUNIONNAME.hGlobal, 0, NULL, 0)))
+    {
+        ReleaseStgMedium(&stgm);
+        return;
+    }
+
+    if (!(path = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
+    {
+        ReleaseStgMedium(&stgm);
+        return;
+    }
+
+    len = DragQueryFileW((HDROP)stgm.DUMMYUNIONNAME.hGlobal, 0, path, len + 1);
+    ReleaseStgMedium(&stgm);
+    if (!len) goto done;
+
+    attrib = GetFileAttributesW(path);
+    if (attrib == INVALID_FILE_ATTRIBUTES)
+        goto done;
+
+    if (!(security = create_security_info(path, !!(attrib & FILE_ATTRIBUTE_DIRECTORY))))
+        goto done;
+
+    security_page = CreateSecurityPage(security);
+    IUnknown_Release((IUnknown *)security);
+    if (!security_page) goto done;
+
+    lpfnAddPage(security_page, lParam);
+
+done:
+    HeapFree(GetProcessHeap(), 0, path);
+}
+
+
 #define MAX_PROP_PAGES 99
 
 static void DoOpenProperties(ContextMenu *This, HWND hwnd)
@@ -697,6 +998,7 @@ static void DoOpenProperties(ContextMenu *This, HWND hwnd)
 	if (SUCCEEDED(ret))
 	{
             init_file_properties_pages(lpDo, Properties_AddPropSheetCallback, (LPARAM)&psh);
+            init_security_properties_pages(lpDo, Properties_AddPropSheetCallback, (LPARAM)&psh);
 
 	    hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
 	    if (hpsxa != NULL)
diff --git a/dlls/shell32/shresdef.h b/dlls/shell32/shresdef.h
index 92185d637e7..dfbe7d8588b 100644
--- a/dlls/shell32/shresdef.h
+++ b/dlls/shell32/shresdef.h
@@ -149,6 +149,26 @@
 #define IDM_RECYCLEBIN_RESTORE      301
 #define IDM_RECYCLEBIN_ERASE        302
 
+#define IDS_SECURITY_ADD_FILE           400
+#define IDS_SECURITY_ADD_SUBDIRECTORY   401
+#define IDS_SECURITY_ALL_ACCESS         402
+#define IDS_SECURITY_APPEND_DATA        403
+#define IDS_SECURITY_DELETE             404
+#define IDS_SECURITY_DELETE_CHILD       405
+#define IDS_SECURITY_EXECUTE            406
+#define IDS_SECURITY_LIST_DIRECTORY     407
+#define IDS_SECURITY_READ_ATTRIBUTES    408
+#define IDS_SECURITY_READ_CONTROL       409
+#define IDS_SECURITY_READ_DATA          410
+#define IDS_SECURITY_READ_EA            411
+#define IDS_SECURITY_SYNCHRONIZE        412
+#define IDS_SECURITY_TRAVERSE           413
+#define IDS_SECURITY_WRITE_ATTRIBUTES   414
+#define IDS_SECURITY_WRITE_DAC          415
+#define IDS_SECURITY_WRITE_DATA         416
+#define IDS_SECURITY_WRITE_EA           417
+#define IDS_SECURITY_WRITE_OWNER        418
+
 /* Note: this string is referenced from the registry*/
 #define IDS_RECYCLEBIN_FOLDER_NAME   8964
 
-- 
2.30.1




More information about the wine-devel mailing list