代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <Windows.h>
HANDLE creatFile(void);
long WriteBuffer(HANDLE);
char * GetBuffer(void);
void main(void)
{
HANDLE hFile;
printf("CreateFile: ");
hFile = creatFile();
if(hFile != NULL)
{
WriteBuffer(hFile);
FlushFileBuffers(hFile);
}
CloseHandle(hFile);
printf("\n\rDone");
getchar();
}
HANDLE creatFile(void)
{
HANDLE hFile;
LPCWSTR sFileName = L"\\\\.\\E:";
DWORD dwDesiredAccess = GENERIC_WRITE;
DWORD fShareMode = FILE_SHARE_WRITE | FILE_SHARE_WRITE;
DWORD fCreationDisposition = OPEN_EXISTING;
DWORD fFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
hFile = CreateFile(sFileName, dwDesiredAccess,fShareMode,
NULL, fCreationDisposition, fFlagsAndAttributes,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
hFile = NULL;
printf("INVALID_HANDLE_VALUE: ");
switch (GetLastError())
{
case 5:
printf("\n\r Administrative Account required to run this program\n\r");
break;
case 87:
printf("\n\r Invalid Parameter in CreateFile Call \n\r");
break;
default:
printf("Error %d\n",GetLastError());
break;
}
return NULL;
}
else
{
printf("Attached -> %d\n\r",hFile);
return hFile;
}
}
long WriteBuffer(HANDLE hFile)
{
char *str = GetBuffer(); // x 64 will give us 512 (sector sized buffer) ;
DWORD bytesWritten;
long totalBytesWritten = 0;
long idx = 0;
int len = strlen(str);
for(idx = 0; idx < 100000; idx ++)
{
if(WriteFile(hFile, str, 512 * sizeof(char), &bytesWritten, NULL))
{
totalBytesWritten += bytesWritten;
printf("Sectors Written : %d\r",idx+1);
}
else
{
int le = GetLastError();
printf("Last Error : %d\r",GetLastError());
break;
}
}
printf("\n\r");
printf("Bytes Written: %d\n\r", totalBytesWritten);
printf("Handle -> %d\n\r",hFile);
return totalBytesWritten;
}
char * GetBuffer(void)
{
int i = 0, idx = 0;
const char * cstr_init = "ERASED1 ";
char *buffer = (char*)malloc(512);
char word2[512];
for (idx = 0; idx < 512; idx+=8) {
for (i = 0; i < 8; i++) {
buffer[idx+i] = cstr_init[i];
if(strlen(buffer) == 512)
break;
}
}
return buffer;
}
问题:
问题:
如何修复WriteFile,使其在16个扇区之后不会失败...
如何修复GetBuffer,使其实际生成512缓冲区而不是528?
备注 该应用程序是ANSI C,该程序以管理员身份运行。
答案 0 :(得分:1)
我无法通过WriteFile()
说出错误,但是,您的字符串操作存在问题。
C字符串以空值终止,也就是说,字符串文字"abc"
实际上是一个字符数组,如:{'a','b','c','\0'}
所有str...()
操作都依赖于此事实。没有信息存储在字符串长度的任何地方,只有事实是它应该以{{1}}结尾。
您的'\0'
功能已改进:
GetBuffer()
你得到了char * GetBuffer(void)
{
int i = 0, idx = 0;
const char * cstr_init = "ERASED1 ";
char *buffer = malloc(513); // Space for a '\0'
for (idx = 0; idx < 512; idx+=8) {
for (i = 0; i < 8; i++) {
buffer[idx+i] = cstr_init[i];
}
}
}
的奇怪结果,因为它查找strlen()
并且只找到一个528字节,读取512字节以外的malloced正在调用未定义的行为,你可能找到了'\ 0'为513字节,或从未找到过。
其他评论,在调用'\0'
之后,你永远不会GetBuffer()
返回free()
,这是一个内存泄漏,因为它已被malloced并在该上下文之外丢失。此外,char *
的更好实现将是:
GetBuffer()
答案 1 :(得分:0)
INT类型只能是0到65536无符号的2字节数。用LONG(long)替换所有INT类型以开始...不确定您所处的编译器环境 - 因为此更改可能不适用
答案 2 :(得分:0)
我无法解决问题2 - 我喜欢的方式。但是,通过Telling WriteFile从528字节的缓冲区中写出512个字节 - 我得到了所需的结果。问题1。
因为磁盘驱动器上有文件系统 - Windows操作系统识别出这一事实并阻止写入完整驱动器。我需要做的就是锁定驱动器,这将使我可以独占访问驱动器。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <Windows.h>
#include <winioctl.h>
HANDLE creatFile(void);
long WriteBuffer(HANDLE);
char * GetBuffer(void);
void main(void)
{
HANDLE hFile;
printf("CreateFile: ");
hFile = creatFile();
if(hFile != NULL)
{
WriteBuffer(hFile);
FlushFileBuffers(hFile);
}
CloseHandle(hFile);
printf("\n\rDone");
getchar();
}
HANDLE creatFile(void)
{
HANDLE hFile;
LPCWSTR sFileName = L"\\\\.\\E:";
DWORD dwDesiredAccess = GENERIC_WRITE;
DWORD fShareMode = FILE_SHARE_WRITE | FILE_SHARE_WRITE;
DWORD fCreationDisposition = OPEN_EXISTING;
DWORD fFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
BOOL bResult = FALSE; // results flag
LPDWORD lpBytesReturned = 0;
hFile = CreateFile(sFileName, dwDesiredAccess,fShareMode,
NULL, fCreationDisposition, fFlagsAndAttributes,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
hFile = NULL;
printf("INVALID_HANDLE_VALUE: ");
switch (GetLastError())
{
case 5:
printf("\n\r Administrative Account required to run this program\n\r");
break;
case 87:
printf("\n\r Invalid Parameter in CreateFile Call \n\r");
break;
default:
printf("Error %d\n",GetLastError());
break;
}
return NULL;
}
else
{
printf("Attached -> %d\n\r",hFile);
// HERE I JUST ADD THE FSCTL_LOCK_VOLUME command to stop Windows preventing me from writing to the drive
bResult = DeviceIoControl(hFile, // device to be queried
FSCTL_LOCK_VOLUME, // dwIoControlCode
NULL, 0, // no input buffer
NULL, 0, // output buffer
lpBytesReturned, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
return hFile;
}
}
long WriteBuffer(HANDLE hFile)
{
char *str = GetBuffer(); // x 64 will give us 512 (sector sized buffer) ;
DWORD bytesWritten;
long totalBytesWritten = 0;
long idx = 0;
int len = strlen(str);
for(idx = 0; idx < 100000; idx ++)
{
if(WriteFile(hFile, str, 512 * sizeof(char), &bytesWritten, NULL))
{
totalBytesWritten += bytesWritten;
printf("Sectors Written : %d\r",idx+1);
}
else
{
int le = GetLastError();
printf("\n\rLast Error : %d\r",GetLastError());
break;
}
}
printf("\n\r");
printf("Bytes Written: %d\n\r", totalBytesWritten);
printf("Handle -> %d\n\r",hFile);
return totalBytesWritten;
}
char * GetBuffer(void)
{
const char * cstr_init = "ERASED2 ";
const int cstr_init_len = strlen(cstr_init);
char *buffer = (char*)malloc(513);
int i;
for (i = 0; i < 512; i+=8) {
memcpy(buffer+i, cstr_init, cstr_init_len);
// Or strcpy(buffer+1, cstr_init);
// Or strcat(buffer, cstr_init); // Inefficient because each call runs from buffer[0] to find a '\0' for where to start appending
}
return buffer;
}
因此,为了将来参考,如果您希望直接写入驱动器,首先锁定音量很重要。我知道上面的代码中存在内存泄漏 - 但作为将数据写入驱动器的学习练习,我并不感到困扰。代码将被整理并制作成.dll