Вызов API CreateFile Win32 с OPEN_ALWAYS завершился неудачно - PullRequest
3 голосов
/ 05 июня 2009

У нас была строка кода

    if( !CreateFile( m_hFile, szFile, GENERIC_READ|GENERIC_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL ) )
    {
      DWORD dwErr = GetLastError();

      CString czInfo;
      czInfo.Format ("CMemoryMapFile::OpenAppend SetFilePointer call failed - GetLastError returned %d", dwErr);
      LOG(czInfo);

      return false;
    }

Этот код работал отлично в течение многих лет. Несколько недель назад у нас был клиент с проблемой. Оказывается, проблема может быть связана с этой строкой кода, где функция вернет дескриптор INVALID_HANDLE_VALUE, а GetLastError () вернет ERROR_FILE_NOT_FOUND (2).

Теперь, это очень смущает нас. OPEN_ALWAYS должен указывать файл, который будет создан, если он не существует. Итак, почему мы получаем ERROR_FILE_NOT_FOUND?

Больше путаницы: для этого клиента это происходило только на одной сетевой точке (мы использовали путь UNC). Другие пути UNC к другим машинам для этого клиента работали. Местные пути работали. Все остальные наши клиенты (более 10000 установок) не имеют никаких проблем.

Заказчик использовал XP в качестве клиентской ОС, а на серверах работала стандартная Windows Server 2003 (я думаю, версия для малого бизнеса). Мы не могли воспроизвести их ошибки в нашей тестовой лаборатории, используя те же ОС. Они могли повторить проблему с несколькими клиентами XP, но проблема была только на одном сервере (другие серверы Server 2003 не демонстрировали проблему).

Мы исправили проблему, вложив два вызова CreateFile, первый с OPEN_EXISTING, а второй с CREATE_ALWAYS, если OPEN_EXISTING не удалось. Таким образом, у нас нет срочной необходимости исправления.

Мой вопрос: есть ли у кого-нибудь идеи, почему этот вызов API потерпит неудачу именно таким образом? Мы озадачены.

Добавление:

Функция CreateFile, описанная выше, является оболочкой для функции Windows API. Вот код:

bool CMemoryMapFile::CreateFile( HANDLE & hFile, LPCSTR szFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes )
{
  hFile = ::CreateFile (szFile, dwDesiredAccess, dwShareMode, NULL, 
                        dwCreationDisposition, dwFlagsAndAttributes, NULL);
  return (hFile != INVALID_HANDLE_VALUE) 
}

Ответы [ 5 ]

3 голосов
/ 05 июня 2009

Во-первых, вы всегда должны проверять успешность API CreateFile () следующим образом:

if (CreateFile(...) == INVALID_HANDLE_VALUE)
{
   // handle the error
}

потому что CreateFile () не возвращает! = 0 в случае успеха, но ничего, кроме INVALID_HANDLE_VALUE (что равно -1).

Тогда CreateFile () может завершиться с ошибкой в ​​описанной вами ситуации, если либо каталог не существует, в котором вы хотите создать / открыть файл, либо он может не работать, если у пользователя есть права на открытие и запись файлов. в этом каталоге, но нет прав для создания новых файлов.

2 голосов
/ 21 января 2012

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

Мы считаем, что это выпуск акций. Мы решили проблему с помощью простого цикла повторов:

Если CreateFile с OPEN_ALWAYS не удается с ERROR_FILE_NOT_FOUND, мы просто спим в течение нескольких мс и пытаемся снова. Он всегда работает во второй раз (если это не удалось в первый раз).

2 голосов
/ 05 июня 2009

Может быть, каталог, в котором вы хотите создать файл, не существует?

Вы уверены, что исправили это с помощью двух вызовов CreateFile? Или ты просто не воспроизводил это?

1 голос
/ 05 июня 2009

Если CreateFile завершится неудачно, он вернет INVALID_HANDLE_VALUE, который не равен нулю (я думаю, что это отрицательное значение 1). Так что CreateFile может быть успешным и возвращать ноль в качестве дескриптора.

Безопасно проверять GetLastError () только после сбоя функции, но, похоже, вы проверяли последнюю ошибку, когда CreateFile завершился успешно (вернул ноль).

Согласно этой статье , некоторые функции устанавливают «последнюю ошибку», если им это удается:

0 голосов
/ 05 июня 2009

По моим предположениям, это может быть что-то, связанное с сервером, например сервер, неправильно реализующий поддержку этой операции файловой системы. Может быть, сервер Linux по сравнению с сервером Windows?

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

Вызов CreateFile должен выглядеть следующим образом:

m_hFile = CreateFile( szFile, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
if(m_hFile == INVALID_HANDLE_VALUE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...