]> wimlib.net Git - wimlib/blobdiff - src/wimboot.c
Remove unnecessary argument to hlist iteration macros
[wimlib] / src / wimboot.c
index 3562890d7636b08d4ea686df1fe5f9e26002deb7..b06816e28c4a6986a45fe37114f5cd99876ee28e 100644 (file)
 #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
@@ -93,8 +94,8 @@ query_partition_and_disk_info(const wchar_t *path,
 
        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;
        }
@@ -102,8 +103,8 @@ query_partition_and_disk_info(const wchar_t *path,
        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;
        }
@@ -121,8 +122,9 @@ query_partition_and_disk_info(const wchar_t *path,
                                 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;
                }
@@ -145,8 +147,8 @@ query_partition_and_disk_info(const wchar_t *path,
 
        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;
        }
@@ -164,8 +166,8 @@ query_partition_and_disk_info(const wchar_t *path,
                                 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;
                }
@@ -290,23 +292,24 @@ write_wimoverlay_dat(const wchar_t *path, const void *contents, u32 size)
        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;
        }
 
@@ -592,13 +595,11 @@ retry:
                                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;
        }
@@ -612,11 +613,11 @@ retry:
                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;
@@ -982,8 +983,8 @@ retry_ioctl:
        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;
        }
@@ -1005,17 +1006,14 @@ retry_ioctl:
                        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\"",
@@ -1059,54 +1057,68 @@ out:
  *
  * @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
@@ -1136,15 +1148,15 @@ wimboot_set_pointer(HANDLE h,
                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
@@ -1152,25 +1164,18 @@ wimboot_set_pointer(HANDLE h,
                 * 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__ */