]> wimlib.net Git - wimlib/blobdiff - src/win32_apply.c
Add randomized testing program
[wimlib] / src / win32_apply.c
index fbed6b9c685d479cca4ba69559d98bd6de8a7ee2..6f9e41b98393669f8ad42151ecd9407c4c2c6e88 100644 (file)
 #include "wimlib/apply.h"
 #include "wimlib/assert.h"
 #include "wimlib/blob_table.h"
-#include "wimlib/capture.h" /* for mangle_pat() and match_pattern_list()  */
 #include "wimlib/dentry.h"
 #include "wimlib/encoding.h"
 #include "wimlib/error.h"
 #include "wimlib/metadata.h"
+#include "wimlib/object_id.h"
 #include "wimlib/paths.h"
 #include "wimlib/pattern.h"
 #include "wimlib/reparse.h"
+#include "wimlib/scan.h" /* for mangle_pat() and match_pattern_list()  */
 #include "wimlib/textfile.h"
 #include "wimlib/xml.h"
 #include "wimlib/wimboot.h"
@@ -68,7 +69,7 @@ struct win32_apply_ctx {
        } wimboot;
 
        /* External backing information  */
-       struct string_set *prepopulate_pats;
+       struct string_list *prepopulate_pats;
        void *mem_prepopulate_pats;
        bool tried_to_load_prepopulate_list;
 
@@ -158,6 +159,9 @@ struct win32_apply_ctx {
         * [PrepopulateList].  */
        unsigned long num_system_compression_exclusions;
 
+       /* Number of files for which we couldn't set the object ID.  */
+       unsigned long num_object_id_failures;
+
        /* The Windows build number of the image being applied, or 0 if unknown.
         */
        u64 windows_build_number;
@@ -299,6 +303,9 @@ win32_get_supported_features(const wchar_t *target,
        if (short_names_supported)
                supported_features->short_names = 1;
 
+       if (vol_flags & FILE_SUPPORTS_OBJECT_IDS)
+               supported_features->object_ids = 1;
+
        supported_features->timestamps = 1;
 
        /* Note: Windows does not support case sensitive filenames!  At least
@@ -331,7 +338,7 @@ load_prepopulate_pats(struct win32_apply_ctx *ctx)
        const struct blob_descriptor *blob;
        int ret;
        void *buf;
-       struct string_set *s;
+       struct string_list *strings;
        void *mem;
        struct text_file_section sec;
 
@@ -359,14 +366,14 @@ load_prepopulate_pats(struct win32_apply_ctx *ctx)
        if (ret)
                return ret;
 
-       s = CALLOC(1, sizeof(struct string_set));
-       if (!s) {
+       strings = CALLOC(1, sizeof(struct string_list));
+       if (!strings) {
                FREE(buf);
                return WIMLIB_ERR_NOMEM;
        }
 
        sec.name = T("PrepopulateList");
-       sec.strings = s;
+       sec.strings = strings;
 
        ret = do_load_text_file(path, buf, blob->size, &mem, &sec, 1,
                                LOAD_TEXT_FILE_REMOVE_QUOTES |
@@ -375,10 +382,10 @@ load_prepopulate_pats(struct win32_apply_ctx *ctx)
        STATIC_ASSERT(OS_PREFERRED_PATH_SEPARATOR == WIM_PATH_SEPARATOR);
        FREE(buf);
        if (ret) {
-               FREE(s);
+               FREE(strings);
                return ret;
        }
-       ctx->prepopulate_pats = s;
+       ctx->prepopulate_pats = strings;
        ctx->mem_prepopulate_pats = mem;
        return 0;
 }
@@ -1003,8 +1010,7 @@ open_target_directory(struct win32_apply_ctx *ctx)
                              0,
                              FILE_SHARE_VALID_FLAGS,
                              FILE_OPEN_IF,
-                               FILE_DIRECTORY_FILE |
-                               FILE_OPEN_FOR_BACKUP_INTENT,
+                             FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT,
                              NULL,
                              0);
        if (!NT_SUCCESS(status)) {
@@ -1123,7 +1129,7 @@ adjust_compression_attribute(HANDLE h, const struct wim_dentry *dentry,
        status = winnt_fsctl(h, FSCTL_SET_COMPRESSION,
                             &compression_state, sizeof(USHORT), NULL, 0, NULL);
        if (NT_SUCCESS(status))
-               return status;
+               return 0;
 
        winnt_error(status, L"Can't %s compression attribute on \"%ls\"",
                    (compressed ? "set" : "clear"), current_path(ctx));
@@ -2430,7 +2436,7 @@ static wchar_t *bootloader_pattern_strings[] = {
        L"\\Windows\\System32\\CodeIntegrity\\driver.stl",
 };
 
-static const struct string_set bootloader_patterns = {
+static const struct string_list bootloader_patterns = {
        .strings = bootloader_pattern_strings,
        .num_strings = ARRAY_LEN(bootloader_pattern_strings),
 };
@@ -2660,6 +2666,46 @@ end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
         FILE_ATTRIBUTE_SPARSE_FILE     |       \
         FILE_ATTRIBUTE_COMPRESSED)
 
+static void
+set_object_id(HANDLE h, const struct wim_inode *inode,
+             struct win32_apply_ctx *ctx)
+{
+       const void *object_id;
+       u32 len;
+       NTSTATUS status;
+
+       if (!ctx->common.supported_features.object_ids)
+               return;
+
+       object_id = inode_get_object_id(inode, &len);
+       if (likely(object_id == NULL))  /* No object ID?  */
+               return;
+
+       status = winnt_fsctl(h, FSCTL_SET_OBJECT_ID,
+                            object_id, len, NULL, 0, NULL);
+       if (NT_SUCCESS(status))
+               return;
+
+       /* Object IDs must be unique within the filesystem.  A duplicate might
+        * occur if an image containing object IDs is applied twice to the same
+        * filesystem.  Arguably, the user should be warned in this case; but
+        * the reality seems to be that nothing important cares about object IDs
+        * except the Distributed Link Tracking Service... so for now these
+        * failures are just ignored.  */
+       if (status == STATUS_DUPLICATE_NAME ||
+           status == STATUS_OBJECT_NAME_COLLISION)
+               return;
+
+       ctx->num_object_id_failures++;
+       if (ctx->num_object_id_failures < 10) {
+               winnt_warning(status, L"Can't set object ID on \"%ls\"",
+                             current_path(ctx));
+       } else if (ctx->num_object_id_failures == 10) {
+               WARNING("Suppressing further warnings about failure to set "
+                       "object IDs.");
+       }
+}
+
 /* Set the security descriptor @desc, of @desc_size bytes, on the file with open
  * handle @h.  */
 static NTSTATUS
@@ -2804,7 +2850,12 @@ do_apply_metadata_to_file(HANDLE h, const struct wim_inode *inode,
        FILE_BASIC_INFORMATION info;
        NTSTATUS status;
 
-       /* Set security descriptor if present and not in NO_ACLS mode  */
+       /* Set the file's object ID if present and object IDs are supported by
+        * the filesystem.  */
+       set_object_id(h, inode, ctx);
+
+       /* Set the file's security descriptor if present and we're not in
+        * NO_ACLS mode  */
        if (inode_has_security_descriptor(inode) &&
            !(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
        {