2015-07-29 3 views
0

Я пытаюсь работать с функцией ReadFile. Вот мой код:Функция ReadFile возвращает ERROR_INVALID_PARAMETER

#define BUFFERSIZE 5 

int main(int argc, char* argv[]) 
{ 
    OVERLAPPED overlapIn = {}; 
    HANDLE tHandle; 
    char buf[BUFFERSIZE] = {}; 
    DWORD lpNumberOfBytesRead; 

    tHandle = CreateFile(
     L"\\\\.\\D:", 
     GENERIC_READ, 
     FILE_SHARE_READ, 
     NULL, 
     OPEN_EXISTING, 
     FILE_ATTRIBUTE_NORMAL, 
     NULL); 

    if (tHandle == INVALID_HANDLE_VALUE) 
    { 
     DWORD error = GetLastError(); 
     assert(0); 
    } 

    if (ReadFile(tHandle, &buf, BUFFERSIZE - 1, &lpNumberOfBytesRead, NULL) == 0) 
    { 
     int error = GetLastError(); 
     printf("Terminal failure: Unable to read from disk.\n GetLastError=%d\n", error); 
     CloseHandle(tHandle); 
     return 1; 
    } 

Функция GetLastError возвращает код 87, который ERROR_INVALID_PARAMETER.

Понятно, что один из параметров неверен, но я понятия не имею, какой из них, поскольку я пытался делать все, как это написано в документации.

+0

Я полагаю, вы получите ошибку после того, как 1-й 'if'. Вы не можете читать из дисковода просто так. –

+0

Нет, я не говорю о функции ReadFile. И да, я могу читать с такого диска. –

+4

Ошибка BUFFERSIZE-1. Вы не можете рассчитывать на кеш файловой системы, когда читаете необработанные данные с диска. Поддерживаемое выравнивание зависит от файловой системы, 4096 - хороший круглый номер. Вы также должны указать FILE_SHARE_WRITE в вызове CreateFile(). И при создании CreateFile() вам придется делать гораздо больше шума, assert() не режет. –

ответ

3

Это описано в documentation for CreateFile:

Объем ручки можно открыть некешированной по усмотрению конкретной файловой системы, даже если некешированной параметр не указан в CreateFile. Вы должны предположить, что все файловые системы Microsoft открывают дескрипторы томов как незашифрованные.

MSDN article on File Buffering описывает требования к некешированной ручками:

размеров доступа файлов, в том числе дополнительного смещения файла в OVERLAPPED структуре, если указано, должно быть в течение нескольких байт, который является целым числом, кратным от объема объемного сектора. Например, если размер сектора составляет 512 байт, приложение может запрашивать чтение и запись 512, 1024, 1,536 или 2048 байт, но не 335, 981 или 7,171 байт.

Адреса буфера доступа к файлам для операций чтения и записи должны быть выровнены по физическому сектору, что означает выравнивание по адресам в памяти, которые являются целыми кратными размеру физического сектора тома. В зависимости от диска это требование может не выполняться.

Строгий код должен проверять размер сектора для рассматриваемой файловой системы, а затем использовать this approach для выделения памяти. Однако, по моему опыту, размер сектора всегда был меньше или равен размерности распределения, поэтому вы можете избавиться от использования только VirtualAlloc() для выделения блока памяти.

0

размер буфера должен быть совмещен с ГНБ размером сектора

WIN32_FIND_DATA atr = {0}; 
DWORD BYTES_PER_SECTOR; 
char path[MAX_PATH]; 

/* get path length current dir */ 
const size_t len = GetCurrentDirectory(0, 0); 

/* set path to path char array */ 
GetCurrentDirectory(len, path); 

/* windows function to get disk details */ 
GetDiskFreeSpace(NULL, NULL, &BYTES_PER_SECTOR, NULL, NULL); 

/* find first file in dir */ 
find = FindFirstFile(path, &atr); 

for(;find != INVALID_HANDLE_VALUE;){ 

/* get the file size */ 
DWORD filesize = atr.nFileSizeLow; 
    if(atr.nFileSizeHigh > 0){ 
        filesize = atr.nFileSizeHigh; 
        filesize = (filesize << 31); 
        filesize = atr.nFileSizeLow; 
        } 
/* sector size aligned file size */ 
size_t buffer_size = ((BYTES_PER_SECTOR + ((filesize + BYTES_PER_SECTOR)-1)) & ~(BYTES_PER_SECTOR -1)); 

/* create buffer */ 
DWORD buffer[buffer_size];              

/* create a new file or open an existing file */ 
handle = CreateFile(&path[0], GENERIC_READ | GENERIC_WRITE, 0 , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, NULL))!=INVALID_HANDLE_VALUE) 

/* read the file in to buffer */ 
ReadFile(handle, (void*)&buffer, buffer_size, &bytesread, NULL) 

if(FindNextFile(find, &atr)==0){ printf("last file processed, leaving\n");break;}; 
} 
CloseHandle(file); 
FindClose(find); 
Смежные вопросы