]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
win32_capture_streams(): Decrease buffer size for stream info
[wimlib] / src / win32_capture.c
index ef53f1aaf45c49c02a898b76e2da38617a921f6b..e333568a18746ef8f74e01450e01ddce7401959e 100644 (file)
@@ -214,13 +214,6 @@ read_win32_encrypted_file_prefix(const struct wim_lookup_table_entry *lte,
        return ret;
 }
 
-
-static u64
-FILETIME_to_u64(const FILETIME *ft)
-{
-       return ((u64)ft->dwHighDateTime << 32) | (u64)ft->dwLowDateTime;
-}
-
 /* Load the short name of a file into a WIM dentry.
  *
  * If we can't read the short filename for some reason, we just ignore the error
@@ -352,7 +345,7 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                  size_t filename_nchars,
                                  struct add_image_params *params,
                                  struct win32_capture_state *state,
-                                 unsigned vol_flags);
+                                 DWORD vol_flags);
 
 /* Reads the directory entries of directory and recursively calls
  * win32_build_dentry_tree() on them.  */
@@ -363,7 +356,7 @@ win32_recurse_directory(HANDLE h,
                        struct wim_dentry *root,
                        struct add_image_params *params,
                        struct win32_capture_state *state,
-                       unsigned vol_flags)
+                       DWORD vol_flags)
 {
        int ret;
 
@@ -834,10 +827,10 @@ win32_capture_streams(HANDLE *hFile_p,
                      struct wim_inode *inode,
                      struct list_head *unhashed_streams,
                      u64 file_size,
-                     unsigned vol_flags)
+                     DWORD vol_flags)
 {
        int ret;
-       u8 _buf[8192] _aligned_attribute(8);
+       u8 _buf[1024] _aligned_attribute(8);
        u8 *buf;
        size_t bufsize;
        IO_STATUS_BLOCK io_status;
@@ -957,14 +950,14 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                  size_t filename_nchars,
                                  struct add_image_params *params,
                                  struct win32_capture_state *state,
-                                 unsigned vol_flags)
+                                 DWORD vol_flags)
 {
        struct wim_dentry *root = NULL;
        struct wim_inode *inode = NULL;
        HANDLE h = INVALID_HANDLE_VALUE;
        int ret;
        NTSTATUS status;
-       BY_HANDLE_FILE_INFORMATION file_info;
+       FILE_ALL_INFORMATION file_info;
        u8 *rpbuf;
        u16 rpbuflen;
        u16 not_rpfixed;
@@ -993,14 +986,65 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                goto out;
        }
 
-       if (!GetFileInformationByHandle(h, &file_info)) {
-               set_errno_from_GetLastError();
-               ERROR_WITH_ERRNO("\"%ls\": Can't get file information", full_path);
-               ret = WIMLIB_ERR_STAT;
-               goto out;
+       {
+               IO_STATUS_BLOCK iosb;
+
+               status = (*func_NtQueryInformationFile)(h, &iosb,
+                                                       &file_info, sizeof(file_info),
+                                                       FileAllInformation);
+               if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
+                       set_errno_from_GetLastError();
+                       ERROR_WITH_ERRNO("\"%ls\": Can't get file information", full_path);
+                       ret = WIMLIB_ERR_STAT;
+                       goto out;
+               }
        }
 
