MCPcopy Create free account
hub / github.com/deathkiller/jazz2-native / DeleteDirectoryInternal

Function DeleteDirectoryInternal

Sources/Shared/IO/FileSystem.cpp:188–944  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

186
187#if defined(DEATH_TARGET_WINDOWS)
188 static bool DeleteDirectoryInternal(ArrayView<wchar_t> path, bool recursive, std::int32_t depth)
189 {
190 if (recursive) {
191 if (path.size() + 3 <= FileSystem::MaxPathLength) {
192 if DEATH_UNLIKELY(NtQueryDirectoryFile == nullptr) {
193 if (HMODULE hNtdll = ::GetModuleHandle(L"ntdll.dll")) {
194 NtQueryDirectoryFile = (_NtQueryDirectoryFile)::GetProcAddress(hNtdll, "NtQueryDirectoryFile");
195 DEATH_ASSERT(NtQueryDirectoryFile != nullptr, "NtQueryDirectoryFile() cannot be found", false);
196 }
197 }
198
199 Array<wchar_t> bufferExtended{NoInit, FileSystem::MaxPathLength};
200 std::memcpy(bufferExtended.data(), path.data(), path.size() * sizeof(wchar_t));
201
202 std::size_t bufferOffset = path.size();
203 if (bufferExtended[bufferOffset - 1] == L'/' || path[bufferOffset - 1] == L'\\') {
204 bufferExtended[bufferOffset - 1] = L'\\';
205 } else {
206 bufferExtended[bufferOffset] = L'\\';
207 bufferOffset++;
208 }
209
210 // Remove trailing backslash and open directory
211 Array<wchar_t> dirPath{NoInit, bufferOffset};
212 std::memcpy(dirPath.data(), bufferExtended.data(), (bufferOffset - 1) * sizeof(wchar_t));
213 dirPath[bufferOffset - 1] = L'\0';
214
215# if defined(DEATH_TARGET_WINDOWS_RT)
216 HANDLE hDirectory = ::CreateFileFromAppW(dirPath, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
217 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
218# else
219 HANDLE hDirectory = ::CreateFileW(dirPath, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
220 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
221# endif
222
223 if (hDirectory != NULL && hDirectory != INVALID_HANDLE_VALUE) {
224 constexpr ULONG BufferSize = 64 * 1024;
225 std::uint8_t* buffer = new std::uint8_t[BufferSize];
226
227 while (true) {
228 IO_STATUS_BLOCK ioStatus;
229 NTSTATUS status = NtQueryDirectoryFile(hDirectory, nullptr, nullptr, nullptr, &ioStatus,
230 buffer, BufferSize, FileFullDirectoryInformation, FALSE, nullptr, FALSE);
231
232 if (status < 0) {
233 break;
234 }
235
236 FILE_FULL_DIR_INFORMATION* entry = reinterpret_cast<FILE_FULL_DIR_INFORMATION*>(buffer);
237
238 while (true) {
239 ULONG fileNameLengthInChars = entry->FileNameLength / sizeof(wchar_t);
240
241 // Skip "." and ".."
242 if (!((fileNameLengthInChars == 1 && entry->FileName[0] == L'.') ||
243 (fileNameLengthInChars == 2 && entry->FileName[0] == L'.' && entry->FileName[1] == L'.'))) {
244
245 std::memcpy(&bufferExtended[bufferOffset], entry->FileName, entry->FileNameLength);

Callers 1

Calls 6

DEATH_ASSERTFunction · 0.85
callbackClass · 0.85
DEATH_UNLIKELYFunction · 0.70
sizeMethod · 0.45
dataMethod · 0.45
prefixMethod · 0.45

Tested by

no test coverage detected