diff --git a/lib/zip_source_file_win32.h b/lib/zip_source_file_win32.h index f01232677..c1353aac4 100644 --- a/lib/zip_source_file_win32.h +++ b/lib/zip_source_file_win32.h @@ -59,6 +59,7 @@ struct zip_win32_file_operations { BOOL(__stdcall *move_file)(const void *from, const void *to, DWORD flags); BOOL(__stdcall *set_file_attributes)(const void *name, DWORD attributes); char *(*string_duplicate)(const char *string); + HANDLE(__stdcall *find_first_file)(const void *name, void *data); }; typedef struct zip_win32_file_operations zip_win32_file_operations_t; diff --git a/lib/zip_source_file_win32_ansi.c b/lib/zip_source_file_win32_ansi.c index dce75cd9a..6f4ae2bb2 100644 --- a/lib/zip_source_file_win32_ansi.c +++ b/lib/zip_source_file_win32_ansi.c @@ -41,6 +41,7 @@ static BOOL __stdcall ansi_get_file_attributes_ex(const void *name, GET_FILEEX_I static void ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); static BOOL __stdcall ansi_move_file(const void *from, const void *to, DWORD flags); static BOOL __stdcall ansi_set_file_attributes(const void *name, DWORD attributes); +static HANDLE __stdcall ansi_find_first_file(const void *name, void* data); /* clang-format off */ zip_win32_file_operations_t ops_ansi = { @@ -52,7 +53,8 @@ zip_win32_file_operations_t ops_ansi = { ansi_make_tempname, ansi_move_file, ansi_set_file_attributes, - strdup + strdup, + ansi_find_first_file, }; /* clang-format on */ @@ -122,3 +124,9 @@ ansi_set_file_attributes(const void *name, DWORD attributes) { return SetFileAttributesA((const char *)name, attributes); } + +static HANDLE __stdcall +ansi_find_first_file(const void *name, void *data) +{ + return FindFirstFileA((const char *)name, data); +} diff --git a/lib/zip_source_file_win32_named.c b/lib/zip_source_file_win32_named.c index a406d32f0..39e4a6d7f 100644 --- a/lib/zip_source_file_win32_named.c +++ b/lib/zip_source_file_win32_named.c @@ -221,8 +221,16 @@ _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t st->regular_file = false; if (file_attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { - if ((file_attributes.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) == 0) { - st->regular_file = true; + if ((file_attributes.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0) { + if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + WIN32_FIND_DATA find_data; + if (file_ops->find_first_file(ctx->fname, &find_data) != INVALID_HANDLE_VALUE) { + st->regular_file = (find_data.dwReserved0 == IO_REPARSE_TAG_DEDUP); + } + } + else { + st->regular_file = true; + } } } diff --git a/lib/zip_source_file_win32_utf16.c b/lib/zip_source_file_win32_utf16.c index 01767a13f..4b61562c9 100644 --- a/lib/zip_source_file_win32_utf16.c +++ b/lib/zip_source_file_win32_utf16.c @@ -42,6 +42,7 @@ static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uin static BOOL __stdcall utf16_move_file(const void *from, const void *to, DWORD flags); static BOOL __stdcall utf16_set_file_attributes(const void *name, DWORD attributes); static char *utf16_strdup(const char *string); +static HANDLE __stdcall utf16_find_first_file(const void *name, void* data); /* clang-format off */ @@ -54,7 +55,8 @@ zip_win32_file_operations_t ops_utf16 = { utf16_make_tempname, utf16_move_file, utf16_set_file_attributes, - utf16_strdup + utf16_strdup, + utf16_find_first_file }; /* clang-format on */ @@ -141,3 +143,10 @@ static char * utf16_strdup(const char *string) { return (char *)_wcsdup((const wchar_t *)string); } + + +static HANDLE __stdcall +utf16_find_first_file(const void *name, void* data) +{ + return FindFirstFileW((const wchar_t *)name, data); +}