| 28 | } |
| 29 | |
| 30 | void HddCreate::WriteImage(const std::string& hddPath, u64 fileBytes, u64 zeroSizeBytes) |
| 31 | { |
| 32 | constexpr int buffsize = 4 * 1024; |
| 33 | const u8 buff[buffsize] = {0}; // 4kb. |
| 34 | |
| 35 | if (FileSystem::FileExists(hddPath.c_str())) |
| 36 | { |
| 37 | errored.store(true); |
| 38 | SetError(); |
| 39 | return; |
| 40 | } |
| 41 | |
| 42 | auto newImage = FileSystem::OpenManagedCFile(hddPath.c_str(), "wb"); |
| 43 | if (!newImage) |
| 44 | { |
| 45 | errored.store(true); |
| 46 | SetError(); |
| 47 | return; |
| 48 | } |
| 49 | |
| 50 | bool sparseSupported = false; |
| 51 | #ifdef _WIN32 |
| 52 | // Handle owned by CFile. |
| 53 | HANDLE nativeFile = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(newImage.get()))); |
| 54 | |
| 55 | if (nativeFile == INVALID_HANDLE_VALUE) |
| 56 | { |
| 57 | Console.Error("DEV9: HddCreate: failed to get handle"); |
| 58 | newImage.reset(); |
| 59 | FileSystem::DeleteFilePath(hddPath.c_str()); |
| 60 | errored.store(true); |
| 61 | SetError(); |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | // Check if we support sparse files. |
| 66 | DWORD dwFlags; |
| 67 | if (GetVolumeInformationByHandleW(nativeFile, nullptr, 0, nullptr, nullptr, &dwFlags, nullptr, 0) == FALSE) |
| 68 | { |
| 69 | Console.Error("DEV9: HddCreate: failed to check sparse"); |
| 70 | newImage.reset(); |
| 71 | FileSystem::DeleteFilePath(hddPath.c_str()); |
| 72 | errored.store(true); |
| 73 | SetError(); |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | if (dwFlags & FILE_SUPPORTS_SPARSE_FILES) |
| 78 | { |
| 79 | // Sparse files supported. |
| 80 | FILE_SET_SPARSE_BUFFER sparseSetting; |
| 81 | sparseSetting.SetSparse = true; |
| 82 | FILE_ZERO_DATA_INFORMATION sparseRange; |
| 83 | sparseRange.FileOffset.QuadPart = 0; |
| 84 | sparseRange.BeyondFinalZero.QuadPart = fileBytes; |
| 85 | DWORD dwTemp; |
| 86 | |
| 87 | if ((DeviceIoControl(nativeFile, FSCTL_SET_SPARSE, &sparseSetting, sizeof(sparseSetting), nullptr, 0, &dwTemp, nullptr) == FALSE) || |