X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwin32_capture.c;h=3466ad47f1af8f36025e6b27fdf53545081723ff;hp=5d89dc63c6d3337af71d690512d3da55e38cb9ee;hb=e7265caaa69fa3456a6e3253390f27288fa1521d;hpb=b60a4b18cd9fded4e45b7fa884d8f67eafd6755d diff --git a/src/win32_capture.c b/src/win32_capture.c index 5d89dc63..3466ad47 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -87,14 +87,13 @@ read_win32_file_prefix(const struct wim_lookup_table_entry *lte, { int ret = 0; void *out_buf; - DWORD err; u64 bytes_remaining; - HANDLE hFile = win32_open_file_data_only(lte->file_on_disk); + HANDLE hFile = win32_open_existing_file(lte->file_on_disk, + FILE_READ_DATA); if (hFile == INVALID_HANDLE_VALUE) { - err = GetLastError(); - ERROR("Failed to open \"%ls\"", lte->file_on_disk); - win32_error(err); + set_errno_from_GetLastError(); + ERROR_WITH_ERRNO("Failed to open \"%ls\"", lte->file_on_disk); return WIMLIB_ERR_OPEN; } @@ -111,9 +110,9 @@ read_win32_file_prefix(const struct wim_lookup_table_entry *lte, if (!ReadFile(hFile, out_buf, bytesToRead, &bytesRead, NULL) || bytesRead != bytesToRead) { - err = GetLastError(); - ERROR("Failed to read data from \"%ls\"", lte->file_on_disk); - win32_error(err); + set_errno_from_GetLastError(); + ERROR_WITH_ERRNO("Failed to read data from \"%ls\"", + lte->file_on_disk); ret = WIMLIB_ERR_READ; break; } @@ -217,20 +216,20 @@ read_win32_encrypted_file_prefix(const struct wim_lookup_table_entry *lte, export_ctx.buf_filled = 0; export_ctx.bytes_remaining = size; - err = OpenEncryptedFileRawW(lte->file_on_disk, 0, &file_ctx); + err = OpenEncryptedFileRaw(lte->file_on_disk, 0, &file_ctx); if (err != ERROR_SUCCESS) { - ERROR("Failed to open encrypted file \"%ls\" for raw read", - lte->file_on_disk); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to open encrypted file \"%ls\" " + "for raw read", lte->file_on_disk); ret = WIMLIB_ERR_OPEN; goto out_free_buf; } err = ReadEncryptedFileRaw(win32_encrypted_export_cb, &export_ctx, file_ctx); if (err != ERROR_SUCCESS) { - ERROR("Failed to read encrypted file \"%ls\"", - lte->file_on_disk); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to read encrypted file \"%ls\"", + lte->file_on_disk); ret = export_ctx.wimlib_err_code; if (ret == 0) ret = WIMLIB_ERR_READ; @@ -318,7 +317,7 @@ win32_get_short_name(HANDLE hFile, const wchar_t *path, struct wim_dentry *dentr * win32_query_security_descriptor() - Query a file's security descriptor * * We need the file's security descriptor in SECURITY_DESCRIPTOR_RELATIVE - * relative format, and we currently have a handle opened with as many relevant + * format, and we currently have a handle opened with as many relevant * permissions as possible. At this point, on Windows there are a number of * options for reading a file's security descriptor: * @@ -344,7 +343,7 @@ win32_get_short_name(HANDLE hFile, const wchar_t *path, struct wim_dentry *dentr static DWORD win32_query_security_descriptor(HANDLE hFile, const wchar_t *path, SECURITY_INFORMATION requestedInformation, - PSECURITY_DESCRIPTOR *buf, + SECURITY_DESCRIPTOR *buf, DWORD bufsize, DWORD *lengthNeeded) { #ifdef WITH_NTDLL @@ -377,7 +376,7 @@ win32_get_security_descriptor(HANDLE hFile, int add_flags) { SECURITY_INFORMATION requestedInformation; - u8 _buf[1]; + u8 _buf[4096]; u8 *buf; size_t bufsize; DWORD lenNeeded; @@ -393,7 +392,7 @@ win32_get_security_descriptor(HANDLE hFile, for (;;) { err = win32_query_security_descriptor(hFile, path, requestedInformation, - (PSECURITY_DESCRIPTOR)buf, + (SECURITY_DESCRIPTOR*)buf, bufsize, &lenNeeded); switch (err) { case ERROR_SUCCESS: @@ -422,7 +421,7 @@ win32_get_security_descriptor(HANDLE hFile, goto out_free_buf; default: fail: - errno = win32_error_to_errno(err); + set_errno_from_win32_error(err); ERROR("Failed to read security descriptor of \"%ls\"", path); ret = WIMLIB_ERR_READ; goto out_free_buf; @@ -490,8 +489,7 @@ win32_recurse_directory(HANDLE hDir, status == STATUS_NO_MORE_MATCHES) { ret = 0; } else { - errno = win32_error_to_errno( - RtlNtStatusToDosError(status)); + set_errno_from_nt_status(status); ERROR_WITH_ERRNO("Failed to read directory " "\"%ls\"", dir_path); ret = WIMLIB_ERR_READ; @@ -503,7 +501,7 @@ win32_recurse_directory(HANDLE hDir, for (;;) { if (!(info->FileNameLength == 2 && info->FileName[0] == L'.') && !(info->FileNameLength == 4 && info->FileName[0] == L'.' && - info->FileName[1] == L'.')) + info->FileName[1] == L'.')) { wchar_t *p; struct wim_dentry *child; @@ -550,7 +548,7 @@ out_free_buf: dir_path[dir_path_num_chars] = OS_PREFERRED_PATH_SEPARATOR; dir_path[dir_path_num_chars + 1] = L'*'; dir_path[dir_path_num_chars + 2] = L'\0'; - hFind = FindFirstFileW(dir_path, &dat); + hFind = FindFirstFile(dir_path, &dat); dir_path[dir_path_num_chars] = L'\0'; if (hFind == INVALID_HANDLE_VALUE) { @@ -558,8 +556,9 @@ out_free_buf: if (err == ERROR_FILE_NOT_FOUND) { return 0; } else { - ERROR("Failed to read directory \"%ls\"", dir_path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to read directory \"%ls\"", + dir_path); return WIMLIB_ERR_READ; } } @@ -591,11 +590,11 @@ out_free_buf: goto out_find_close; if (child) dentry_add_child(root, child); - } while (FindNextFileW(hFind, &dat)); + } while (FindNextFile(hFind, &dat)); err = GetLastError(); if (err != ERROR_NO_MORE_FILES) { - ERROR("Failed to read directory \"%ls\"", dir_path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to read directory \"%ls\"", dir_path); if (ret == 0) ret = WIMLIB_ERR_READ; } @@ -780,9 +779,8 @@ win32_get_reparse_data(HANDLE hFile, const wchar_t *path, &bytesReturned, NULL)) { - DWORD err = GetLastError(); - ERROR("Failed to get reparse data of \"%ls\"", path); - win32_error(err); + set_errno_from_GetLastError(); + ERROR_WITH_ERRNO("Failed to get reparse data of \"%ls\"", path); return -WIMLIB_ERR_READ; } if (bytesReturned < 8 || bytesReturned > REPARSE_POINT_MAX_SIZE) { @@ -810,10 +808,10 @@ win32_get_reparse_data(HANDLE hFile, const wchar_t *path, } static DWORD WINAPI -win32_tally_encrypted_size_cb(unsigned char *_data, void *_ctx, +win32_tally_encrypted_size_cb(unsigned char *_data, void *_size_ret, unsigned long len) { - *(u64*)_ctx += len; + *(u64*)_size_ret += len; return ERROR_SUCCESS; } @@ -824,18 +822,20 @@ win32_get_encrypted_file_size(const wchar_t *path, u64 *size_ret) void *file_ctx; int ret; - *size_ret = 0; - err = OpenEncryptedFileRawW(path, 0, &file_ctx); + err = OpenEncryptedFileRaw(path, 0, &file_ctx); if (err != ERROR_SUCCESS) { - ERROR("Failed to open encrypted file \"%ls\" for raw read", path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to open encrypted file \"%ls\" " + "for raw read", path); return WIMLIB_ERR_OPEN; } + *size_ret = 0; err = ReadEncryptedFileRaw(win32_tally_encrypted_size_cb, size_ret, file_ctx); if (err != ERROR_SUCCESS) { - ERROR("Failed to read raw encrypted data from \"%ls\"", path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to read raw encrypted data from " + "\"%ls\"", path); ret = WIMLIB_ERR_READ; } else { ret = 0; @@ -1002,7 +1002,7 @@ out_invalid_stream_name: * already present in Windows XP. */ static int -win32_capture_streams(HANDLE hFile, +win32_capture_streams(HANDLE *hFile_p, const wchar_t *path, size_t path_num_chars, struct wim_inode *inode, @@ -1039,7 +1039,7 @@ win32_capture_streams(HANDLE hFile, /* Get a buffer containing the stream information. */ for (;;) { - status = NtQueryInformationFile(hFile, &io_status, buf, bufsize, + status = NtQueryInformationFile(*hFile_p, &io_status, buf, bufsize, FileStreamInformation); if (status == STATUS_SUCCESS) { break; @@ -1058,7 +1058,7 @@ win32_capture_streams(HANDLE hFile, } buf = newbuf; } else { - errno = win32_error_to_errno(RtlNtStatusToDosError(status)); + set_errno_from_nt_status(status); ERROR_WITH_ERRNO("Failed to read streams of %ls", path); ret = WIMLIB_ERR_READ; goto out_free_buf; @@ -1071,6 +1071,14 @@ win32_capture_streams(HANDLE hFile, goto out_free_buf; } + if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) { + /* OpenEncryptedFileRaw() seems to fail with + * ERROR_SHARING_VIOLATION if there are any handles opened to + * the file. */ + CloseHandle(*hFile_p); + *hFile_p = INVALID_HANDLE_VALUE; + } + /* Parse one or more stream information structures. */ info = (const FILE_STREAM_INFORMATION*)buf; for (;;) { @@ -1122,9 +1130,9 @@ out_free_buf: path, capture_access_denied_msg); return 0; } else { - ERROR("Failed to look up data streams " - "of \"%ls\"", path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to look up data streams " + "of \"%ls\"", path); return WIMLIB_ERR_READ; } } @@ -1139,8 +1147,9 @@ out_free_buf: } while (win32func_FindNextStreamW(hFind, &dat)); err = GetLastError(); if (err != ERROR_HANDLE_EOF) { - ERROR("Win32 API: Error reading data streams from \"%ls\"", path); - win32_error(err); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Error reading data streams from " + "\"%ls\"", path); ret = WIMLIB_ERR_READ; } out_find_close: @@ -1149,7 +1158,7 @@ out_find_close: #endif /* !WITH_NTDLL */ unnamed_only: - /* FindFirstStreamW() API is not available, or the volume does not + /* FindFirstStream() API is not available, or the volume does not * support named streams. Only capture the unnamed data stream. */ DEBUG("Only capturing unnamed data stream"); if (!(inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY | @@ -1312,7 +1321,7 @@ again: /* Capture the unnamed data stream (only should be present for regular * files) and any alternate data streams. */ - ret = win32_capture_streams(hFile, + ret = win32_capture_streams(&hFile, path, path_num_chars, inode, @@ -1331,6 +1340,19 @@ again: params->lookup_table); } else if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) { /* Directory (not a reparse point) --- recurse to children */ + + if (hFile == INVALID_HANDLE_VALUE) { + /* Re-open handle that was closed to read raw encrypted + * data. */ + hFile = win32_open_existing_file(path, FILE_READ_DATA); + if (hFile == INVALID_HANDLE_VALUE) { + set_errno_from_GetLastError(); + ERROR_WITH_ERRNO("Failed to reopen \"%ls\"", + path); + ret = WIMLIB_ERR_OPEN; + goto out_close_handle; + } + } ret = win32_recurse_directory(hFile, path, path_num_chars, @@ -1400,19 +1422,13 @@ win32_build_dentry_tree(struct wim_dentry **root_ret, if (path_nchars > WINDOWS_NT_MAX_PATH) return WIMLIB_ERR_INVALID_PARAM; - if (GetFileAttributesW(root_disk_path) == INVALID_FILE_ATTRIBUTES && - GetLastError() == ERROR_FILE_NOT_FOUND) - { - ERROR("Capture directory \"%ls\" does not exist!", - root_disk_path); - return WIMLIB_ERR_OPENDIR; - } - ret = win32_get_file_and_vol_ids(root_disk_path, ¶ms->capture_root_ino, ¶ms->capture_root_dev); - if (ret) + if (ret) { + ERROR_WITH_ERRNO("Can't open %ls", root_disk_path); return ret; + } win32_get_vol_flags(root_disk_path, &vol_flags, NULL);