2013-04-16 2 views
6

Я столкнулся с этой ситуацией с помощью функции MapViewOfFile от WinAPI. Поиск в Интернете не выявил никаких явных исправлений, поэтому я расскажу о своей проблеме и решении.Почему MapViewOfFile не работает с ERROR_ACCESS_DENIED?

Рассмотрим следующий фрагмент кода:

const char *name = "Global\\Object_Name"; 
unsigned long size = get_object_size(); 

HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, 
            NULL, 
            PAGE_READWRITE, 
            0, 
            size, 
            name); 

if (!handle || handle == INVALID_HANDLE_VALUE) 
    exit(GetLastError()); 

bool created = GetLastError() == 0; 

void *block = MapViewOfFile(handle, 
          FILE_MAP_ALL_ACCESS, 
          0, 
          0, 
          size); 

if (block == NULL) 
    exit(GetLastError()); 

В одном конкретном случае, CreateFileMapping успешно возвращающегося ручку. GetLastError возвращался ERROR_ALREADY_EXISTS, поэтому created == false. Теперь звонок в MapViewOfFile, используя тот же размер, который я передал CreateFileMapping, возвращает NULL и GetLastError возвращает 0x05: ERROR_ACCESS_DENIED. Процесс выполнялся с правами администратора.

В документации MSDN не упоминается какая-либо причина возникновения этой ситуации. Так почему же CreateFileMapping преуспевает, но MapViewOfFile терпят неудачу?

ответ

7

Уверен, что существует много причин, почему ERROR_ACCESS_DENIED может возникнуть в результате звонка по телефону MapViewOfFile. В моей конкретной ситуации это было связано с аргументом size.

Подсказка в том, что created == false. Он показывает, что объект "Global\\Object_Name" уже создан. По какой-то причине создающий вызов инициализировал раздел с меньшим размером. Для того, что похоже на надзор, второй звонок на CreateFileMapping с радостью даст вам ручку уже существующему объекту, даже если вы попросите более крупное сопоставление.

Теперь вызов MapViewOfFile невозможен, поскольку запрашивает представление, которое больше, чем фактический раздел.

Итак, если вы находитесь в аналогичной ситуации, когда второй вызов MapViewOfFile сбой, проверьте размер, на который вы пытаетесь выполнить сопоставление.

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

6

После многого страдания я наконец нашел причину этой ошибки в своем приложении, в случае, если кто-то другой борется с тем же, проблема связана не с методом MapViewOfFile, а с CreateFileMapping, размером с createFileMapping должен быть размером файла, а не размером элемента для чтения, если вы не знаете размер, то он должен быть 0, это не относится к MapViewOfFile, поскольку значение, передаваемое как размер, - это длина блок, который вы хотите прочитать/записать.

Ваш код рабочий будет выглядеть следующим образом:

const char *name = "Global\\Object_Name"; 
unsigned long size = get_object_size(); 

HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, 
            NULL, 
            PAGE_READWRITE, 
            0, 
            0, 
            name); 

if (!handle || handle == INVALID_HANDLE_VALUE) 
    exit(GetLastError()); 

bool created = GetLastError() == 0; 

void *block = MapViewOfFile(handle, 
          FILE_MAP_ALL_ACCESS, 
          0, 
          0, 
          size); 

if (block == NULL) 
    exit(GetLastError()); 

Справедливый положить это здесь, чтобы документ, что я нашел, к сожалению, трудно найти эту ошибку, когда вы не знаете, что вызывает его. Надеюсь, это сэкономит пару часов кому-то другому.