ntdll: Correct filename-pattern behaviour

Costas Christofi christofi.cos at gmail.com
Thu Jan 5 04:42:36 CST 2012


Small fix for match_filename() in /dll/ntdll/directory.c, so the
matching complies with Windows behaviour.

This lets us match cases such as "foo123 -> *?" and "foo123 ->
f*??*?3". In the current version of Wine, both of these will
incorrectly return false, even though the patterns should normally
match (and do match under Windows).

Note that this patch provides a generic solution for the bug
identified in this thread on the MGE forums:
http://sourceforge.net/projects/morrgraphext/forums/forum/866295/topic/3832169

Costas
-------------- next part --------------
From 965a22c1f51ff47650df65b17f0a86913d4d14e2 Mon Sep 17 00:00:00 2001
From: Costas Christofi <christofi.cos at gmail.com>
Date: Thu, 5 Jan 2012 10:52:06 +0200
Subject: match_filename() now able to handle patterns of types
 "foo123 -> *?" and "foo123 -> f*??*?3",
 which are used in some Windows applications.

---
 dlls/ntdll/directory.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 65c8b8f..3fba4b7 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1170,6 +1170,7 @@ static ULONG hash_short_file_name( const UNICODE_STRING *name, LPWSTR buffer )
 static BOOLEAN match_filename( const UNICODE_STRING *name_str, const UNICODE_STRING *mask_str )
 {
     int mismatch;
+    int symnum, charnum;
     const WCHAR *name = name_str->Buffer;
     const WCHAR *mask = mask_str->Buffer;
     const WCHAR *name_end = name + name_str->Length / sizeof(WCHAR);
@@ -1189,11 +1190,23 @@ static BOOLEAN match_filename( const UNICODE_STRING *name_str, const UNICODE_STR
             if (mask == mask_end) return TRUE; /* end of mask is all '*', so match */
             lastjoker = mask;
 
-            /* skip to the next match after the joker(s) */
+            /* skip a sequence of mixed '?'s and '*'s, but keep count of the '?'s */
+            symnum = 0, charnum = 0;
+            while (mask < mask_end && (*mask == '?' || *mask == '*'))
+            {
+                if (*mask == '?') symnum++;
+                mask++;
+            }
+
+            /* skip to the next match after the joker(s), and count chars skipped */
             if (is_case_sensitive)
-                while (name < name_end && (*name != *mask)) name++;
+                while (name < name_end && (*name != *mask)) { name++; charnum++; }
             else
-                while (name < name_end && (toupperW(*name) != toupperW(*mask))) name++;
+                while (name < name_end && (toupperW(*name) != toupperW(*mask))) { name++; charnum++; }
+
+            /* ensure that enough chars were skipped to satisfy the '?'s */
+            if (symnum > charnum) return FALSE;
+
             next_to_retry = name;
             break;
         case '?':
-- 
1.7.4.1


More information about the wine-patches mailing list