【发布时间】:2017-11-20 14:16:16
【问题描述】:
我试图让BackupRead() 和BackupWrite() 使用http://pinvoke.net 作为我的参考。我在谷歌找到的大多数答案都是引用 C++ 甚至是 Delphi...我想用他们的 ACL 备份一个文件/文件夹。
编辑:
这是我当前的代码(我正在为SE_BACKUP_NAME 和SE_RESTORE_NAME 和SE_TAKE_OWNERSHIP_NAME 设置权限):
var bReadHandle = ArchiveWinApi.CreateFile(sourcePath, (uint)(ArchiveWinApi.ACCESS_MASK.GENERIC_READ | ArchiveWinApi.ACCESS_MASK.READ_CONTROL | ArchiveWinApi.ACCESS_MASK.ACCESS_SYSTEM_SECURITY), 0, IntPtr.Zero, FileMode.Open, ArchiveWinApi.ExtendedFileAttributes.BackupSemantics, IntPtr.Zero);
if (!IsValid(bReadHandle))
{
var error = GetLastWin32Error();
throw new Exception("InvalidFileHandle");
}
var bWriteHandle = ArchiveWinApi.CreateFile(destPath, (uint)(ArchiveWinApi.ACCESS_MASK.GENERIC_WRITE | ArchiveWinApi.ACCESS_MASK.WRITE_OWNER | ArchiveWinApi.ACCESS_MASK.WRITE_DAC | ArchiveWinApi.ACCESS_MASK.ACCESS_SYSTEM_SECURITY), 0, IntPtr.Zero, FileMode.Create, ArchiveWinApi.ExtendedFileAttributes.BackupSemantics, IntPtr.Zero);
if (!IsValid(bWriteHandle))
{
var error = GetLastWin32Error();
throw new Exception("InvalidFileHandle");
}
var bufferSize = 4096;
var buffer = Marshal.AllocHGlobal(bufferSize);
var backupReadContext = IntPtr.Zero;
var backupWriteContext = IntPtr.Zero;
uint lpNumberOfBytesRead = 0;
uint lpNumberOfBytesWritten = 0;
while (true)
{
var result = ArchiveWinApi.BackupRead(bReadHandle, out buffer, (uint) bufferSize, out lpNumberOfBytesRead, false, true, ref backupReadContext);
if (!result)
{
var error = GetLastWin32Error();
throw new Exception("BackupRead failed");
}
if (lpNumberOfBytesRead == 0) break;
result = ArchiveWinApi.BackupWrite(bWriteHandle, buffer, lpNumberOfBytesRead, out lpNumberOfBytesWritten, false, true, ref backupWriteContext);
if (!result)
{
var error = GetLastWin32Error();
throw new Exception("BackupWrite failed");
}
}
ArchiveWinApi.BackupRead(bReadHandle, out buffer, 0, out lpNumberOfBytesRead, true, true, ref backupReadContext);
ArchiveWinApi.CloseHandle(bReadHandle);
ArchiveWinApi.BackupWrite(bWriteHandle, buffer, 0, out lpNumberOfBytesWritten, true, true, ref backupWriteContext);
ArchiveWinApi.CloseHandle(bWriteHandle);
我收到 System.AccessViolationException: 'Attempted to read or write protected memory。这通常表明其他内存已损坏。'
编辑 2:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool BackupRead(IntPtr hFile, out IntPtr lpBuffer, [MarshalAs(UnmanagedType.U4)] uint nNumberOfBytesToRead, [MarshalAs(UnmanagedType.U4)] out uint lpNumberOfBytesRead, [MarshalAs(UnmanagedType.Bool)] bool bAbort, [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, ref IntPtr lpContext);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool BackupWrite(IntPtr hFile, IntPtr lpBuffer, [MarshalAs(UnmanagedType.U4)] uint nNumberOfBytesToWrite, [MarshalAs(UnmanagedType.U4)] out uint lpNumberOfBytesWritten, [MarshalAs(UnmanagedType.Bool)] bool bAbort, [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, ref IntPtr lpContext);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPWStr)] string lpFileName, [MarshalAs(UnmanagedType.U4)] uint dwDesiredAccess, [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, IntPtr lpSecurityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition, [MarshalAs(UnmanagedType.U4)] ExtendedFileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
public enum ACCESS_MASK : uint
{
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
ACCESS_SYSTEM_SECURITY = 0x01000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_ALL = 0x10000000,
}
[Flags]
public enum ExtendedFileAttributes
{
BackupSemantics = 33554432,
}
【问题讨论】:
-
lpBuffer设置为您分配的缓冲区,nNumberOfBytesToRead不能超过缓冲区lpBuffer的大小(通常完全正确)。它不能是文件的大小,lpNumberOfBytesRead是指向接收读取字节数的变量的指针。 -
我应该为缓冲区分配多少?
-
你想要多少。仅不小于
WIN32_STREAM_ID的大小。通常在 0x10000 - 0x100000 范围内 -
已编辑问题,包含代码和当前进度