"NUL" 上的 UWP CreateFile2 ERROR_ACCESS_DENIED

UWP CreateFile2 ERROR_ACCESS_DENIED on "NUL"

我正在尝试将一些旧东西从 WP8 迁移到带有 C++ 扩展的通用 Windows 平台。当我尝试使用此代码时,问题就开始了

HANDLE h = CreateFile(L"NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);

h 为 -1,最后错误为 5 (ERROR_ACCESS_DENIED) CreateFile 以这种方式重新定义:

HANDLE CreateFile(
_In_ LPCWSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
)
{
    CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
    extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
    extendedParameters.dwFileAttributes = dwFlagsAndAttributes & 0x0003FFF7;
    extendedParameters.dwFileFlags = dwFlagsAndAttributes & 0xFF3C0000;
    extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
    extendedParameters.lpSecurityAttributes = lpSecurityAttributes;
    extendedParameters.hTemplateFile = hTemplateFile;
    return CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, 
dwCreationDisposition, &extendedParameters);
}

此代码适用于 Windows Phone 8,但不适用于 Windows 10。所以,问题是 - 我做错了什么。

这里有两个问题。首先,如 CreateFile2 function:

中所述

When called from a Windows Store app, CreateFile2 is simplified. You can open only files or directories inside the ApplicationData.LocalFolder or Package.InstalledLocation directories. You can't open named pipes or mailslots or create encrypted files (FILE_ATTRIBUTE_ENCRYPTED).

因此,在 UWP 中使用 CreateFile2 函数时,我们需要提供 ApplicationData.LocalFolder or Package.InstalledLocation 目录内的路径作为 lpFileName 参数,而不仅仅是文件名,例如:

Windows::Storage::StorageFolder^ localFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
String^ path = localFolder->Path;
path += L"\Test.txt";

CREATEFILE2_EXTENDED_PARAMETERS extendedParams;
extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN;
extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extendedParams.lpSecurityAttributes = NULL;
extendedParams.hTemplateFile = NULL;

HANDLE fileHandle = CreateFile2(path->Data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, &extendedParams);

第二个是我们不能使用NUL作为文件名。见 Naming Files, Paths, and Namespaces:

Do not use the following reserved names for the name of a file:

CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
Also avoid these names followed immediately by an extension; for example, NUL.txt is not recommended. For more information, see Namespaces.

因此,您可以像下面这样更改代码,这样应该不会出错。

Windows::Storage::StorageFolder^ localFolder = Windows::Storage::ApplicationData::Current->LocalFolder;
String^ path = localFolder->Path;
path += L"\Test.txt"; //Replace with the name you want to use.

HANDLE h = CreateFile(path->Data(), 0, 0, NULL, OPEN_ALWAYS, 0, NULL);