+static noinline_for_stack u64
+get_sort_key(HANDLE h)
+{
+ STARTING_VCN_INPUT_BUFFER in = { .StartingVcn.QuadPart = 0 };
+ RETRIEVAL_POINTERS_BUFFER out;
+ DWORD bytesReturned;
+
+ if (!DeviceIoControl(h, FSCTL_GET_RETRIEVAL_POINTERS,
+ &in, sizeof(in),
+ &out, sizeof(out),
+ &bytesReturned, NULL))
+ return 0;
+
+ if (out.ExtentCount < 1)
+ return 0;
+
+ return out.Extents[0].Lcn.QuadPart;
+}
+
+static void
+set_sort_key(struct wim_inode *inode, u64 sort_key)
+{
+ for (unsigned i = 0; i < inode->i_num_streams; i++) {
+ struct wim_inode_stream *strm = &inode->i_streams[i];
+ struct blob_descriptor *blob = stream_blob_resolved(strm);
+ if (blob && (blob->blob_location == BLOB_IN_WINNT_FILE_ON_DISK ||
+ blob->blob_location == BLOB_WIN32_ENCRYPTED))
+ blob->sort_key = sort_key;
+ }
+}
+
+static noinline_for_stack u32
+get_volume_information(HANDLE h, const wchar_t *full_path,
+ struct capture_params *params)
+{
+ FILE_FS_ATTRIBUTE_INFORMATION attr_info;
+ FILE_FS_VOLUME_INFORMATION vol_info;
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
+ u32 vol_flags;
+
+ /* Get volume flags */
+ status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+ &attr_info,
+ sizeof(attr_info),
+ FileFsAttributeInformation);
+ if (likely((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
+ (iosb.Information >=
+ offsetof(FILE_FS_ATTRIBUTE_INFORMATION,
+ FileSystemAttributes) +
+ sizeof(attr_info.FileSystemAttributes))))
+ {
+ vol_flags = attr_info.FileSystemAttributes;
+ } else {
+ winnt_warning(status, L"\"%ls\": Can't get volume attributes",
+ printable_path(full_path));
+ vol_flags = 0;
+ }
+
+ /* Get volume ID. */
+ status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+ &vol_info,
+ sizeof(vol_info),
+ FileFsVolumeInformation);
+ if (likely((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
+ (iosb.Information >=
+ offsetof(FILE_FS_VOLUME_INFORMATION,
+ VolumeSerialNumber) +
+ sizeof(vol_info.VolumeSerialNumber))))
+ {
+ params->capture_root_dev = vol_info.VolumeSerialNumber;
+ } else {
+ winnt_warning(status, L"\"%ls\": Can't get volume ID",
+ printable_path(full_path));
+ params->capture_root_dev = 0;
+ }
+ return vol_flags;
+}
+
+struct file_info {
+ u32 attributes;
+ u32 num_links;
+ u64 creation_time;
+ u64 last_write_time;
+ u64 last_access_time;
+ u64 ino;
+ u64 end_of_file;
+};
+
+static noinline_for_stack NTSTATUS
+get_file_info(HANDLE h, struct file_info *info)
+{
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
+ FILE_ALL_INFORMATION all_info;
+
+ status = (*func_NtQueryInformationFile)(h, &iosb, &all_info,
+ sizeof(all_info),
+ FileAllInformation);
+
+ if (unlikely(!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW))
+ return status;
+
+ info->attributes = all_info.BasicInformation.FileAttributes;
+ info->num_links = all_info.StandardInformation.NumberOfLinks;
+ info->creation_time = all_info.BasicInformation.CreationTime.QuadPart;
+ info->last_write_time = all_info.BasicInformation.LastWriteTime.QuadPart;
+ info->last_access_time = all_info.BasicInformation.LastAccessTime.QuadPart;
+ info->ino = all_info.InternalInformation.IndexNumber.QuadPart;
+ info->end_of_file = all_info.StandardInformation.EndOfFile.QuadPart;
+ return STATUS_SUCCESS;
+}
+