]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
Factor out Win32 => NT path conversion and use in win32_capture.c
[wimlib] / src / win32_capture.c
index bc5422e85c7feaeebfcd2989aaea0f93b6fdb802..6223ed26135acb26fc4da3d7d139998bc982b5f6 100644 (file)
@@ -406,11 +406,18 @@ winnt_recurse_directory(HANDLE h,
                                                           info->FileName[1] == L'.'))
                        {
                                wchar_t *p;
+                               wchar_t *filename;
                                struct wim_dentry *child;
 
                                p = full_path + full_path_nchars;
-                               *p++ = L'\\';
-                               p = wmempcpy(p, info->FileName,
+                               /* Only add a backslash if we don't already have
+                                * one.  This prevents a duplicate backslash
+                                * from being added when the path to the capture
+                                * dir had a trailing backslash.  */
+                               if (*(p - 1) != L'\\')
+                                       *p++ = L'\\';
+                               filename = p;
+                               p = wmempcpy(filename, info->FileName,
                                             info->FileNameLength / 2);
                                *p = '\0';
 
@@ -419,7 +426,7 @@ winnt_recurse_directory(HANDLE h,
                                                        h,
                                                        full_path,
                                                        p - full_path,
-                                                       full_path + full_path_nchars + 1,
+                                                       filename,
                                                        info->FileNameLength / 2,
                                                        params,
                                                        stats,
@@ -453,9 +460,6 @@ out_free_buf:
 
 /* Reparse point fixup status code  */
 enum rp_status {
-       /* Reparse point should be excluded from capture  */
-       RP_EXCLUDED     = -0,
-
        /* Reparse point will be captured literally (no fixup)  */
        RP_NOT_FIXED    = -1,
 
@@ -650,14 +654,13 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                                                    capture_root_ino,
                                                    capture_root_dev);
        if (!rel_target) {
-               /* Target points outside of the tree being captured.  Exclude
-                * this reparse point from the capture (but inform the library
-                * user).  */
+               /* Target points outside of the tree being captured.  Don't
+                * adjust it.  */
                ret = winnt_rpfix_progress(params, path, &rpdata,
-                                          WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK);
+                                          WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK);
                if (ret)
                        return ret;
-               return RP_EXCLUDED;
+               return RP_NOT_FIXED;
        }
 
        if (rel_target == rpdata.substitute_name) {
@@ -722,7 +725,7 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
  *     On success, the length of the reparse point buffer in bytes is written
  *     to this location.
  *
- * On success, returns a nonpositive `enum rp_status' value.
+ * On success, returns a negative `enum rp_status' value.
  * On failure, returns a positive error code.
  */
 static int
@@ -1201,9 +1204,6 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                ret = winnt_get_reparse_data(h, full_path, params,
                                             rpbuf, &rpbuflen);
                switch (ret) {
-               case RP_EXCLUDED:
-                       ret = 0;
-                       goto out;
                case RP_FIXED:
                        not_rpfixed = 0;
                        break;
@@ -1385,9 +1385,8 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                        struct add_image_params *params)
 {
        wchar_t *path;
-       DWORD dret;
-       size_t path_nchars;
        int ret;
+       UNICODE_STRING ntpath;
        struct winnt_scan_stats stats;
 
        /* WARNING: There is no check for overflow later when this buffer is
@@ -1397,33 +1396,31 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        if (!path)
                return WIMLIB_ERR_NOMEM;
 
-       /* Translate into full path.  */
-       dret = GetFullPathName(root_disk_path, WINDOWS_NT_MAX_PATH - 3,
-                              &path[4], NULL);
+       ret = win32_path_to_nt_path(root_disk_path, &ntpath);
+       if (ret)
+               goto out_free_path;
 
-       if (unlikely(dret == 0 || dret >= WINDOWS_NT_MAX_PATH - 3)) {
-               ERROR("Can't get full path name for \"%ls\"", root_disk_path);
-               return WIMLIB_ERR_UNSUPPORTED;
+       if (ntpath.Length < 4 * sizeof(wchar_t) ||
+           ntpath.Length > WINDOWS_NT_MAX_PATH * sizeof(wchar_t) ||
+           wmemcmp(ntpath.Buffer, L"\\??\\", 4))
+       {
+               ERROR("\"%ls\": unrecognized path format", root_disk_path);
+               ret = WIMLIB_ERR_INVALID_PARAM;
+               goto out_free_path;
        }
 
-       /* Add \??\ prefix to form the NT namespace path.  */
-       wmemcpy(path, L"\\??\\", 4);
-       path_nchars = dret + 4;
-
-       /* Strip trailing slashes.  If we don't do this, we may create a path
-       * with multiple consecutive backslashes, which for some reason causes
-       * Windows to report that the file cannot be found.  */
-       while (unlikely(path[path_nchars - 1] == L'\\' &&
-                       path[path_nchars - 2] != L':'))
-               path[--path_nchars] = L'\0';
+       params->capture_root_nchars = ntpath.Length / sizeof(wchar_t);
+       wmemcpy(path, ntpath.Buffer, params->capture_root_nchars);
+       path[params->capture_root_nchars] = L'\0';
 
-       params->capture_root_nchars = path_nchars;
+       HeapFree(GetProcessHeap(), 0, ntpath.Buffer);
 
        memset(&stats, 0, sizeof(stats));
 
        ret = winnt_build_dentry_tree_recursive(root_ret, NULL,
-                                               path, path_nchars, L"", 0,
-                                               params, &stats, 0);
+                                               path, params->capture_root_nchars,
+                                               L"", 0, params, &stats, 0);
+out_free_path:
        FREE(path);
        if (ret == 0)
                winnt_do_scan_warnings(root_disk_path, &stats);