|
3 | 3 | #include "util/stringUtils.h" |
4 | 4 |
|
5 | 5 | #include <windows.h> |
| 6 | +#include "util/windows/nt.h" |
6 | 7 | #include <ntstatus.h> |
7 | | -#include <winternl.h> |
8 | 8 |
|
9 | 9 | static void createSubfolders(const char* fileName) |
10 | 10 | { |
@@ -102,31 +102,48 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) |
102 | 102 | return ffAppendFDBuffer(handle, buffer); |
103 | 103 | } |
104 | 104 |
|
105 | | -HANDLE openat(HANDLE dfd, const char* fileName, bool directory) |
| 105 | +HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory) |
106 | 106 | { |
107 | | - NTSTATUS ret; |
108 | | - UNICODE_STRING fileNameW; |
109 | | - ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) { |
110 | | - .Length = (USHORT) strlen(fileName), |
111 | | - .Buffer = (PCHAR) fileName |
112 | | - }, TRUE); |
113 | | - if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE; |
114 | | - |
115 | | - FF_AUTO_CLOSE_FD HANDLE hFile; |
| 107 | + assert(fileNameLen <= 0x7FFF); |
| 108 | + |
| 109 | + HANDLE hFile; |
116 | 110 | IO_STATUS_BLOCK iosb = {}; |
117 | | - ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) { |
118 | | - .Length = sizeof(OBJECT_ATTRIBUTES), |
119 | | - .RootDirectory = dfd, |
120 | | - .ObjectName = &fileNameW, |
121 | | - }, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)); |
122 | | - RtlFreeUnicodeString(&fileNameW); |
123 | | - |
124 | | - if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED) |
| 111 | + if(!NT_SUCCESS(NtOpenFile(&hFile, |
| 112 | + (directory ? FILE_LIST_DIRECTORY | FILE_TRAVERSE : FILE_READ_DATA | FILE_READ_EA) | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) { |
| 113 | + .Length = sizeof(OBJECT_ATTRIBUTES), |
| 114 | + .RootDirectory = dfd, |
| 115 | + .ObjectName = &(UNICODE_STRING) { |
| 116 | + .Buffer = (PWSTR) fileName, |
| 117 | + .Length = fileNameLen * (USHORT) sizeof(wchar_t), |
| 118 | + .MaximumLength = (fileNameLen + 1) * (USHORT) sizeof(wchar_t), |
| 119 | + }, |
| 120 | + .Attributes = OBJ_CASE_INSENSITIVE, |
| 121 | + }, |
| 122 | + &iosb, |
| 123 | + FILE_SHARE_READ | (directory ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0), |
| 124 | + FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE) |
| 125 | + ))) |
125 | 126 | return INVALID_HANDLE_VALUE; |
126 | 127 |
|
127 | 128 | return hFile; |
128 | 129 | } |
129 | 130 |
|
| 131 | +HANDLE openat(HANDLE dfd, const char* fileName, bool directory) |
| 132 | +{ |
| 133 | + wchar_t fileNameW[MAX_PATH]; |
| 134 | + int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, fileNameW, ARRAY_SIZE(fileNameW)); |
| 135 | + if (len == 0) return INVALID_HANDLE_VALUE; |
| 136 | + // Implies `fileNameW[len] = L'\0';` and `len` includes the null terminator |
| 137 | + |
| 138 | + for (int i = 0; i < len - 1; ++i) |
| 139 | + { |
| 140 | + if (fileNameW[i] == L'/') |
| 141 | + fileNameW[i] = L'\\'; |
| 142 | + } |
| 143 | + |
| 144 | + return openatW(dfd, fileNameW, (uint16_t)(len - 1), directory); |
| 145 | +} |
| 146 | + |
130 | 147 | bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer) |
131 | 148 | { |
132 | 149 | HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false); |
|
0 commit comments