#ifdef __WIN32__
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <aclapi.h> /* for SetSecurityInfo() */
-#include "win32_common.h"
-#include "wimlib_internal.h"
-#include "dentry.h"
-#include "lookup_table.h"
-#include "endianness.h"
+#include "wimlib/win32_common.h"
+
+#include "wimlib/apply.h"
+#include "wimlib/dentry.h"
+#include "wimlib/endianness.h"
+#include "wimlib/error.h"
+#include "wimlib/lookup_table.h"
+#include "wimlib/metadata.h"
+#include "wimlib/reparse.h"
+#include "wimlib/security.h"
#define MAX_CREATE_HARD_LINK_WARNINGS 5
#define MAX_CREATE_SOFT_LINK_WARNINGS 5
static int
win32_extract_try_rpfix(u8 *rpbuf,
+ u16 *rpbuflen_p,
const wchar_t *extract_root_realpath,
unsigned extract_root_realpath_nchars)
{
size_t new_print_name_nchars;
utf16lechar *p;
- ret = parse_reparse_data(rpbuf, 8 + le16_to_cpu(*(u16*)(rpbuf + 4)),
- &rpdata);
+ ret = parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata);
if (ret)
return ret;
stripped_nchars = ret;
target = rpdata.substitute_name;
target_nchars = rpdata.substitute_name_nbytes / sizeof(utf16lechar);
- stripped_target = target + 6;
+ stripped_target = target + stripped_nchars;
stripped_target_nchars = target_nchars - stripped_nchars;
new_target = alloca((6 + extract_root_realpath_nchars +
p = new_target;
if (stripped_nchars == 6) {
/* Include \??\ prefix if it was present before */
- wmemcpy(p, L"\\??\\", 4);
- p += 4;
+ p = wmempcpy(p, L"\\??\\", 4);
}
/* Print name excludes the \??\ if present. */
*p++ = extract_root_realpath[1];
}
/* Copy the rest of the extract root */
- wmemcpy(p, extract_root_realpath + 2, extract_root_realpath_nchars - 2);
- p += extract_root_realpath_nchars - 2;
+ p = wmempcpy(p, extract_root_realpath + 2, extract_root_realpath_nchars - 2);
/* Append the stripped target */
- wmemcpy(p, stripped_target, stripped_target_nchars);
- p += stripped_target_nchars;
+ p = wmempcpy(p, stripped_target, stripped_target_nchars);
new_target_nchars = p - new_target;
new_print_name_nchars = p - new_print_name;
rpdata.substitute_name_nbytes = new_target_nchars * sizeof(utf16lechar);
rpdata.print_name = new_print_name;
rpdata.print_name_nbytes = new_print_name_nchars * sizeof(utf16lechar);
- return make_reparse_buffer(&rpdata, rpbuf);
+ return make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p);
}
/* Wrapper around the FSCTL_SET_REPARSE_POINT ioctl to set the reparse data on
struct apply_args *args)
{
int ret;
- u8 rpbuf[REPARSE_POINT_MAX_SIZE];
+ u8 rpbuf[REPARSE_POINT_MAX_SIZE] _aligned_attribute(8);
DWORD bytesReturned;
+ u16 rpbuflen;
DEBUG("Setting reparse data on \"%ls\"", path);
- ret = wim_inode_get_reparse_data(inode, rpbuf);
+ ret = wim_inode_get_reparse_data(inode, rpbuf, &rpbuflen);
if (ret)
return ret;
!inode->i_not_rpfixed)
{
ret = win32_extract_try_rpfix(rpbuf,
+ &rpbuflen,
args->target_realpath,
args->target_realpath_len);
if (ret)
* "Not used with this operation; set to NULL."
*/
if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, rpbuf,
- 8 + le16_to_cpu(*(u16*)(rpbuf + 4)),
+ rpbuflen,
NULL, 0,
&bytesReturned /* lpBytesReturned */,
NULL /* lpOverlapped */))
static bool
path_is_root_of_drive(const wchar_t *path)
{
- if (!*path)
+ if (*path == L'\0')
return false;
+ if (!wcsncmp(path, L"\\\\?\\", 4))
+ path += 4;
+
if (*path != L'/' && *path != L'\\') {
if (*(path + 1) == L':')
path += 2;
{
int ret = 0;
const struct wim_inode *inode = dentry->d_inode;
- const wchar_t *short_name;
if (stream_name_utf16 == NULL) {
/* Unnamed stream. */
}
if (dentry_has_short_name(dentry))
- SetFileShortNameW(h, short_name);
+ SetFileShortNameW(h, dentry->short_name);
else if (running_on_windows_7_or_later())
SetFileShortNameW(h, L"");
} else {
win32_get_vol_flags(output_path, &args->vol_flags);
args->have_vol_flags = true;
- missing_features = dentry_features ^ args->vol_flags;
+ missing_features = dentry_features & ~args->vol_flags;
/* Warn the user about data that may not be extracted. */
if (missing_features & FILE_SUPPORTS_SPARSE_FILES)
!(args->vol_flags & FILE_SUPPORTS_REPARSE_POINTS))
{
WARNING("Not extracting reparse point \"%ls\"", output_path);
+ dentry->not_extracted = 1;
} else {
/* Create the file, directory, or reparse point, and extract the
* data streams. */
/* Save extracted path for a later call to
* CreateHardLinkW() if this inode has multiple links.
* */
- inode->i_extracted_file = WSTRDUP(output_path);
+ inode->i_extracted_file = WCSDUP(output_path);
if (!inode->i_extracted_file)
return WIMLIB_ERR_NOMEM;
}
HANDLE h;
const struct wim_inode *inode = dentry->d_inode;
- if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
- !(args->vol_flags & FILE_SUPPORTS_REPARSE_POINTS))
- {
- /* Skip reparse points not extracted */
- return 0;
- }
-
/* Windows doesn't let you change the timestamps of the root directory
* (at least on FAT, which is dumb but expected since FAT doesn't store
* any metadata about the root directory...) */