Информация об изменениях

Сообщение Re[5]: CreateFile - AccessDenied когда существует папка от 12.05.2020 16:13

Изменено 12.05.2020 16:18 Alexander G

Re[5]: CreateFile - AccessDenied когда существует папка
Здравствуйте, MuPoB, Вы писали:

MPB>Проблема в том, что между вызовом функции CreateFile и вызовом любой функции, анализирующей ошибку (GetFilAttrbutes, FindFirstFile и т.п.) может произойти всё что угодно, и то, что вернёт функция анализа, будет уже неадекватно. Или если сначала проверить, существует такая папка или нет, а потом создать файл — опять перед созданием состояние ФС может поменяться


MPB>Нужно чтобы сразу ошибка была говорящей, а не просто AccessDenied. Создание рандомного файла и его переименование сразу позволяет понять, что директория с таким именем уже существует


Есть решение. После неуспешного CreateFile получить последний NTSTATUS из TEB.

HANDLE h = ::CreateFile(path, 0, 7, 0, OPEN_ALWAYS, 0, 0);
if (h == INVALID_HANDLE_VALUE)
{
   NTSTATUS status = GetLastNtStatus();
   if (status == STATUS_FILE_IS_A_DIRECTORY) { ... }
}


Разве что заминка будет с GetLastNtStatus. Документриованный путь мне неизвестен.
Недокументировано как-то так:
inline NTSTATUS GetLastNtStatus()
{
#if defined(_M_X64)
    return __readgsdword(0x1250);
#elif defined (_M_IX86)
    return __readfsdword(0xBF4);
#else
#error Implement this for ARM or whatever architecture you have
#endif 
}

Магические константы подсмотрел в Википедии.
Re[5]: CreateFile - AccessDenied когда существует папка
Здравствуйте, MuPoB, Вы писали:

MPB>Проблема в том, что между вызовом функции CreateFile и вызовом любой функции, анализирующей ошибку (GetFilAttrbutes, FindFirstFile и т.п.) может произойти всё что угодно, и то, что вернёт функция анализа, будет уже неадекватно. Или если сначала проверить, существует такая папка или нет, а потом создать файл — опять перед созданием состояние ФС может поменяться


MPB>Нужно чтобы сразу ошибка была говорящей, а не просто AccessDenied. Создание рандомного файла и его переименование сразу позволяет понять, что директория с таким именем уже существует


Есть решение. После неуспешного CreateFile получить последний NTSTATUS из TEB.

HANDLE h = ::CreateFile(path, 0, 7, 0, OPEN_ALWAYS, 0, 0);
if (h == INVALID_HANDLE_VALUE)
{
   NTSTATUS status = GetLastNtStatus();
   if (status == STATUS_FILE_IS_A_DIRECTORY) { ... }
}


Разве что заминка будет с GetLastNtStatus. Документриованный путь мне неизвестен.
Недокументировано как-то так:
inline NTSTATUS GetLastNtStatus()
{
#if defined(_M_X64)
    return __readgsdword(0x1250);
#elif defined (_M_IX86)
    return __readfsdword(0xBF4);
#else
#error Implement this for ARM or whatever architecture you have
#endif 
}

Магические константы подсмотрел в Википедии.

Более чистым, возможно, будет прямой вызов NtCreateFile / NtOpenFile.
Это более легально с точки зрения документрованности, но потребует большего изменения вызывающего кода.