#endif
#include "wimlib/win32_common.h"
-#include "wimlib/win32.h"
+
#include "wimlib/assert.h"
+#include "wimlib/blob_table.h"
#include "wimlib/error.h"
-#include "wimlib/lookup_table.h"
#include "wimlib/util.h"
#include "wimlib/wimboot.h"
+#include "wimlib/win32.h"
#include "wimlib/wof.h"
static HANDLE
h = open_file(vol_name, GENERIC_READ);
if (h == INVALID_HANDLE_VALUE) {
- ERROR("\"%ls\": Can't open volume device (err=%"PRIu32")",
- vol_name, (u32)GetLastError());
+ win32_error(GetLastError(), L"\"%ls\": Can't open volume device",
+ vol_name);
ret = WIMLIB_ERR_OPEN;
goto out;
}
if (!query_device(h, IOCTL_DISK_GET_PARTITION_INFO_EX,
part_info, sizeof(PARTITION_INFORMATION_EX)))
{
- ERROR("\"%ls\": Can't get partition info (err=%"PRIu32")",
- vol_name, (u32)GetLastError());
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't get partition info", vol_name);
ret = WIMLIB_ERR_READ;
goto out;
}
extents, extents_size))
break;
if (GetLastError() != ERROR_MORE_DATA) {
- ERROR("\"%ls\": Can't get volume extent info (err="PRIu32")",
- vol_name, (u32)GetLastError());
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't get volume extent info",
+ vol_name);
ret = WIMLIB_ERR_READ;
goto out;
}
h = open_file(disk_name, GENERIC_READ);
if (h == INVALID_HANDLE_VALUE) {
- ERROR("\"%ls\": Can't open disk device (err=%"PRIu32")",
- disk_name, (u32)GetLastError());
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't open disk device", disk_name);
ret = WIMLIB_ERR_OPEN;
goto out;
}
drive_info, drive_info_size))
break;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- ERROR("\"%ls\": Can't get disk info (err=%"PRIu32")",
- disk_name, (u32)GetLastError());
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't get disk info", disk_name);
ret = WIMLIB_ERR_READ;
goto out;
}
h = CreateFile(path, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("\"%ls\": Can't open file for writing", path);
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't open file for writing", path);
return WIMLIB_ERR_OPEN;
}
+ SetLastError(0);
if (!WriteFile(h, contents, size, &bytes_written, NULL) ||
bytes_written != size)
{
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("\"%ls\": Can't write file", path);
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't write file", path);
CloseHandle(h);
return WIMLIB_ERR_WRITE;
}
if (!CloseHandle(h)) {
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("\"%ls\": Can't close handle", path);
+ win32_error(GetLastError(),
+ L"\"%ls\": Can't close handle", path);
return WIMLIB_ERR_WRITE;
}
err = err2;
}
}
- set_errno_from_win32_error(err);
- ERROR_WITH_ERRNO("\"%ls\": Can't open for reading", path);
+ win32_error(err, L"\"%ls\": Can't open for reading", path);
return WIMLIB_ERR_OPEN;
}
if (!GetFileInformationByHandle(h, &info)) {
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("\"%ls\": Can't query metadata", path);
+ win32_error(GetLastError(), L"\"%ls\": Can't query metadata", path);
CloseHandle(h);
return WIMLIB_ERR_STAT;
}
return WIMLIB_ERR_NOMEM;
}
+ SetLastError(0);
if (!ReadFile(h, contents, info.nFileSizeLow, &bytes_read, NULL) ||
bytes_read != info.nFileSizeLow)
{
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("\"%ls\": Can't read data", path);
+ win32_error(GetLastError(), L"\"%ls\": Can't read data", path);
CloseHandle(h);
ret = WIMLIB_ERR_READ;
goto out_free_contents;
h = open_file(drive_path, GENERIC_WRITE);
if (h == INVALID_HANDLE_VALUE) {
- set_errno_from_GetLastError();
- ERROR_WITH_ERRNO("Failed to open \"%ls\"", drive_path + 4);
+ win32_error(GetLastError(),
+ L"Failed to open \"%ls\"", drive_path + 4);
ret = WIMLIB_ERR_OPEN;
goto out_free_in;
}
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_close_handle;
} else {
- set_errno_from_win32_error(err);
- ERROR_WITH_ERRNO("Failed to add overlay source \"%ls\" "
- "to volume \"%ls\" (err=0x%08"PRIx32")",
- wim_path, drive_path + 4, (u32)err);
+ win32_error(err, L"Failed to add overlay source \"%ls\" "
+ "to volume \"%ls\"", wim_path, drive_path + 4);
ret = WIMLIB_ERR_WIMBOOT;
goto out_close_handle;
}
}
if (bytes_returned != sizeof(data_source_id)) {
- set_errno_from_win32_error(ERROR_INVALID_DATA);
ret = WIMLIB_ERR_WIMBOOT;
ERROR("Unexpected result size when adding "
"overlay source \"%ls\" to volume \"%ls\"",
*
* @h
* Open handle to the file, with GENERIC_WRITE access.
- * @printable_name
- * Printable representation of the path to the file.
- * @lte
- * Unnamed data stream of the file.
+ * @blob
+ * The blob for the unnamed data stream of the file.
* @data_source_id
* Allocated identifier for the WIM data source on the destination volume.
- * @lookup_table_hash
- * SHA-1 message digest of the WIM's lookup table.
+ * @blob_table_hash
+ * SHA-1 message digest of the WIM's blob table.
* @wof_running
* %true if the WOF driver appears to be available and working; %false if
* not.
*
- * Returns 0 on success, or a positive error code on failure.
+ * Returns %true on success, or %false on failure with GetLastError() set.
*/
-int
+bool
wimboot_set_pointer(HANDLE h,
- const wchar_t *printable_name,
- const struct wim_lookup_table_entry *lte,
+ const struct blob_descriptor *blob,
u64 data_source_id,
- const u8 lookup_table_hash[SHA1_HASH_SIZE],
+ const u8 blob_table_hash[SHA1_HASH_SIZE],
bool wof_running)
{
DWORD bytes_returned;
- DWORD err;
if (wof_running) {
/* The WOF driver is running. We can create the reparse point
* using FSCTL_SET_EXTERNAL_BACKING. */
-
+ unsigned int max_retries = 4;
struct {
struct wof_external_info wof_info;
struct wim_provider_external_info wim_info;
} in;
+ retry:
+ memset(&in, 0, sizeof(in));
+
in.wof_info.version = WOF_CURRENT_VERSION;
in.wof_info.provider = WOF_PROVIDER_WIM;
in.wim_info.version = WIM_PROVIDER_CURRENT_VERSION;
in.wim_info.flags = 0;
in.wim_info.data_source_id = data_source_id;
- copy_hash(in.wim_info.resource_hash, lte->hash);
+ copy_hash(in.wim_info.unnamed_data_stream_hash, blob->hash);
- /* lookup_table_hash is not necessary */
+ /* blob_table_hash is not necessary */
if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING,
&in, sizeof(in), NULL, 0,
&bytes_returned, NULL))
- goto fail;
+ {
+ /* Try to track down sporadic errors */
+ if (wimlib_print_errors) {
+ WARNING("FSCTL_SET_EXTERNAL_BACKING failed (err=%u); data was %zu bytes:",
+ (u32)GetLastError(), sizeof(in));
+ print_byte_field((const u8 *)&in, sizeof(in), wimlib_error_file);
+ putc('\n', wimlib_error_file);
+ }
+ if (--max_retries) {
+ WARNING("Retrying after 100ms...");
+ Sleep(100);
+ goto retry;
+ }
+ WARNING("Too many retries; returning failure");
+ return false;
+ }
} else {
/* The WOF driver is running. We need to create the reparse
in.wim_info.version = 2;
in.wim_info.flags = 0;
in.wim_info.data_source_id = data_source_id;
- copy_hash(in.wim_info.resource_hash, lte->hash);
- copy_hash(in.wim_info.wim_lookup_table_hash, lookup_table_hash);
- in.wim_info.stream_uncompressed_size = lte->size;
- in.wim_info.stream_compressed_size = lte->rspec->size_in_wim;
- in.wim_info.stream_offset_in_wim = lte->rspec->offset_in_wim;
+ copy_hash(in.wim_info.unnamed_data_stream_hash, blob->hash);
+ copy_hash(in.wim_info.blob_table_hash, blob_table_hash);
+ in.wim_info.unnamed_data_stream_uncompressed_size = blob->size;
+ in.wim_info.unnamed_data_stream_compressed_size = blob->rdesc->size_in_wim;
+ in.wim_info.unnamed_data_stream_offset_in_wim = blob->rdesc->offset_in_wim;
if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT,
&in, sizeof(in), NULL, 0, &bytes_returned, NULL))
- goto fail;
+ return false;
/* We also need to create an unnamed data stream of the correct
* size. Otherwise the file shows up as zero length. It can be
* are unimportant. */
if (!DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
&bytes_returned, NULL))
- goto fail;
+ return false;
if (!SetFilePointerEx(h,
- (LARGE_INTEGER){ .QuadPart = lte->size},
+ (LARGE_INTEGER){ .QuadPart = blob->size},
NULL, FILE_BEGIN))
- goto fail;
+ return false;
if (!SetEndOfFile(h))
- goto fail;
+ return false;
}
- return 0;
-
-fail:
- err = GetLastError();
- set_errno_from_win32_error(err);
- ERROR_WITH_ERRNO("\"%ls\": Couldn't set WIMBoot pointer data "
- "(err=%"PRIu32")", printable_name, (u32)err);
- return WIMLIB_ERR_WIMBOOT;
+ return true;
}
#endif /* __WIN32__ */