Нужно получить права на чтение и запись залоченого фолдера.
Или как сделать следующий код валидным:
DirectoryInfo dir = new DirectoryInfo(@"D:/System Volume Information");
foreach (var item in dir.GetDirectories())
{
Console.WriteLine(item.FullName);
}
Желательно что бы работало с System Volume Information
Следующий код не работает тоже:
[Flags]
enum MoveFileFlags
{
MOVEFILE_REPLACE_EXISTING = 0x00000001,
MOVEFILE_COPY_ALLOWED = 0x00000002,
MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
MOVEFILE_WRITE_THROUGH = 0x00000008,
MOVEFILE_CREATE_HARDLINK = 0x00000010,
MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
static void Main(string[] args)
{
string path = @"D:/System Volume Information";
DirectoryInfo dir = new DirectoryInfo(path);
MoveFileEx(path, path + "2", MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
string msg = new Win32Exception(Marshal.GetLastWin32Error()).Message;
Console.WriteLine(msg);
}
Ответ
Ага, я нашёл, как Far это делает.
Он не просто запускает процесс от имени администратора (на самом деле, дочерний процесс, с которым связывается через pipe). Этот самый дочерний процесс, будучи запущенным от имени администратора, имеет право затребовать себе привилегии Backup и Restore (вот официальный метод, как сделать такое на чистом WinAPI). Что он и делает. Имея эти привилегии, дочерний процесс может делать всё
Мораль: вы можете ограничить в правах административный процесс, но он может снять ваши ограничения.
Для читателей, вот работающий код: (разумеется, вы должны добавить манифест, как указано в ответе @Dmitry)
class Program
{
static public void Main()
{
using (var outf = File.CreateText(@"D:\dirlist.txt"))
{
if (!RequestSeBackupPrivilege())
{
outf.WriteLine("Cannot request privilege: ");
return;
}
try
{
string path = @"D:\System Volume Information";
var dir = new DirectoryInfo(path);
foreach (var item in dir.GetFileSystemInfos())
outf.WriteLine(item.FullName);
}
catch (Exception ex)
{
outf.WriteLine("Exception:");
outf.Write(ex);
}
}
}
static bool RequestSeBackupPrivilege()
{
LUID luid;
if (!LookupPrivilegeValue(null, "SeBackupPrivilege", out luid))
return false;
TOKEN_PRIVILEGES_SINGLE tp = new TOKEN_PRIVILEGES_SINGLE
{
PrivilegeCount = 1,
Luid = luid,
Attributes = SE_PRIVILEGE_ENABLED
};
IntPtr hToken;
return
OpenProcessToken(
GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken) &&
AdjustTokenPrivileges(
hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero) &&
(Marshal.GetLastWin32Error() != ERROR_NOT_ALL_ASSIGNED);
}
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_QUERY = 0x00000008;
const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
const int ERROR_NOT_ALL_ASSIGNED = 1300;
[DllImport("kernel32.dll", ExactSpelling = true)]
static extern IntPtr GetCurrentProcess();
[StructLayout(LayoutKind.Sequential)]
struct TOKEN_PRIVILEGES_SINGLE
{
public UInt32 PrivilegeCount;
public LUID Luid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
struct LUID
{
public uint LowPart;
public int HighPart;
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LookupPrivilegeValue(
string lpSystemName, string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(
IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool AdjustTokenPrivileges(
IntPtr htok, bool disall, ref TOKEN_PRIVILEGES_SINGLE newst,
int len, IntPtr prev, IntPtr relen);
}
Определения структур данных взяты на pinvoke.net.
Комментариев нет:
Отправить комментарий