nova-nix-0.8.0.0: cbits/nn_winfs.c
#include "nn_winfs.h"
#ifdef _WIN32
#include <windows.h>
#include <winternl.h>
/* FileCaseSensitiveInformation and its flag are absent from older SDK and
* MinGW headers; both values are fixed ABI, defined locally. */
enum { NN_FILE_CASE_SENSITIVE_INFORMATION = 71 };
#ifndef FILE_CS_FLAG_CASE_SENSITIVE_DIR
#define FILE_CS_FLAG_CASE_SENSITIVE_DIR 0x00000001
#endif
typedef struct nn_file_case_sensitive_info {
ULONG flags;
} nn_file_case_sensitive_info;
typedef NTSTATUS(NTAPI *nn_nt_set_information_file)(HANDLE, PIO_STATUS_BLOCK,
PVOID, ULONG, ULONG);
int nn_dir_set_case_sensitive(const wchar_t *path) {
HMODULE ntdll;
nn_nt_set_information_file set_information_file;
HANDLE dir;
nn_file_case_sensitive_info info;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
/* NtSetInformationFile is the documented route to the per-directory
* flag (fsutil and WSL use it); resolved dynamically because it lives
* in ntdll, which is always loaded but not in the link line. */
ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll == NULL) {
return 0;
}
set_information_file =
(nn_nt_set_information_file)GetProcAddress(ntdll, "NtSetInformationFile");
if (set_information_file == NULL) {
return 0;
}
dir = CreateFileW(path, FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (dir == INVALID_HANDLE_VALUE) {
return 0;
}
info.flags = FILE_CS_FLAG_CASE_SENSITIVE_DIR;
status = set_information_file(dir, &iosb, &info, sizeof info,
NN_FILE_CASE_SENSITIVE_INFORMATION);
CloseHandle(dir);
return status >= 0 ? 1 : 0;
}
#else /* !_WIN32 */
/* Per-directory case sensitivity is an NTFS feature; APFS decides at
* volume creation and Linux filesystems are case-sensitive by nature. */
int nn_dir_set_case_sensitive(const wchar_t *path) {
(void)path;
return 0;
}
#endif