| 348 | } |
| 349 | |
| 350 | static bool diag_write_file(const char *base_name, const char *data, size_t length, bool append) { |
| 351 | char path[CBM_PATH_MAX]; |
| 352 | if (!diag_full_path(base_name, path, sizeof(path))) { |
| 353 | return false; |
| 354 | } |
| 355 | wchar_t *wide_path = cbm_path_to_wide(path); |
| 356 | DWORD access = append ? FILE_APPEND_DATA : GENERIC_WRITE; |
| 357 | HANDLE handle = wide_path |
| 358 | ? CreateFileW(wide_path, access, FILE_SHARE_READ, NULL, CREATE_NEW, |
| 359 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL) |
| 360 | : INVALID_HANDLE_VALUE; |
| 361 | DWORD creation_error = handle == INVALID_HANDLE_VALUE ? GetLastError() : ERROR_SUCCESS; |
| 362 | if (handle == INVALID_HANDLE_VALUE && wide_path && |
| 363 | (creation_error == ERROR_FILE_EXISTS || creation_error == ERROR_ALREADY_EXISTS)) { |
| 364 | handle = CreateFileW(wide_path, access, FILE_SHARE_READ, NULL, |
| 365 | append ? OPEN_EXISTING : TRUNCATE_EXISTING, |
| 366 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| 367 | } |
| 368 | free(wide_path); |
| 369 | if (!diag_win_handle_valid(handle)) { |
| 370 | if (handle != INVALID_HANDLE_VALUE) { |
| 371 | (void)CloseHandle(handle); |
| 372 | } |
| 373 | return false; |
| 374 | } |
| 375 | bool ok = true; |
| 376 | size_t offset = 0; |
| 377 | while (offset < length) { |
| 378 | DWORD chunk = length - offset > MAXDWORD ? MAXDWORD : (DWORD)(length - offset); |
| 379 | DWORD bytes_written = 0; |
| 380 | if (!WriteFile(handle, data + offset, chunk, &bytes_written, NULL) || bytes_written == 0) { |
| 381 | ok = false; |
| 382 | break; |
| 383 | } |
| 384 | offset += bytes_written; |
| 385 | } |
| 386 | return CloseHandle(handle) != 0 && ok; |
| 387 | } |
| 388 | |
| 389 | static bool diag_native_rename(const char *source_name, const char *destination_name) { |
| 390 | char source[CBM_PATH_MAX]; |
no test coverage detected