如何在C#中使用CreateFile打开目录以检查已删除文件的条目?或者现在不可能?我记得当能够使用CreateFile或可能的CreateFileEx在NTFS分区上打开目录时,但是在旧操作系统下使用C++.
到目前为止,我已经有足够的Windows API调用(到kernel32.dll)读取现有文件,但它不会打开目录:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Runtime.ConstrainedExecution;
using System.Security;
namespace Kernel_Test
{
class Program
{
static void Main(string[] args)
{
Kernel_Tools cKT = new Kernel_Tools();
cKT.DoTest("C:\\Temp");
cKT.DoTest("C:\\Temp\\test.txt");
}
}
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
class Kernel_Tools
{
public void DoTest(string cTarget)
{
IntPtr cFile = NativeMethods.CreateFile(
cTarget,
NativeMethods.GENERIC_READ /* 0 or NativeMethods.GENERIC_READ */ ,
FileShare.Read,
IntPtr.Zero /* failed try: NativeMethods.OPEN_ALWAYS */,
(FileMode) NativeMethods.OPEN_EXISTING,
NativeMethods.FILE_FLAG_BACKUP_SEMANTICS /* 0 */ ,
IntPtr.Zero);
Console.WriteLine(cTarget);
Console.WriteLine(cFile);
if ((int)cFile != -1)
{
int length = 20;
byte[] bytes = new byte[length];
int numRead = 0;
int ErrorCheck = NativeMethods.ReadFile(cFile, bytes, length, out numRead, IntPtr.Zero);
// This sample code will not work for all files.
//int r = NativeMethods.ReadFile(_handle, bytes, length, out numRead, IntPtr.Zero);
// Since we removed MyFileReader's finalizer, we no longer need to
// call GC.KeepAlive here. Platform invoke will keep the SafeHandle
// instance alive for the duration of the call.
if (ErrorCheck == 0)
{
Console.WriteLine("Read failed.");
NativeMethods.CloseHandle(cFile);
return;
//throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (numRead < length)
{
byte[] newBytes = new byte[numRead];
Array.Copy(bytes, newBytes, numRead);
bytes = newBytes;
}
for (int i = 0; i < bytes.Length; i++)
Console.Write((char)bytes[i]);
Console.Write("\n\r");
// Console.WriteLine();
NativeMethods.CloseHandle(cFile);
}
}
}
[SuppressUnmanagedCodeSecurity()]
internal static class NativeMethods
{
// Win32 constants for accessing files.
internal const int GENERIC_READ = unchecked((int)0x80000000);
internal const int FILE_FLAG_BACKUP_SEMANTICS = unchecked((int)0x02000000);
internal const int OPEN_EXISTING = unchecked((int)3);
// Allocate a file object in the kernel, then return a handle to it.
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
internal extern static IntPtr CreateFile(
String fileName,
int dwDesiredAccess,
System.IO.FileShare dwShareMode,
IntPtr securityAttrs_MustBeZero,
System.IO.FileMode dwCreationDisposition,
int dwFlagsAndAttributes,
IntPtr hTemplateFile_MustBeZero);
// Use the file handle.
[DllImport("kernel32", SetLastError = true)]
internal extern static int ReadFile(
IntPtr handle,
byte[] bytes,
int numBytesToRead,
out int numBytesRead,
IntPtr overlapped_MustBeZero);
// Free the kernel's file object (close the file).
[DllImport("kernel32", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal extern static bool CloseHandle(IntPtr handle);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑1:修改它以使用OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS和GENERIC_READ.
当作为Vista管理用户运行时,这将打开并显示指定文本文件的开头,与原始文件一样,但仍无法打开目录.我猜我需要SE_BACKUP_NAME和SE_RESTORE_NAME权限,但我不确定如何指定除了将其作为本地计算机运行的服务(我只有最模糊的想法).
AFAIK,这是一个相当复杂的过程.您不能只使用CreateFile并枚举"已删除的文件".您必须加载驱动器的主文件表,并枚举标记为已删除的文件,然后尝试从MFT中列出的磁盘位置加载数据.这将需要大量的Platform Invoked代码,并且可能需要对C#中的本机数据结构进行一些重新定义.
对你的问题的简短回答是这样的:
CreateFile("\\\\.\\PhysicalDrive0",
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
NULL)
Run Code Online (Sandbox Code Playgroud)
您使用create file打开磁盘本身.
这是关于Code Project整个过程的一篇非常好的文章.但是,这一切都在c ++中.代码在那里,似乎你知道如何p\invoke,所以移植它不应该是一个问题.
编辑:
驱动器是外置的这一事实不应该让它变得更难,你仍然可以像我展示的那样打开磁盘(也许在连接驱动器后使用WMI工具查找路径).然后,您可以使用Wiki32页面上的FAT32信息来定义您可以读取MFT和文件系统的其他部分的数据结构.到达目的地后,您只需遍历目录表中的32字节文件定义,查看第一个字节:
0xE5 Entry has been previously erased and is available. File undelete utilities must replace this character with a regular character as part of the undeletion process.
Run Code Online (Sandbox Code Playgroud)