- char *utf8_name;
- size_t utf8_name_nbytes;
- ret = utf16_to_utf8((const char*)dat.cFileName,
- wcslen(dat.cFileName) * sizeof(wchar_t),
- &utf8_name,
- &utf8_name_nbytes);
- if (ret)
- goto out_find_close;
-
- char name[strlen(root_disk_path) + utf8_name_nbytes + 1];
- sprintf(name, "%s/%s", root_disk_path, utf8_name);
- FREE(utf8_name);
- ret = build_dentry_tree(&child, name, lookup_table,
- sd, config, add_image_flags,
- progress_func, sd_set);
- if (ret)
- goto out_find_close;
- if (child)
- dentry_add_child(root, child);
- }
- } while (FindNextFileW(hFind, &dat));
- err = GetLastError();
- if (err != ERROR_NO_MORE_FILES) {
- ERROR("Win32 API: Failed to read directory \"%s\"", root_disk_path);
- win32_error(err);
- if (ret == 0)
- ret = WIMLIB_ERR_READ;
- }
-out_find_close:
- FindClose(hFind);
- return ret;
-}
-
-static int win32_capture_reparse_point(const char *path,
- HANDLE hFile,
- struct wim_inode *inode,
- struct wim_lookup_table *lookup_table)
-{
- /* "Reparse point data, including the tag and optional GUID,
- * cannot exceed 16 kilobytes." - MSDN */
- char reparse_point_buf[16 * 1024];
- DWORD bytesReturned;
- const REPARSE_DATA_BUFFER *buf;
-
- if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT,
- NULL, 0, reparse_point_buf,
- sizeof(reparse_point_buf), &bytesReturned, NULL))
- {
- ERROR("Win32 API: Failed to get reparse data of \"%s\"", path);
- return WIMLIB_ERR_READ;
- }
- buf = (const REPARSE_DATA_BUFFER*)reparse_point_buf;
- inode->i_reparse_tag = buf->ReparseTag;
- return inode_add_ads_with_data(inode, "", (const u8*)buf + 8,
- bytesReturned - 8, lookup_table);
-}
-
-static int win32_sha1sum(const wchar_t *path, u8 hash[SHA1_HASH_SIZE])
-{
- HANDLE hFile;
- SHA_CTX ctx;
- u8 buf[32768];
- DWORD bytesRead;
- int ret;
-
- hFile = win32_open_file(path);
- if (hFile == INVALID_HANDLE_VALUE)
- return WIMLIB_ERR_OPEN;
-
- sha1_init(&ctx);
- for (;;) {
- if (!ReadFile(hFile, buf, sizeof(buf), &bytesRead, NULL)) {
- ret = WIMLIB_ERR_READ;
- goto out_close_handle;
- }
- if (bytesRead == 0)
- break;
- sha1_update(&ctx, buf, bytesRead);
- }
- ret = 0;
- sha1_final(hash, &ctx);
-out_close_handle:
- CloseHandle(hFile);
- return ret;
-}
-
-static int win32_capture_stream(const char *path,
- const wchar_t *path_utf16,
- size_t path_utf16_nchars,
- struct wim_inode *inode,
- struct wim_lookup_table *lookup_table,
- WIN32_FIND_STREAM_DATA *dat)
-{
- struct wim_ads_entry *ads_entry;
- u8 hash[SHA1_HASH_SIZE];
- struct wim_lookup_table_entry *lte;
- int ret;
- wchar_t *p, *colon;
- bool is_named_stream;
- wchar_t *spath;
- size_t spath_nchars;
- DWORD err;
-
- p = dat->cStreamName;
- wimlib_assert(*p == L':');
- p += 1;
- colon = wcschr(p, L':');
- wimlib_assert(colon != NULL);
-
- if (wcscmp(colon + 1, L"$DATA")) {
- /* Not a DATA stream */
- ret = 0;
- goto out;
- }
-
- is_named_stream = (p != colon);
-
- if (is_named_stream) {
- char *utf8_stream_name;
- size_t utf8_stream_name_len;
- ret = utf16_to_utf8((const char *)p,
- colon - p,
- &utf8_stream_name,
- &utf8_stream_name_len);
- if (ret)
- goto out;
- DEBUG_WIN32_SAFE("Add alternate data stream %s:%s", path, utf8_stream_name);
- ads_entry = inode_add_ads(inode, utf8_stream_name);
- FREE(utf8_stream_name);
- if (!ads_entry) {
- ret = WIMLIB_ERR_NOMEM;
- goto out;
- }
- }
-
- *colon = '\0';
- spath_nchars = path_utf16_nchars;
- if (is_named_stream)
- spath_nchars += colon - p + 1;
-
- spath = MALLOC((spath_nchars + 1) * sizeof(wchar_t));
- memcpy(spath, path_utf16, path_utf16_nchars * sizeof(wchar_t));
- if (is_named_stream) {
- spath[path_utf16_nchars] = L':';
- memcpy(&spath[path_utf16_nchars + 1], p, (colon - p) * sizeof(wchar_t));
- }
- spath[spath_nchars] = L'\0';
-
- ret = win32_sha1sum(spath, hash);
- if (ret) {
- err = GetLastError();
- ERROR("Win32 API: Failed to read \"%s\" to calculate SHA1sum", path);
- win32_error(err);
- goto out_free_spath;
- }
-
- lte = __lookup_resource(lookup_table, hash);
- if (lte) {
- lte->refcnt++;
- } else {
- lte = new_lookup_table_entry();
- if (!lte) {
- ret = WIMLIB_ERR_NOMEM;
- goto out_free_spath;
- }
- lte->file_on_disk = (char*)spath;
- spath = NULL;
- lte->resource_location = RESOURCE_WIN32;
- lte->resource_entry.original_size = (uint64_t)dat->StreamSize.QuadPart;
- lte->resource_entry.size = (uint64_t)dat->StreamSize.QuadPart;
- copy_hash(lte->hash, hash);
- lookup_table_insert(lookup_table, lte);
- }
- if (is_named_stream)
- ads_entry->lte = lte;
- else
- inode->i_lte = lte;
-out_free_spath:
- FREE(spath);
-out:
- return ret;
-}
-
-static int win32_capture_streams(const char *path,
- const wchar_t *path_utf16,
- size_t path_utf16_nchars,
- struct wim_inode *inode,
- struct wim_lookup_table *lookup_table)
-{
- WIN32_FIND_STREAM_DATA dat;
- int ret;
- HANDLE hFind;
- DWORD err;
-
- hFind = FindFirstStreamW(path_utf16, FindStreamInfoStandard, &dat, 0);
- if (hFind == INVALID_HANDLE_VALUE) {
- ERROR("Win32 API: Failed to look up data streams of \"%s\"",
- path);
- return WIMLIB_ERR_READ;
- }
- do {
- ret = win32_capture_stream(path, path_utf16,
- path_utf16_nchars,
- inode, lookup_table,
- &dat);
- if (ret)
- goto out_find_close;
- } while (FindNextStreamW(hFind, &dat));
- err = GetLastError();
- if (err != ERROR_HANDLE_EOF) {
- ERROR("Win32 API: Error reading data streams from \"%s\"", path);
- win32_error(err);
- ret = WIMLIB_ERR_READ;
- }
-out_find_close:
- FindClose(hFind);
- return ret;
-}
-#endif
-
-/*
- * build_dentry_tree():
- * Recursively builds a tree of WIM dentries from an on-disk directory
- * tree.
- *
- * @root_ret: Place to return a pointer to the root of the dentry tree. Only
- * modified if successful. Set to NULL if the file or directory was
- * excluded from capture.
- *
- * @root_disk_path: The path to the root of the directory tree on disk.
- *
- * @lookup_table: The lookup table for the WIM file. For each file added to the
- * dentry tree being built, an entry is added to the lookup table,
- * unless an identical stream is already in the lookup table.
- * These lookup table entries that are added point to the path of
- * the file on disk.
- *
- * @sd: Ignored. (Security data only captured in NTFS mode.)
- *
- * @capture_config:
- * Configuration for files to be excluded from capture.
- *
- * @add_flags: Bitwise or of WIMLIB_ADD_IMAGE_FLAG_*