* described by @blob. */
int
read_winnt_stream_prefix(const struct blob_descriptor *blob, u64 size,
- consume_data_callback_t cb, void *cb_ctx)
+ const struct read_blob_callbacks *cbs)
{
const wchar_t *path;
HANDLE h;
bytes_read = iosb.Information;
bytes_remaining -= bytes_read;
- ret = (*cb)(buf, bytes_read, cb_ctx);
+ ret = call_consume_chunk(buf, bytes_read, cbs);
if (ret)
break;
}
}
struct win32_encrypted_read_ctx {
- consume_data_callback_t read_prefix_cb;
- void *read_prefix_ctx;
+ const struct read_blob_callbacks *cbs;
int wimlib_err_code;
u64 bytes_remaining;
};
if (bytes_to_consume == 0)
return ERROR_SUCCESS;
- ret = (*ctx->read_prefix_cb)(data, bytes_to_consume, ctx->read_prefix_ctx);
+ ret = call_consume_chunk(data, bytes_to_consume, ctx->cbs);
if (ret) {
ctx->wimlib_err_code = ret;
/* It doesn't matter what error code is returned here, as long
int
read_win32_encrypted_file_prefix(const struct blob_descriptor *blob,
u64 size,
- consume_data_callback_t cb, void *cb_ctx)
+ const struct read_blob_callbacks *cbs)
{
struct win32_encrypted_read_ctx export_ctx;
DWORD err;
if (blob->file_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
flags |= CREATE_FOR_DIR;
- export_ctx.read_prefix_cb = cb;
- export_ctx.read_prefix_ctx = cb_ctx;
+ export_ctx.cbs = cbs;
export_ctx.wimlib_err_code = 0;
export_ctx.bytes_remaining = size;
}
static int
-winnt_load_efsrpc_raw_data(struct wim_inode *inode, const wchar_t *nt_path,
+winnt_scan_efsrpc_raw_data(struct wim_inode *inode, const wchar_t *nt_path,
struct list_head *unhashed_blobs)
{
struct blob_descriptor *blob;
if (ret)
goto err;
+ /* Empty EFSRPC data does not make sense */
+ wimlib_assert(blob->size != 0);
+
strm = inode_add_stream(inode, STREAM_TYPE_EFSRPC_RAW_DATA,
NO_STREAM_NAME, blob);
if (!strm)
return true;
}
-/* Build the path to the stream. For unnamed streams, this is simply the path
- * to the file. For named streams, this is the path to the file, followed by a
- * colon, followed by the stream name. */
+/* Build the path to the data stream. For unnamed streams, this is simply the
+ * path to the file. For named streams, this is the path to the file, followed
+ * by a colon, followed by the stream name. */
static wchar_t *
-build_stream_path(const wchar_t *path, size_t path_nchars,
- const wchar_t *stream_name, size_t stream_name_nchars)
+build_data_stream_path(const wchar_t *path, size_t path_nchars,
+ const wchar_t *stream_name, size_t stream_name_nchars)
{
size_t stream_path_nchars;
wchar_t *stream_path;
blob = new_blob_descriptor();
if (!blob)
goto err_nomem;
- blob->file_on_disk = build_stream_path(path,
- path_nchars,
- stream_name,
- stream_name_nchars);
+ blob->file_on_disk = build_data_stream_path(path,
+ path_nchars,
+ stream_name,
+ stream_name_nchars);
if (!blob->file_on_disk)
goto err_nomem;
blob->blob_location = BLOB_IN_WINNT_FILE_ON_DISK;
goto out_free_buf;
}
- ret = winnt_scan_data_stream(path, path_nchars, L"::$DATA", 7,
- file_size, inode, unhashed_blobs);
+ {
+ wchar_t stream_name[] = L"::$DATA";
+ ret = winnt_scan_data_stream(path, path_nchars, stream_name, 7,
+ file_size, inode, unhashed_blobs);
+ }
out_free_buf:
/* Free buffer if allocated on heap. */
if (unlikely(buf != _buf))
return ret;
}
+static 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 int
winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
HANDLE cur_dir,
NTSTATUS status;
FILE_ALL_INFORMATION file_info;
ACCESS_MASK requestedPerms;
+ u64 sort_key;
ret = try_exclude(full_path, full_path_nchars, params);
if (ret < 0) /* Excluded? */
}
}
+ sort_key = get_sort_key(h);
+
if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)) {
/* Load information about the raw encrypted data. This is
* needed for any directory or non-directory that has
* needed. */
(*func_NtClose)(h);
h = NULL;
- ret = winnt_load_efsrpc_raw_data(inode, full_path,
+ ret = winnt_scan_efsrpc_raw_data(inode, full_path,
params->unhashed_blobs);
if (ret)
goto out;
goto out;
}
+ set_sort_key(inode, sort_key);
+
if (inode_is_directory(inode)) {
/* Directory: recurse to children. */