Use GetFileAttributesExA/W instead of opening file.
diff --git a/lib/zip_source_file_win32.c b/lib/zip_source_file_win32.c
index 4a46e96..8e59357 100644
--- a/lib/zip_source_file_win32.c
+++ b/lib/zip_source_file_win32.c
@@ -35,7 +35,7 @@
 
 static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
 
-static int _zip_filetime_to_time_t(FILETIME ft, time_t *t);
+static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h);
 
 static zip_source_file_operations_t ops_win32_read = {
     _zip_win32_op_close,
@@ -183,7 +183,7 @@
 }
 
 
-bool
+static bool
 _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h) {
     FILETIME mtimeft;
     time_t mtime;
@@ -218,7 +218,7 @@
 }
 
 
-static int
+bool
 _zip_filetime_to_time_t(FILETIME ft, time_t *t) {
     /*
     Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux
diff --git a/lib/zip_source_file_win32.h b/lib/zip_source_file_win32.h
index 0097afd..78c77ad 100644
--- a/lib/zip_source_file_win32.h
+++ b/lib/zip_source_file_win32.h
@@ -52,6 +52,7 @@
     HANDLE (*create_file)(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
     BOOL (*delete_file)(const char *name);
     DWORD (*get_file_attributes)(const char *name);
+    BOOL (*get_file_attributes_ex)(const char *name, GET_FILEEX_INFO_LEVELS info_level, void *information);
     void (*make_tempname)(char *buf, size_t len, const char *name, int i);
     BOOL (*move_file)(const char *from, const char *to, DWORD flags);
     BOOL (*set_file_attributes)(const char *name, DWORD attributes);
@@ -68,7 +69,7 @@
 zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f);
 zip_int64_t _zip_win32_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len);
 
-bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h);
+bool _zip_filetime_to_time_t(FILETIME ft, time_t *t);
 int _zip_win32_error_to_errno(DWORD win32err);
 
 #endif /* _HAD_ZIP_SOURCE_FILE_WIN32_H */
diff --git a/lib/zip_source_file_win32_ansi.c b/lib/zip_source_file_win32_ansi.c
index 0909519..0d2568c 100644
--- a/lib/zip_source_file_win32_ansi.c
+++ b/lib/zip_source_file_win32_ansi.c
@@ -41,6 +41,7 @@
     CreateFileA,
     DeleteFileA,
     GetFileAttributesA,
+    GetFileAttributesExA,
     ansi_make_tempname,
     MoveFileExA,
     SetFileAttributesA,
diff --git a/lib/zip_source_file_win32_utf16.c b/lib/zip_source_file_win32_utf16.c
index 8263ac9..97b7a8e 100644
--- a/lib/zip_source_file_win32_utf16.c
+++ b/lib/zip_source_file_win32_utf16.c
@@ -37,6 +37,7 @@
 static HANDLE utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file);
 static BOOL utf16_delete_file(const char *name);
 static DWORD utf16_get_file_attributes(const char *name);
+static BOOL utf16_get_file_attributes(const char *name, GET_FILEEX_INFO_LEVELS info_level, void *information);
 static void utf16_make_tempname(char *buf, size_t len, const char *name, int i);
 static BOOL utf16_move_file(const char *from, const char *to, DWORD flags);
 static BOOL utf16_set_file_attributes(const char *name, DWORD attributes);
@@ -47,6 +48,7 @@
     utf16_create_file,
     utf16_delete_file,
     utf16_get_file_attributes,
+    utf16_get_file_attributes_ex,
     utf16_make_tempname,
     utf16_move_file,
     utf16_set_file_attributes,
@@ -94,7 +96,7 @@
     
     return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams);
 #else
-    wprintf(L"CreateFileW(\"%s\", %x, %x, %x, %p, %x)\n", (const wchar_t *)name, access, share_mode, creation_disposition, security_attributes, file_attributes);
+    // wprintf(L"CreateFileW(\"%s\", %x, %x, %x, %p, %x)\n", (const wchar_t *)name, access, share_mode, creation_disposition, security_attributes, file_attributes);
     return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file);
 #endif
 }
@@ -112,6 +114,13 @@
 }
 
 
+static BOOL
+utf16_get_file_attributes(const char *name, GET_FILEEX_INFO_LEVELS info_level, void *information) {
+    return GetFeilAttributesExW((const wchar_t *)name, info_level, information);
+}
+
+
+
 static void
 utf16_make_tempname(char *buf, size_t len, const char *name, int i) {
     _snwprintf((wchar_t *)buf, len, L"%s.%08x", (const wchar_t *)name, i);
diff --git a/lib/zip_source_file_win32_write.c b/lib/zip_source_file_win32_write.c
index dfcf1ad..300c84c 100644
--- a/lib/zip_source_file_win32_write.c
+++ b/lib/zip_source_file_win32_write.c
@@ -193,19 +193,25 @@
 
 static bool
 _zip_win32_write_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) {
-    HANDLE h = win32_write_open(ctx, ctx->fname, false, NULL);
-    bool ok;
+    zip_source_file_win32_write_operations_t *write_ops = (zip_source_file_win32_write_operations_t *)ctx->ops_userdata;
     
-    if (h == INVALID_HANDLE_VALUE) {
-        printf("open in stat failed\n");
+    WIN32_FILE_ATTRIBUTE_DATA file_attributes;
+
+    if (!write_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) {
+        zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
         return false;
     }
-
-    ok = _zip_stat_win32(ctx, st, h);
     
-    // CloseHandle(h);
+    st->exists = true;
+    st->regular_file = true; /* TODO: Is this always right? How to determine without a HANDLE? */
+    if (!_zip_filetime_to_time_t(file_attributes->ftLastWriteTime, &st->mtime)) {
+        printf("filetime_to_time_t failed\n");
+        zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
+        return false;
+    }
+    st->size = ((zip_uint64_t)file_attributes->nFileSizeHigh << 32) | file_attributes->nFileSizeLow;
     
-    return ok;
+    return true;
 }