in fixups/FileRedirectionFixup/FindFirstFileFixup.cpp [343:542]
BOOL __stdcall FindNextFileFixup(_In_ HANDLE findFile, _Out_ win32_find_data_t<CharT>* findFileData) noexcept try
{
auto guard = g_reentrancyGuard.enter();
if (!guard)
{
Log(L"FindNextFileFixup for file.");
return impl::FindNextFile(findFile, findFileData);
}
DWORD FindNextFileInstance = ++g_FileIntceptInstance;
Log(L"[%d]FindNextFileFixup.", FindNextFileInstance);
if (findFile == INVALID_HANDLE_VALUE)
{
::SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
auto data = reinterpret_cast<find_data*>(findFile);
#if !_DEBUG
Log(L"[%d]FindNextFileFixup is against redir =%ls", FindNextFileInstance, data->redirect_path.c_str());
Log(L"[%d]FindNextFileFixup is against pkgVfs =%ls", FindNextFileInstance, data->package_vfs_path.c_str());
Log(L"[%d]FindNextFileFixup is against request=%ls", FindNextFileInstance, data->requested_path.c_str());
#endif
auto redirectedFileExists = [&](auto filename)
{
if (data->redirect_path.empty())
{
Log(L"[%d]FindNextFile redirectedFileExists returns false.", FindNextFileInstance);
return false;
}
auto revertSize = data->redirect_path.length();
// NOTE: 'is_ansi' evaluation not inline due to the bug:
// https://developercommunity.visualstudio.com/content/problem/324366/illegal-indirection-error-when-the-evaluation-of-i.html
constexpr bool is_ansi = psf::is_ansi<std::decay_t<decltype(*filename)>>;
if constexpr (is_ansi)
{
data->redirect_path += widen(filename);
}
else
{
data->redirect_path += filename;
}
auto result = impl::PathExists(data->redirect_path.c_str());
data->redirect_path.resize(revertSize);
Log(L"[%d]FindNextFile redirectedFileExists returns %ls", FindNextFileInstance, data->redirect_path.c_str());
return result;
};
auto vfspathFileExists = [&](auto filename)
{
if (data->package_vfs_path.empty())
{
Log(L"[%d]FindNextFile vfspathFileExists returns false.", FindNextFileInstance);
return false;
}
auto revertSize = data->package_vfs_path.length();
// NOTE: 'is_ansi' evaluation not inline due to the bug:
// https://developercommunity.visualstudio.com/content/problem/324366/illegal-indirection-error-when-the-evaluation-of-i.html
constexpr bool is_ansi = psf::is_ansi<std::decay_t<decltype(*filename)>>;
if constexpr (is_ansi)
{
data->package_vfs_path += widen(filename);
}
else
{
data->package_vfs_path += filename;
}
auto result = impl::PathExists(data->package_vfs_path.c_str());
data->package_vfs_path.resize(revertSize);
Log(L"[%d]FindNextFile vfspathFileExists returns %ls", FindNextFileInstance, data->package_vfs_path.c_str());
return result;
};
if (!data->redirect_path.empty())
{
if (data->find_handles[0])
{
Log(L"[%d]FindNextFile[0] to be checked.", FindNextFileInstance);
if (impl::FindNextFile(data->find_handles[0].get(), findFileData))
{
Log(L"[%d]FindNextFile[0] returns TRUE: %ls", FindNextFileInstance, data->cached_data.cFileName);
return TRUE;
}
else if (::GetLastError() == ERROR_NO_MORE_FILES)
{
Log(L"[%d]FindNextFile[0] had FALSE with ERROR_NO_MORE_FILES.", FindNextFileInstance);
data->find_handles[0].reset();
if (data->package_vfs_path.empty() || !data->find_handles[1])
{
Log(L"[%d]FindNextFile[1] not in use.", FindNextFileInstance);
if (data->requested_path.empty() || !data->find_handles[2])
{
Log(L"[%d]FindNextFile[2] not in use, so return ERROR_NO_MORE_FILES.", FindNextFileInstance);
// NOTE: Last error scribbled over by closing find_handles[0]
::SetLastError(ERROR_NO_MORE_FILES);
return FALSE;
}
// else check[1]
}
if (!redirectedFileExists(data->cached_data.cFileName))
{
if (copy_find_data(data->cached_data, *findFileData))
{
Log(L"[%d]FindNextFile[0] returns FALSE with last error set by caller", FindNextFileInstance);
// NOTE: Last error set by caller
return FALSE;
}
LogString(FindNextFileInstance, L"FindNextFile[0] returns TRUE with ERROR_SUCCESS and file %ls", data->cached_data.cFileName);
::SetLastError(ERROR_SUCCESS);
return TRUE;
}
}
else
{
// Error due to something other than reaching the end
Log(L"[%d]FindNextFile[0] returns FALSE", FindNextFileInstance);
return FALSE;
}
}
}
if (!data->package_vfs_path.empty())
{
while (data->find_handles[1])
{
if (impl::FindNextFile(data->find_handles[1].get(), findFileData))
{
// Skip the file if it exists in the redirected path
if (!redirectedFileExists(findFileData->cFileName))
{
LogString(FindNextFileInstance, L"FindNextFile[1] returns TRUE with ERROR_SUCCESS and %ls", findFileData->cFileName);
::SetLastError(ERROR_SUCCESS);
return TRUE;
}
// Otherwise, skip this file and check the next one
}
else if (::GetLastError() == ERROR_NO_MORE_FILES)
{
Log(L"[%d]FindNextFile[1] returns FALSE with ERROR_NO_MORE_FILES_FOUND.", FindNextFileInstance);
data->find_handles[1].reset();
// now check [2]
}
else
{
Log(L"[%d]FindNextFile[1] returns FALSE", FindNextFileInstance);
// Error due to something other than reaching the end
return FALSE;
}
}
}
if (!data->requested_path.empty())
{
while (data->find_handles[2])
{
if (impl::FindNextFile(data->find_handles[2].get(), findFileData))
{
// Skip the file if it exists in the redirected path
if (!redirectedFileExists(findFileData->cFileName) &&
!vfspathFileExists(findFileData->cFileName))
{
LogString(FindNextFileInstance, L"FindNextFile[2] returns TRUE with ERROR_SUCCESS and %ls", findFileData->cFileName);
::SetLastError(ERROR_SUCCESS);
return TRUE;
}
// Otherwise, skip this file and check the next one
}
else if (::GetLastError() == ERROR_NO_MORE_FILES)
{
Log(L"[%d]FindNextFile[2] returns FALSE with ERROR_NO_MORE_FILES_FOUND.", FindNextFileInstance);
data->find_handles[2].reset();
::SetLastError(ERROR_NO_MORE_FILES);
return FALSE;
}
else
{
Log(L"[%d]FindNextFile[2] returns FALSE", FindNextFileInstance);
// Error due to something other than reaching the end
return FALSE;
}
}
}
// We ran out of data either on a previous call, or by ignoring files that have been redirected
::SetLastError(ERROR_NO_MORE_FILES);
return FALSE;
}