|
16 | 16 | #include <sstream> |
17 | 17 | #include <algorithm> |
18 | 18 | #include <memory> |
| 19 | +#include <locale> |
| 20 | +#include <codecvt> |
19 | 21 |
|
20 | 22 | #ifdef _WIN32 |
21 | 23 | #include <io.h> |
22 | 24 | #include <direct.h> |
23 | 25 | #include <windows.h> |
24 | 26 | #include <winbase.h> /* needed for memory mapping of file functions */ |
| 27 | + |
| 28 | +struct dir_handle_deleter { |
| 29 | + typedef HANDLE pointer; |
| 30 | + |
| 31 | + void operator()(HANDLE dirp) { |
| 32 | + if (dirp != INVALID_HANDLE_VALUE) { |
| 33 | + FindClose(dirp); |
| 34 | + } |
| 35 | + } |
| 36 | +}; |
| 37 | +typedef std::unique_ptr<HANDLE, dir_handle_deleter> unique_dir_handle_ptr; |
25 | 38 | #endif |
26 | 39 |
|
27 | 40 | #ifdef SCP_UNIX |
@@ -566,6 +579,62 @@ void cf_search_root_path(int root_index) |
566 | 579 | } |
567 | 580 |
|
568 | 581 | #if defined _WIN32 |
| 582 | + { |
| 583 | + // Check if the case matches the case as specified in Pathtypes |
| 584 | + // Since Windows paths are case insensitive this wouldn't cause issues here but other |
| 585 | + // platforms would fail to find data paths in this case so we show a nice error if we detect that here |
| 586 | + |
| 587 | + // Ignore the root since the case of that is allowed to differ (it's handled in the mod handling) |
| 588 | + if (i != CF_TYPE_ROOT) { |
| 589 | + // We use FindFirstFileNameW for this, it should hopefully work... |
| 590 | + // First, convert our path from ASCII/UTF-8 to wchar_t |
| 591 | + std::string search_string = search_path; |
| 592 | + // Remove any trailing directory separators |
| 593 | + if (search_string[search_string.size() - 1] == '\\') { |
| 594 | + search_string = search_string.substr(0, search_string.size() - 1); |
| 595 | + } |
| 596 | + |
| 597 | + char parent_name[MAX_PATH]; |
| 598 | + memset(parent_name, 0, sizeof(parent_name)); |
| 599 | + strcpy_s(parent_name, search_string.c_str()); |
| 600 | + |
| 601 | + CHAR file_name[MAX_PATH]; |
| 602 | + memset(file_name, 0, sizeof(file_name)); |
| 603 | + strcpy_s(file_name, search_string.c_str()); |
| 604 | + |
| 605 | + PathStripPathA(file_name); |
| 606 | + if (PathRemoveFileSpecA(parent_name)) { |
| 607 | + strcat_s(parent_name, "\\*"); |
| 608 | + |
| 609 | + WIN32_FIND_DATAA find_data; |
| 610 | + auto handle = unique_dir_handle_ptr(FindFirstFileA(parent_name, &find_data)); |
| 611 | + if (handle.get() != INVALID_HANDLE_VALUE) { |
| 612 | + do { |
| 613 | + if (stricmp(find_data.cFileName, file_name)) { |
| 614 | + // Not the same name, not even if we check case-insensitive |
| 615 | + continue; |
| 616 | + } |
| 617 | + |
| 618 | + // Same name, might have case differences |
| 619 | + if (!strcmp(find_data.cFileName, file_name)) { |
| 620 | + // Case matches, everything is alright. |
| 621 | + continue; |
| 622 | + } |
| 623 | + |
| 624 | + // We need to do some formatting on the parent_name in order to show a nice error message |
| 625 | + SCP_string parent_name_str = parent_name; |
| 626 | + parent_name_str = parent_name_str.substr(0, parent_name_str.size() - 1); // Remove trailing * |
| 627 | + parent_name_str += find_data.cFileName; |
| 628 | + |
| 629 | + // If we are still here then the case didn't match which means that we have to show the error message |
| 630 | + Error(LOCATION, "Data directory '%s' for path type '%s' does not match the required case! " |
| 631 | + "All data directories must exactly match the case specified by the engine or your mod " |
| 632 | + "will not work on other platforms.", parent_name_str.c_str(), Pathtypes[i].path); |
| 633 | + } while (FindNextFileA(handle.get(), &find_data) != 0); |
| 634 | + } |
| 635 | + } |
| 636 | + } |
| 637 | + } |
569 | 638 | strcat_s( search_path, "*.*" ); |
570 | 639 |
|
571 | 640 | intptr_t find_handle; |
@@ -667,7 +736,7 @@ void cf_search_root_path(int root_index) |
667 | 736 | if (!fnmatch ("*.*", dir->d_name, 0)) |
668 | 737 | { |
669 | 738 | SCP_string fn; |
670 | | - sprintf(fn, "%s/%s", search_path, dir->d_name); |
| 739 | + sprintf(fn, "%s%s", search_path, dir->d_name); |
671 | 740 |
|
672 | 741 | struct stat buf; |
673 | 742 | if (stat(fn.c_str(), &buf) == -1) { |
|
0 commit comments