Long story short, I'm trying to query the recycle bin as another user. This is a WPF app with a service, and I need to query the recycle bin within the service... I know... We need to use NetNamedPipeBinding
, and can't use the OperationBehavior
attribute.
Thus far, I've had success in my Windows 10 VM with the following method:
OpenProcess
for a known pid (our WPF app), which is running under the user (tester) to impersonateOpenProcessToken
to get their token.WindowsIdentity.Impersonate()
SHQueryRecycleBin
to query the recycle bin.I've then tried the same code in a Windows XP VM, and I can't get it work. As soon as SHQueryRecycleBin
is called, I get an message box display stating that:
The Recycle Bin on C:\ is corrupted. Do you want to empty the Recycle Bin for this drive?
I know this is not true, as I can query the recycle bin if I'm running as tester, and also view it via windows explorer.
This looks like a common issue, and I found a Microsoft KB article. This is listed under causes:
This problem can occur when the logical drive that is referenced is an NTFS drive and there was an error in a permissions-compare operation.
I believe all my problems are related to permissions. But this is where I'm stuck. I don't know why I don't have the necessary permissions, and don't have any idea how to troubleshoot this problem. Does anyone have any ideas?
I've tried using ProcessAccessFlags.All
, TOKEN_ALL_ACCESS
, and AdjustTokenPrivileges
as a long shot, which didn't help.
I've been testing this with LINQPad, and using this SO answer to run LINQPad under the system account. For completeness here's a snippet which should copy / paste easily, and the output running under tester and system.
Running as tester:
OpenProcessToken returned 1
AdjustTokenPrivileges = True
Got user's token as 2264
Process running as XPTESTER\tester
Impersonating XPTESTER\tester
hresult=0, cbSize=20, i64Size=160420, i64NumItems=8
Running as system:
OpenProcessToken returned 1
AdjustTokenPrivileges = True
Got user's token as 2128
Process running as NT AUTHORITY\SYSTEM
Impersonating XPTESTER\tester
hresult=0, cbSize=20, i64Size=0, i64NumItems=0
Crude testing code:
void Main()
{
string drive = "C:";
uint pid = 1676;
IntPtr userToken = DuplicateProcessToken(pid);
LUID tLuid = new LUID();
TOKEN_PRIVILEGES NewState = new TOKEN_PRIVILEGES();
NewState.PrivilegeCount = 1;
NewState.Privileges.pLuid = tLuid;
NewState.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
var adjustResult = AdjustTokenPrivileges(userToken, false, ref NewState, (uint)Marshal.SizeOf(NewState), IntPtr.Zero, IntPtr.Zero);
Console.WriteLine("AdjustTokenPrivileges = {0}", adjustResult);
Console.WriteLine("Got user's token as {0}", userToken);
Console.WriteLine("Process running as {0}", WindowsIdentity.GetCurrent().Name);
using(var impersonatedUser = WindowsIdentity.Impersonate(userToken))
{
var winIdentity = WindowsIdentity.GetCurrent();
Console.WriteLine("Impersonating {0}", winIdentity.Name);
var result = new SHQUERYRBINFO();
result.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));
int hresult = SHQueryRecycleBin(drive, ref result);
Console.WriteLine(
"hresult={0}, cbSize={1}, i64Size={2}, i64NumItems={3}",
hresult,
result.cbSize,
result.i64Size,
result.i64NumItems);
}
}
public const Int32 SE_PRIVILEGE_ENABLED = 0x00000002;
public static IntPtr DuplicateProcessToken(uint pid)
{
IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, 0, pid);
uint uPriv = TOKEN_ALL_ACCESS;
IntPtr token = IntPtr.Zero;
int result = OpenProcessToken(hProcess, uPriv, ref token);
Console.WriteLine("OpenProcessToken returned {0}", result);
return token;
}
public const uint STANDARD_RIGHTS_REQUIRED = 0x00F0000;
public const uint STANDARD_RIGHTS_READ = 0x002000;
public const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
public const uint TOKEN_DUPLICATE = 0x0002;
public const uint TOKEN_IMPERSONATE = 0x004;
public const uint TOKEN_QUERY = 0x0008;
public const uint TOKEN_QUERY_SOURCE = 0x0010;
public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const uint TOKEN_ADJUST_GROUPS = 0x0040;
public const uint TOKEN_ADJUST_DEFAULT = 0x0080;
public const uint TOKEN_ADJUST_SESSIONID = 0x0100;
public const uint TOKEN_READ = (STANDARD_RIGHTS_REQUIRED | TOKEN_QUERY);
public const uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED
| TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE
| TOKEN_IMPERSONATE
| TOKEN_QUERY
| TOKEN_QUERY_SOURCE
| TOKEN_ADJUST_PRIVILEGES
| TOKEN_ADJUST_GROUPS
| TOKEN_ADJUST_DEFAULT
| TOKEN_ADJUST_SESSIONID);
// Pack = 8 for x64
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct SHQUERYRBINFO
{
public int cbSize;
public long i64Size;
public long i64NumItems;
}
[DllImport("shell32.dll", SetLastError = true)]
private static extern int SHQueryRecycleBin(string pszRootPath, ref SHQUERYRBINFO pSHQueryRBInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, int blnheritHanfle, uint dwAppProcessId);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern int OpenProcessToken(IntPtr processHandle, uint desiredAccess, ref IntPtr tokenHandle);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AdjustTokenPrivileges(
IntPtr TokenHandle,
[MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
ref TOKEN_PRIVILEGES NewState,
UInt32 BufferLength,
IntPtr PreviousState,
IntPtr ReturnLength);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LUID
{
public Int32 LowPart;
public Int32 HighPart;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LUID_AND_ATTRIBUTES
{
public LUID pLuid;
public Int32 Attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TOKEN_PRIVILEGES
{
public Int32 PrivilegeCount;
public LUID_AND_ATTRIBUTES Privileges;
}
User contributions licensed under CC BY-SA 3.0