- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我写了下面的代码来将 0xFF 写入我的 USB 存储设备上的所有字节。出于某种原因,WriteFile()
调用在扇区 242 处开始出错。我在两个单独的 USB 存储设备上完成了此操作,然后在十六进制编辑器中检查了这些设备。扇区 242 似乎是 FAT16 格式设备上文件分配表的开始,也是 NTFS 设备上引导区的开始。我敢肯定它在这些确切位置出错并非巧合,但我不知道如何改变这种行为。 WriteFile
失败时我收到的 HRESULT
是 -2147024891,即 E_ACCESSDENIED
。有谁知道可能导致问题的原因是什么?
注意:如果您要在本地系统上运行此代码,请务必小心,因为我已经为我的 USB 设备硬编码了物理设备 ID。请确保使用您尝试写入的设备更新 deviceId 变量。你不想破坏你的硬盘。
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer([In] SafeFileHandle hFile, [In] long lDistanceToMove, [Out] out int lpDistanceToMoveHigh, [In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32", SetLastError = true)]
internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes, int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);
[DllImport("kernel32.dll", SetLastError = true)]
internal extern static int WriteFile(SafeFileHandle handle, byte[] bytes, int numBytesToWrite, out int numBytesWritten, IntPtr overlapped_MustBeZero);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool DeviceIoControl(SafeFileHandle hDevice, uint dwIoControlCode, byte[] lpInBuffer, int nInBufferSize, byte[] lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool CloseHandle(SafeFileHandle handle);
public void wipeDisk()
{
const uint OPEN_EXISTING = 3;
const uint GENERIC_WRITE = (0x40000000);
const uint FSCTL_LOCK_VOLUME = 0x00090018;
const uint FSCTL_UNLOCK_VOLUME = 0x0009001c;
const uint FSCTL_DISMOUNT_VOLUME = 0x00090020;
bool success = false;
int intOut;
string deviceId = @"\\.\PHYSICALDRIVE2";
long DiskSize = 2056320000;
SafeFileHandle diskHandle = CreateFile(deviceId, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (diskHandle.IsInvalid)
{
Console.WriteLine(deviceId + " open error.");
return;
}
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": opened.");
success = DeviceIoControl(diskHandle, FSCTL_LOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero);
if (!success)
{
Console.WriteLine(deviceId + " lock error.");
CloseHandle(diskHandle);
return;
}
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": locked.");
success = DeviceIoControl(diskHandle, FSCTL_DISMOUNT_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero);
if (!success)
{
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": dismount error.");
DeviceIoControl(diskHandle, FSCTL_UNLOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero);
CloseHandle(diskHandle);
return;
}
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": unmounted.");
int numBytesPerSector = 512;
long numTotalSectors = DiskSize / 512;
byte[] junkBytes = new byte[512];
for (int x = 0; x < 512; x++)
{
junkBytes[x] = 0xFF;
}
for (long sectorNum = 0; sectorNum < numTotalSectors; sectorNum++)
{
int numBytesWritten = 0;
int moveToHigh;
uint rvalsfp = SetFilePointer(diskHandle, sectorNum * numBytesPerSector, out moveToHigh, EMoveMethod.Begin);
Console.WriteLine("File pointer set " + Marshal.GetHRForLastWin32Error().ToString() + ": " + (sectorNum * numBytesPerSector).ToString());
int rval = WriteFile(diskHandle, junkBytes, junkBytes.Length, out numBytesWritten, IntPtr.Zero);
if (numBytesWritten != junkBytes.Length)
{
Console.WriteLine("Write error on track " + sectorNum.ToString() + " from " + (sectorNum * numBytesPerSector).ToString() + "-" + moveToHigh.ToString() + " " + Marshal.GetHRForLastWin32Error().ToString() + ": Only " + numBytesWritten.ToString() + "/" + junkBytes.Length.ToString() + " bytes written.");
break;
}
else
{
Console.WriteLine("Write success " + Marshal.GetHRForLastWin32Error().ToString() + ": " + numBytesWritten.ToString() + "/" + junkBytes.Length.ToString() + " bytes written.");
}
}
success = DeviceIoControl(diskHandle, FSCTL_UNLOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero);
if (success)
{
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": unlocked.");
}
else
{
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": unlock error: " + Marshal.GetHRForLastWin32Error().ToString());
}
success = CloseHandle(diskHandle);
if (success)
{
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": handle closed.");
}
else
{
Console.WriteLine(deviceId + " " + Marshal.GetHRForLastWin32Error().ToString() + ": close handle error: " + Marshal.GetHRForLastWin32Error().ToString());
}
}
编辑/更新
在使用第三方工具对 USB 设备进行低级别删除后,我能够成功实现此功能。驱动器完全清零后,我能够成功写入设备。似乎 Windows 在识别出有效的 fat 或 ntfs 文件系统以及使用
const uint FSCTL_LOCK_VOLUME = 0x00090018;
const uint FSCTL_DISMOUNT_VOLUME = 0x00090020;
与 DeviceIoControl
配对似乎不会覆盖设备上的锁定窗口。
有谁知道如何在具有有效文件系统的驱动器上使用 DeviceIoControl
在 Windows 中成功锁定可移动 USB 设备?
我已经使用了几个第三方工具来完成我想做的事情,并且它们都能成功运行。我知道这是可能的,但我阅读的所有 MSDN 文档都没有帮助解决问题。
编辑/更新 2
这取自https://web.archive.org/web/20130507212546/http://msdn.microsoft.com/en-us/library/ff551353.aspx
The application needs to lock the volume, dismount the volume, or both, before it can issue DASD I/O. This is new to Windows Vista and was done to address potentially malicious techniques.
The file system will block all write operations to reserved sections of the disk. In this case, those reserved sections include the MBR and the two FAT areas. To block these areas, you need to lock the volume by sending FSCTL_LOCK_VOLUME. You must issue this structure on the same volume handle that performs the actual write operations. This request can fail if there are open file handles. In this case, the application can force a dismount of the file system by issuing FSCTL_DISMOUNT_VOLUME. However, the volume is not actually dismounted until the file handle is closed. Until then, the application can continue to issue DASD I/O by using the same file handle that is currently open.
There is an extended region beyond the volume space that is known to the file system where write operations will be blocked. To allow write operations to this region, you must issue FSCTL_ALLOW_EXTENDED_DASD_IO on the volume handle.
You can use the Win32 API routine DeviceIoControl to issue all the previous FSCTSs.
我相信这正是我们在上面的代码中实现的,但它似乎没有正常工作。我们正在获取句柄并正在锁定和卸载设备,因此我们应该能够正确地写入 protected 区域?
编辑/更新 3
好的,这是当前打开磁盘和卷的顺序。锁定、卸载等方法按照我们认为错误的顺序工作。
SafeFileHandle volumeHandle = CreateFile("\\.\E:",...);
LockVolume(volumeHandle);
DismountVolume(volumeHandle);
SafeFileHandle diskHandle = CreateFile("\\.\PHYSICALDRIVE1"...);
WriteStuff(diskHandle);
//Fails...
UnlockVolume(volumeHandle);
CloseVolume(volumeHandle);
CloseDisk(diskHandle);
我仍然得到相同的结果,它只在磁盘被丢弃时有效。
最佳答案
disk 和 drive 之间存在混淆。
如果你想完全访问一个磁盘(你正在使用\\.\PHYSICALDRIVE
),你必须锁定所有挂载的卷,它们基本上是物理磁盘的所有分区(即驱动器)。
不是在 CreateFile("\\.\PHYSICALDRIVE"...)
返回的句柄上使用 FSCTL_LOCK_VOLUME
,而是获取每个已安装卷的句柄(这是一个驱动器,而不是物理磁盘)使用 string.Replace("\\\\.\\{0}:", DriveLetter)
模式。
您可以使用 IOCTL_DISK_GET_DRIVE_LAYOUT
获取给定物理磁盘的已安装卷列表(最终,您需要一个字母列表)。
编辑:
来自 MSDN :
A write on a disk handle will succeed if one of the following conditions is true:
The sectors to be written to do not fall within a volume's extents.
The sectors to be written to fall within a mounted volume, but you have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The sectors to be written to fall within a volume that has no mounted file system other than RAW.
所以基本上,您应该做的是:
FSCTL_LOCK_VOLUME
或 FSCTL_DISMOUNT_VOLUME
。如果卷中没有文件正在使用(即任何进程都没有打开任何文件的句柄),FSCTL_LOCK_VOLUME
就足够了还要确保您正在使用管理员权限(提升的进程)运行您的应用程序。
关于C# WriteFile() 在 USB 驱动器的扇区 242 处停止写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12081343/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!