-       if (file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+       if (!cur_dir) {
+               /* Root directory; get volume information.  */
+               FILE_FS_ATTRIBUTE_INFORMATION attr_info;
+               FILE_FS_VOLUME_INFORMATION vol_info;
+               IO_STATUS_BLOCK iosb;
+
+               /* Get volume flags  */
+               status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+                                                             &attr_info, sizeof(attr_info),
+                                                             FileFsAttributeInformation);
+               if ((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 {
+                       set_errno_from_nt_status(status);
+                       WARNING_WITH_ERRNO("\"%ls\": Can't get volume attributes",
+                                          full_path);
+                       vol_flags = 0;
+               }
+
+               /* Set inode number of root directory  */
+               params->capture_root_ino = file_info.InternalInformation.IndexNumber.QuadPart;
+
+               /* Get volume ID  */
+               status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+                                                             &vol_info, sizeof(vol_info),
+                                                             FileFsVolumeInformation);
+               if ((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 {
+                       set_errno_from_nt_status(status);
+                       WARNING_WITH_ERRNO("\"%ls\": Can't get volume ID",
+                                          full_path);
+                       params->capture_root_dev = 0;
+               }
+       }
+
+       if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
                rpbuf = alloca(REPARSE_POINT_MAX_SIZE);
                ret = win32_get_reparse_data(h, full_path,
                                             params, rpbuf, &rpbuflen);
@@ -1028,11 +1072,13 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
         * directories on the FAT filesystem. */
        ret = inode_table_new_dentry(params->inode_table,
                                     filename,
-                                    ((u64)file_info.nFileIndexHigh << 32) |
-                                        (u64)file_info.nFileIndexLow,
-                                    file_info.dwVolumeSerialNumber,
-                                    (file_info.nNumberOfLinks <= 1 ||
-                                       (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)),
+                                    file_info.InternalInformation.IndexNumber.QuadPart,
+                                    0, /* We don't follow mount points, so we
+                                          currently don't need to get the
+                                          volume ID / device number.  */
+                                    (file_info.StandardInformation.NumberOfLinks <= 1 ||
+                                       (file_info.BasicInformation.FileAttributes &
+                                        FILE_ATTRIBUTE_DIRECTORY)),
                                     &root);
        if (ret)
                goto out;
@@ -1051,10 +1097,10 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                goto out_progress;
        }
 
-       inode->i_attributes = file_info.dwFileAttributes;
-       inode->i_creation_time = FILETIME_to_u64(&file_info.ftCreationTime);
-       inode->i_last_write_time = FILETIME_to_u64(&file_info.ftLastWriteTime);
-       inode->i_last_access_time = FILETIME_to_u64(&file_info.ftLastAccessTime);
+       inode->i_attributes = file_info.BasicInformation.FileAttributes;
+       inode->i_creation_time = file_info.BasicInformation.CreationTime.QuadPart;
+       inode->i_last_write_time = file_info.BasicInformation.LastWriteTime.QuadPart;
+       inode->i_last_access_time = file_info.BasicInformation.LastAccessTime.QuadPart;
        inode->i_resolved = 1;
 
        params->add_flags &= ~WIMLIB_ADD_FLAG_ROOT;
@@ -1079,8 +1125,7 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                    full_path_nchars,
                                    inode,
                                    params->unhashed_streams,
-                                   ((u64)file_info.nFileSizeHigh << 32) |
-                                       file_info.nFileSizeLow,
+                                   file_info.StandardInformation.EndOfFile.QuadPart,
                                    vol_flags);
        if (ret)
                goto out;
@@ -1172,35 +1217,20 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                        const wchar_t *root_disk_path,
                        struct add_image_params *params)
 {
-       size_t path_nchars;
        wchar_t *path;
+       DWORD dret;
+       size_t path_nchars;
        int ret;
        struct win32_capture_state state;
-       unsigned vol_flags;
-       DWORD dret;
-
-       path_nchars = wcslen(root_disk_path);
-       if (path_nchars > WINDOWS_NT_MAX_PATH)
-               return WIMLIB_ERR_INVALID_PARAM;
-
-       ret = win32_get_file_and_vol_ids(root_disk_path,
-                                        &params->capture_root_ino,
-                                        &params->capture_root_dev);
-       if (ret) {
-               ERROR_WITH_ERRNO("Can't open %ls", root_disk_path);
-               return ret;
-       }
-
-       win32_get_vol_flags(root_disk_path, &vol_flags, NULL);
 
        /* WARNING: There is no check for overflow later when this buffer is
         * being used!  But it's as long as the maximum path length understood
-        * by Windows NT (which is NOT the same as MAX_PATH). */
+        * by Windows NT (which is NOT the same as MAX_PATH).  */
        path = MALLOC((WINDOWS_NT_MAX_PATH + 1) * sizeof(wchar_t));
        if (!path)
                return WIMLIB_ERR_NOMEM;
 
-       /* Translate into full path  */
+       /* Translate into full path.  */
        dret = GetFullPathName(root_disk_path, WINDOWS_NT_MAX_PATH - 3,
                               &path[4], NULL);
 
@@ -1209,7 +1239,7 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                return WIMLIB_ERR_UNSUPPORTED;
        }
 
-       /* Add \??\ prefix  */
+       /* Add \??\ prefix to form the NT namespace path.  */
        wmemcpy(path, L"\\??\\", 4);
        path_nchars = dret + 4;
 
@@ -1228,7 +1258,7 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        memset(&state, 0, sizeof(state));
        ret = win32_build_dentry_tree_recursive(root_ret, NULL,
                                                path, path_nchars, L"", 0,
-                                               params, &state, vol_flags);
+                                               params, &state, 0);
        FREE(path);
        if (ret == 0)
                win32_do_capture_warnings(root_disk_path, &state, params->add_flags);