В этом случае
CreateFile
может легко потерпеть неудачу либо потому, что требуется доступ администратора, либо потому, что "\\\\.\\PhysicalDrive0"
- это неправильный диск.Базовая проверка ошибок настоятельно рекомендуется для любой файловой операции.
Запустите программу с правами администратора и убедитесь, что "\\\\.\\PhysicalDrive0"
- правильный диск (это не всегда C:\
)
SetFilePointerEx
не требуется, если вы читаете файл впоследовательность.Указатель файла автоматически перемещается вперед после каждого ReadFile
#define UNICODE
#include <stdio.h>
#include <Windows.h>
int main(void)
{
HANDLE handle = CreateFile(L"\\\\.\\PhysicalDrive0",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
//wrong disk, or admin access required
DWORD err = GetLastError();
printf("!CreateFile, GetLastError: %d\n", err);
CloseHandle(handle);
return 0;
}
DWORD br = 0;
DISK_GEOMETRY dg;
if(!DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY,
0, 0, &dg, sizeof(dg), &br, 0))
{
DWORD err = GetLastError();
printf("!DeviceIoControl, GetLastError: %d\n", err);
return 0;
}
LARGE_INTEGER t1 = dg.Cylinders;
int t2 = dg.TracksPerCylinder;
int t3 = dg.SectorsPerTrack;
int t4 = dg.BytesPerSector;
unsigned long long total = t1.QuadPart*t2*t3*t4;
printf("%lld\n", t1.QuadPart);
printf("%d\n", t2);
printf("%d\n", t3);
printf("%d\n", t4);
printf("%llu\n", total);
//setup a counter
long long i = 0;
int bufsize = dg.BytesPerSector;
char *buf = malloc(bufsize);
while(ReadFile(handle, buf, bufsize, &br, NULL))
{
if(!br)
break;
//print update
if((i % 1000) == 0)
printf("%.2f Mb\n", (double)i * bufsize / 1000000.0f);
i++;
}
free(buf);
CloseHandle(handle);
return 0;
}
Обратите внимание, что приведенное выше считывает один сектор за раз.Это полезно, если вы хотите исследовать каждый сектор отдельно, но это также медленно.
Метод ниже показывает чтение 100 секторов одновременно.Это быстрее, но немного сложнее, потому что оно включает сектора, которые не обязательно связаны между собой.Чтобы проверить, вы можете разбить buf
на различные сектора.
//read N number of dg.BytesPerSector for each pass
int N = 100;
int bufsize = dg.BytesPerSector * N;
char *buf = malloc(bufsize);
while(ReadFile(handle, buf, bufsize, &br, NULL))
{
if(!br)
break;
//print update
if((i % 1000) == 0)
printf("%.2f Mb\n", (double)i * bufsize / 1000000.0f);
i++;
//look for *.cpp files which have the string `#include` in them:
//buf includes N sectors
//look for `#include` in each sector and print the first 100 characters
for(int j = 0; j < N * dg.BytesPerSector; j += dg.BytesPerSector)
if(strstr(&buf[j], "#include"))
printf("%.100s ...\n", &buf[j]);
}
Примечание: вы используете
(LPCTSTR)strPath
, который предполагает, что программа скомпилирована с определением
UNICODE
(как следуетбыть) но вы используете строку ANSI в качестве аргумента, а затем используете приведение, чтобы скрыть ошибку.Просто используйте Unicode для всех функций WinAPI.Установите предупреждение компилятора на самый высокий уровень и не используйте приведение, если вы не абсолютно уверены.Также
ExpandEnvironmentStrings
для других строк, таких как
"%windir%"
.