0

I am trying to open a Windows Permissions dialog for Named Pipes.
I saw that Process Hacker does it like that on \Device\NamedPipe\InitShutdown:
enter image description here

I used this answer on named pipe but it only works for file paths.
The code (see down below), failed when running:

hr = SHILCreateFromPath(Path.GetDirectoryName(path), out folderPidl, IntPtr.Zero);

The function throws an exception:

The network path was not found

I supposed I need to find a way to generate folderPidl (PIDL) from a named pipe but I am not sure how to do it.

Notice that I can get the named pipe permissions through the NtObjectManager library so this is not the problem, I am searching for a way to do it with the Windows permissions dialog.

PS C:\Users\eviatar> $a=Get-NtFile("\Device\NamedPipe\InitShutdown")
PS C:\Users\eviatar> $a

Handle Name         NtTypeName Inherit ProtectFromClose
------ ----         ---------- ------- ----------------
3276   InitShutdown File       False   False


PS C:\Users\eviatar> $a.SecurityDescriptor.Dacl

Type    User                         Flags Mask
----    ----                         ----- ----
Allowed Everyone                     None  0012019B
Allowed NT AUTHORITY\ANONYMOUS LOGON None  0012019B
Allowed BUILTIN\Administrators       None  001F01FF

The code:

// Program.cs

string path = @"\\.\pipe\InitShutdown";
//path = @"\Device\NamedPipe\InitShutdown";
//path = @"C:\tmp";
PermissionDialog.Show(IntPtr.Zero, path);

----------------------
// PermissionDialog.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace NamePipeViewer
{
    // https://stackoverflow.com/questions/28035464/how-does-one-invoke-the-windows-permissions-dialog-programmatically
    public static class PermissionDialog
    {
        public static bool Show(IntPtr hwndParent, string path)
        {
            if (path == null)
                throw new ArgumentNullException("path");

            SafePidlHandle folderPidl;
            int hr;
            hr = SHILCreateFromPath(Path.GetDirectoryName(path), out folderPidl, IntPtr.Zero);
            if (hr != 0)
                throw new Win32Exception(hr);

            SafePidlHandle filePidl;
            hr = SHILCreateFromPath(path, out filePidl, IntPtr.Zero);
            if (hr != 0)
                throw new Win32Exception(hr);

            IntPtr file = ILFindLastID(filePidl);

            System.Runtime.InteropServices.ComTypes.IDataObject ido;
            hr = SHCreateDataObject(folderPidl, 1, new IntPtr[] { file }, null, typeof(System.Runtime.InteropServices.ComTypes.IDataObject).GUID, out ido);
            if (hr != 0)
                throw new Win32Exception(hr);

            // if you get a 'no such interface' error here, make sure the running thread is STA
            IShellExtInit sei = (IShellExtInit)new SecPropSheetExt();
            sei.Initialize(IntPtr.Zero, ido, IntPtr.Zero);

            IShellPropSheetExt spse = (IShellPropSheetExt)sei;
            IntPtr securityPage = IntPtr.Zero;
            spse.AddPages((p, lp) =>
            {
                securityPage = p;
                return true;
            }, IntPtr.Zero);

            PROPSHEETHEADER psh = new PROPSHEETHEADER();
            psh.dwSize = Marshal.SizeOf(psh);
            psh.hwndParent = hwndParent;
            psh.nPages = 1;
            psh.phpage = Marshal.AllocHGlobal(IntPtr.Size);
            Marshal.WriteIntPtr(psh.phpage, securityPage);

            // TODO: adjust title & icon here, also check out the available flags
            psh.pszCaption = "Permissions for '" + path + "'";

            IntPtr res;
            try
            {
                res = PropertySheet(ref psh);
            }
            finally
            {
                Marshal.FreeHGlobal(psh.phpage);
            }
            return res == IntPtr.Zero;
        }

        private class SafePidlHandle : SafeHandle
        {
            public SafePidlHandle()
                : base(IntPtr.Zero, true)
            {
            }

            public override bool IsInvalid
            {
                get { return handle == IntPtr.Zero; }
            }

            protected override bool ReleaseHandle()
            {
                if (IsInvalid)
                    return false;

                Marshal.FreeCoTaskMem(handle);
                return true;
            }
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct PROPSHEETHEADER
        {
            public int dwSize;
            public int dwFlags;
            public IntPtr hwndParent;
            public IntPtr hInstance;
            public IntPtr hIcon;
            public string pszCaption;
            public int nPages;
            public IntPtr nStartPage;
            public IntPtr phpage;
            public IntPtr pfnCallback;
        }

        [DllImport("shell32.dll")]
        private static extern IntPtr ILFindLastID(SafePidlHandle pidl);

        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        private static extern int SHILCreateFromPath(string pszPath, out SafePidlHandle ppidl, IntPtr rgflnOut);

        [DllImport("shell32.dll")]
        private static extern int SHCreateDataObject(SafePidlHandle pidlFolder, int cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out System.Runtime.InteropServices.ComTypes.IDataObject ppv);

        [DllImport("comctl32.dll", CharSet = CharSet.Unicode)]
        private static extern IntPtr PropertySheet(ref PROPSHEETHEADER lppsph);

        private delegate bool AddPropSheetPage(IntPtr page, IntPtr lParam);

        [ComImport]
        [Guid("1f2e5c40-9550-11ce-99d2-00aa006e086c")] // this GUID points to the property sheet handler for permissions
        private class SecPropSheetExt
        {
        }

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("000214E8-0000-0000-C000-000000000046")]
        private interface IShellExtInit
        {
            void Initialize(IntPtr pidlFolder, System.Runtime.InteropServices.ComTypes.IDataObject pdtobj, IntPtr hkeyProgID);
        }

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("000214E9-0000-0000-C000-000000000046")]
        private interface IShellPropSheetExt
        {
            void AddPages([MarshalAs(UnmanagedType.FunctionPtr)] AddPropSheetPage pfnAddPage, IntPtr lParam);
            void ReplacePage(); // not fully defined, we don't use it 
        }
    }
}


E235
  • 11,560
  • 24
  • 91
  • 141

0 Answers0