Repository: facelessuser/wcmatch

Issue:
Consider using built-in drive splitting
Python provides `os.path.splitdrive` which splits a Windows drive and/or UNC mount. We technically already handle this, but we don't support extended UNC paths such as `//?/UNC/locahost/C$`. In this case, we would only count `//?/UNC/` as the "drive".

We can obviously increase our logic to account for this or just rely on built-in Python logic, which may be better for us as we don't have to maintain this portion.

Using `os.path.splitdrive` will only work on Windows systems though, so if you want to use `FORCEWIN` on a Unix system, you won't get the same logic. We basically have to use pathlib in this case:

```py
>>> p = pathlib.PureWindowsPath('//?/UNC/localhost/C$/test')
>>> p.drive
'\\\\?\\UNC\\localhost\\C$'
```

In general, this looks like the way we should go.  The whole reason we maintained our own was so we could handle Windows logic on Linux/Unix etc. But with `pathlib`, this is less of an issue.

Discussion:
facelessuser: We ended up not only adding UNC extended support, but also now allow escaping pattern expansion chars in Windows drive/mounts. This is kind of important if you want use `BRACE` and use a pattern that uses a Windows volume GUID `\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt`. You can also escape `|` as `SPLIT` uses though, but `|` is technically an invalid path variable on Windows anyways 🤷 .

While working on this, we reworked `escape` and `raw_escape` some to fix some corner cases related to Window's back slashes.
facelessuser: @gir-bot lgtm

Patch:
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 5ae4081..9258c45 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -2,12 +2,16 @@
 
 ## 6.1
 
+- **NEW**: Recognize extended UNC, such as: `//?/UNC/server/mount`, `//?/UNC/c:`, etc.
+- **NEW**: Allow escaping `{`, `}` and `|` in Windows drives for better compatibility with `SPLIT` and `BRACE`.
+- **NEW**: `raw_escape` now accepts the `raw_chars` parameter so that translation of Python raw escapes can be disabled.
 - **NEW**: `EXTMATCH`/`EXTGLOB` can now be used with `NEGATE` without needing `MINUSNEGATE`. If a pattern starts with
   `!(`, and `NEGATE` and `EXTMATCH`/`EXTGLOB` are both enabled, the pattern will not be treated as a `NEGATE` pattern
   (even if `!(` doesn't yield a valid `EXTGLOB` pattern). To negate a pattern that starts with a literal `(`, you must
   escape the bracket: `!\(`.
 - **FIX**: Support Python 3.9.
 - **FIX**: Adjust pattern limit logic of `glob` to be consistent with other functions.
+- **BUG**: Fix corner cases with `escape` and `raw_escape` with back slashes.
 
 ## 6.0.3
 
diff --git a/docs/src/markdown/glob.md b/docs/src/markdown/glob.md
index 726091d..3b92ebb 100644
--- a/docs/src/markdown/glob.md
+++ b/docs/src/markdown/glob.md
@@ -45,7 +45,9 @@ Pattern           | Meaning
 - Windows drives are recognized as either `C:/` and `//Server/mount/`. If a path uses an ambiguous root (`/some/path`),
   the system will assume the drive of the current working directory.
 
-- Meta characters have no effect when inside a UNC path: `//Server?/mount*/`.
+- Meta characters have no effect when inside a UNC path: `//Server?/mount*/`. The one exception is pattern expansion
+  characters like `{}` which are used by [brace expansion](#globbrace) and `|` used by [pattern splitting](#globsplit).
+  Pattern expansion characters are the only characters that can be escaped in a Windows drive/mount.
 
 - If [`FORCEUNIX`](#globforceunix) is applied on a Windows system, match and filter commands that do not touch the file
   system will **not** have slashes normalized. In addition, drive letters will also not be handled. Essentially, paths
@@ -421,8 +423,9 @@ def escape(pattern, unix=None):
 ```
 
 This escapes special glob meta characters so they will be treated as literal characters.  It escapes using backslashes.
-It will escape `-`, `!`, `*`, `?`, `(`, `[`, `|`, `^`, `{`, and `\`. On Windows, it will specifically only escape `\`
-when not already escaped (`\\`). `/` and `\\` (on Windows) are not escaped as they are path separators.
+It will escape `-`, `!`, `*`, `?`, `(`, `)`, `[`, `]`, `|`, `^`, `{`, `}`, and `\`. It is made to handle normal strings.
+If for some reason you wish to use raw strings (`r'raw/string'`), it is recommended that you use
+[`raw_escape`](#globraw_escape).
 
 ```pycon3
 >>> from wcmatch import glob
@@ -432,40 +435,81 @@ when not already escaped (`\\`). `/` and `\\` (on Windows) are not escaped as th
 True
 ```
 
-On a Windows system, drives are not escaped since meta characters are not parsed in drives. Drives on Windows are
-generally treated special. This is because a drive could contain special characters like in `\\?\c:\`.
+Can also be handle Windows style with `/` or `\\` path separators:
+
+```pycon3
+>>> from wmcatch import glob
+>>> glob.escape('some\\path?\\**file**{}.txt')
+'some\\\\path\\?\\\\\\*\\*file\\*\\*\\{\\}.txt'
+>>> glob.globmatch('some\\path?\\**file**{}.txt', glob.escape('some\\path?\\**file**{}.txt'))
+True
+```
+
+On a Windows system, drives only allow escaping `{`, `}`, and `|` for support with [`BRACE`](#globbrace) and/or
+[`SPLIT`](#globsplit). This is because characters (except for pattern expansion characters) are not parsed in drives.
+Drives on Windows are generally treated special.
+
+```pycon3
+>>> from wmcatch import glob
+>>> glob.escape('//./Volume{b75e2c83-0000-0000-0000-602f00000000}\Test\Foo.txt', unix=False)
+'//./Volume\\{b75e2c83-0000-0000-0000-602f00000000\\}\\\\Test\\\\Foo.txt'
+```
 
 `escape` will detect the system it is running on and pick Windows escape logic or Linux/Unix logic. Since
-[`globmatch`](#globglobmatch) allows you to match Unix style paths on a Windows system, and vice versa. You can force
+[`globmatch`](#globglobmatch) allows you to match Unix style paths on a Windows system and vice versa, You can force
 Unix style escaping or Windows style escaping via the `unix` parameter. When `unix` is `None`, the escape style will be
 detected, when `unix` is `True` Linux/Unix style escaping will be used, and when `unix` is `False` Windows style
 escaping will be used.
 
 ```pycon3
->>> glob.escape('some/path?/**file**{}.txt', platform=glob.UNIX)
+>>> glob.escape('some/path?/**file**{}.txt', unix=True)
 ```
 
 !!! new "New 5.0"
     The `unix` parameter is now `None` by default. Set to `True` to force Linux/Unix style escaping or set to `False` to
     force Windows style escaping.
 
+!!! new "New 7.0"
+    `{`, `}`, and `|` will be escaped in Windows drives. Additionally, users can escape these characters in Windows
+    drives manually in their match patterns as well.
+
 #### `glob.raw_escape`
 
 ```py3
-def raw_escape(pattern, unix=None):
+def raw_escape(pattern, unix=None, raw_chars=True):
 ```
 
-This is like [`escape`](#globescape) except it will apply raw character string escapes before doing meta character
-escapes.  This is meant for use with the [`RAWCHARS`](#globrawchars) flag.
+This is like [`escape`](#globescape) except it will escape paths provided as raw strings. Raw strings will be treated
+like a normal python string and handle Python specific escapes as well. This is good if you have an interface that
+provides strings in this form (maybe from a GUI or otherwise). You can disable the Python specific escapes by setting
+`raw_chars` to `False`. `raw_chars` is meant to be used when the [`RAWCHARS`](#globrawchars) flag is also set.
 
 ```pycon3
 >>> from wcmatch import glob
 >>> glob.raw_escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt')
 'some/path\\?/\\*\\*file\\*\\*\\{}.txt'
->>> glob.globmatch('some/path?/**file**{}.txt', glob.escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt'), flags=glob.RAWCHARS)
+>>> glob.globmatch('some/path?/**file**{}.txt', glob.raw_escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt'), flags=glob.RAWCHARS)
+True
+```
+
+Can also be handle Windows style with `/` or `\\` path separators:
+
+```pycon3
+>>> from wcmatch import glob
+>>> glob.raw_escape(r'some\\path?\\\x2a\x2afile\x2a\x2a{}.txt', unix=False)
+'some\\\\path\\?\\\\\\*\\*file\\*\\*\\{\\}.txt'
+>>> glob.globmatch('some\\path?\\**file**{}.txt', glob.raw_escape(r'some\\path?\\\x2a\x2afile\x2a\x2a{}.txt', unix=False), flags=glob.RAWCHARS)
 True
 ```
 
+When disabling `raw_chars`, Python style escapes will no longer be evaluated:
+
+```pycon3
+>>> from wcmatch import glob
+>>> glob.raw_escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt', raw_chars=False)
+'some/path\\?/\\\\x2a\\\\x2afile\\\\x2a\\\\x2a\\{\\}.txt'
+```
+
 `raw_escape` will detect the system it is running on and pick Windows escape logic or Linux/Unix logic. Since
 [`globmatch`](#globglobmatch) allows you to match Unix style paths on a Windows system, and vice versa. You can force
 Unix style escaping or Windows style escaping via the `unix` parameter. When `unix` is `None`, the escape style will be
@@ -473,13 +517,19 @@ detected, when `unix` is `True` Linux/Unix style escaping will be used, and when
 escaping will be used.
 
 ```pycon3
->>> glob.raw_escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt', platform=glob.UNIX)
+>>> glob.raw_escape(r'some/path?/\x2a\x2afile\x2a\x2a{}.txt')
 ```
 
 !!! new "New 5.0"
     The `unix` parameter is now `None` by default. Set to `True` to force Linux/Unix style escaping or set to `False` to
     force Windows style escaping.
 
+!!! new "New 7.0"
+    `{`, `}`, and `|` will be escaped in Windows drives. Additionally, users can escape these characters in Windows
+    drives manually in their match patterns as well.
+
+    `raw_chars` option was added.
+
 ## Flags
 
 #### `glob.CASE, glob.C` {: #globcase}
diff --git a/wcmatch/_wcparse.py b/wcmatch/_wcparse.py
index d988126..9d47ca8 100644
--- a/wcmatch/_wcparse.py
+++ b/wcmatch/_wcparse.py
@@ -34,18 +34,84 @@ BYTES = 1
 
 PATTERN_LIMIT = 1000
 
-RE_WIN_PATH = (
-    re.compile(r'((?:\\\\|/){2}[^\\/]+(?:\\\\|/){1}[^\\/]+|[a-z]:)((?:\\\\|/){1}|$)', re.I),
-    re.compile(br'((?:\\\\|/){2}[^\\/]+(?:\\\\|/){1}[^\\/]+|[a-z]:)((?:\\\\|/){1}|$)', re.I)
+RE_WIN_DRIVE_ESCAPED = (
+    re.compile(
+        r'''(?x)
+        (
+            (?:\\\\|/){2}[?.](?:\\\\|/)(?:
+                [a-z]:|
+                unc(?:(?:\\\\|/)(?:\\[{}|]|[^\\/])+){2} |
+                (?:global(?:\\\\|/))+(?:[a-z]:|unc(?:(?:\\\\|/)(?:\\[{}|]|[^\\/])+){2}|[^\\/]+)
+            ) |
+            (?:\\\\|/){2}(?:\\[{}|]|[^\\/])+(?:\\\\|/)(?:\\[{}|]|[^\\/])+|
+            [a-z]:
+        )((?:\\\\|/){1}|$)
+        ''',
+        re.I
+    ),
+    re.compile(
+        br'''(?x)
+        (
+            (?:\\\\|/){2}[?.](?:\\\\|/)(?:
+                [a-z]:|
+                unc(?:(?:\\\\|/)(?:\\[{}|]|[^\\/])+){2} |
+                (?:global(?:\\\\|/))+(?:[a-z]:|unc(?:(?:\\\\|/)(?:\\[{}|]|[^\\/])+){2}|[^\\/]+)
+            ) |
+            (?:\\\\|/){2}(?:\\[{}|]|[^\\/])+(?:\\\\|/)(?:\\[{}|]|[^\\/])+|
+            [a-z]:
+        )((?:\\\\|/){1}|$)
+        ''',
+        re.I
+    )
+)
+
+RE_WIN_DRIVE = (
+    re.compile(
+        r'''(?x)
+        (
+            (?:\\\\|/){2}[?.](?:\\\\|/)(?:
+                [a-z]:|
+                unc(?:(?:\\\\|/)[^\\/]+){2} |
+                (?:global(?:\\\\|/))+(?:[a-z]:|unc(?:(?:\\\\|/)[^\\/]+){2}|[^\\/]+)
+            ) |
+            (?:\\\\|/){2}[^\\/]+(?:\\\\|/)[^\\/]+|
+            [a-z]:
+        )((?:\\\\|/){1}|$)
+        ''',
+        re.I
+    ),
+    re.compile(
+        br'''(?x)
+        (
+            (?:\\\\|/){2}[?.](?:\\\\|/)(?:
+                [a-z]:|
+                unc(?:(?:\\\\|/)[^\\/]+){2} |
+                (?:global(?:\\\\|/))+(?:[a-z]:|unc(?:(?:\\\\|/)[^\\/]+){2}|[^\\/]+)
+            ) |
+            (?:\\\\|/){2}[^\\/]+(?:\\\\|/)[^\\/]+|
+            [a-z]:
+        )((?:\\\\|/){1}|$)
+        ''',
+        re.I
+    )
 )
-RE_WIN_MAGIC = (
-    re.compile(r'([-!~*?(\[|^{]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))'),
-    re.compile(br'([-!~*?(\[|^{]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))')
+
+RE_WIN_DRIVE_UNESCAPE = (
+    re.compile(r'\\([\\{}|])'),
+    re.compile(br'\\([\\{}|])')
+)
+RE_MAGIC_ESCAPE = (
+    re.compile(r'([-!~*?()\[\]|^{}]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))'),
+    re.compile(br'([-!~*?()\[\]|^{}]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))')
 )
 RE_MAGIC = (
     re.compile(r'([-!~*?(\[|^{\\])'),
     re.compile(br'([-!~*?(\[|^{\\])')
 )
+RE_WIN_DRIVE_MAGIC = (
+    re.compile(r'([{}|]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))'),
+    re.compile(br'([{}|]|(?<!\\)(?:(?:[\\]{2})*)\\(?!\\))')
+)
 RE_WIN_MOUNT = (
     re.compile(r'\\|[a-z]:(?:\\|$)', re.I),
     re.compile(br'\\|[a-z]:(?:\\|$)', re.I)
@@ -233,32 +299,54 @@ class PatternLimitException(Exception):
     """Pattern limit exception."""
 
 
-def raw_escape(pattern, unix=None):
+def raw_escape(pattern, unix=None, raw_chars=True):
     """Apply raw character transform before applying escape."""
 
-    pattern = util.norm_pattern(pattern, False, True)
-    return escape(pattern, unix)
+    return _escape(util.norm_pattern(pattern, False, raw_chars), unix, True)
 
 
 def escape(pattern, unix=None):
+    """Normal escape."""
+
+    return _escape(pattern, unix)
+
+
+def _escape(pattern, unix=None, raw=False):
     """Escape."""
 
-    is_bytes = isinstance(pattern, bytes)
-    ptype = BYTES if is_bytes else UNICODE
-    replace = br'\\\1' if is_bytes else r'\\\1'
-    win = ((unix is None and util.platform() == "windows") or unix is False)
-    magic = RE_WIN_MAGIC[ptype] if win else RE_MAGIC[ptype]
+    if isinstance(pattern, bytes):
+        drive_pat = RE_WIN_DRIVE[BYTES]
+        magic = RE_MAGIC_ESCAPE[BYTES]
+        drive_magic = RE_WIN_DRIVE_MAGIC[BYTES]
+        replace = br'\\\1'
+        slash = b'\\'
+        double_slash = b'\\\\'
+        drive = b''
+    else:
+        drive_pat = RE_WIN_DRIVE[UNICODE]
+        magic = RE_MAGIC_ESCAPE[UNICODE]
+        drive_magic = RE_WIN_DRIVE_MAGIC[UNICODE]
+        replace = r'\\\1'
+        slash = '\\'
+        double_slash = '\\\\'
+        drive = ''
+
+    if not raw:
+        pattern = pattern.replace(slash, double_slash)
 
     # Handle windows drives special.
     # Windows drives are handled special internally.
     # So we shouldn't escape them as we'll just have to
     # detect and undo it later.
-    drive = b'' if is_bytes else ''
-    if win:
-        m = RE_WIN_PATH[ptype].match(pattern)
+    length = 0
+    if ((unix is None and util.platform() == "windows") or unix is False):
+        m = drive_pat.match(pattern)
         if m:
+            # Replace splitting magic chars
             drive = m.group(0)
-    pattern = pattern[len(drive):]
+            length = len(drive)
+            drive = drive_magic.sub(replace, m.group(0))
+    pattern = pattern[length:]
 
     return drive + magic.sub(replace, pattern)
 
@@ -655,9 +743,9 @@ class WcPathSplit(object):
 
         # Detect and store away windows drive as a literal
         if self.win_drive_detect:
-            m = RE_WIN_PATH[UNICODE].match(pattern)
+            m = RE_WIN_DRIVE_ESCAPED[UNICODE].match(pattern)
             if m:
-                drive = m.group(0).replace('\\\\', '\\')
+                drive = RE_WIN_DRIVE_UNESCAPE[UNICODE].sub(r'\1', m.group(0))
                 if self.is_bytes:
                     drive = drive.encode('latin-1')
                 parts.append(WcGlob(drive, False, False, True, True))
@@ -1402,9 +1490,9 @@ class WcParse(object):
         iter(i)
         root_specified = False
         if self.win_drive_detect:
-            m = RE_WIN_PATH[UNICODE].match(pattern)
+            m = RE_WIN_DRIVE_ESCAPED[UNICODE].match(pattern)
             if m:
-                drive = m.group(0).replace('\\\\', '\\')
+                drive = RE_WIN_DRIVE_UNESCAPE[UNICODE].sub(r'\1', m.group(0))
                 if drive.endswith('\\'):
                     slash = True
                 drive = drive[:-1]
diff --git a/wcmatch/glob.py b/wcmatch/glob.py
index 0b50ae1..169e5f4 100644
--- a/wcmatch/glob.py
+++ b/wcmatch/glob.py
@@ -572,10 +572,10 @@ def globfilter(filenames, patterns, *, flags=0, root_dir=None, limit=_wcparse.PA
     return matches
 
 
-def raw_escape(pattern, unix=None):
+def raw_escape(pattern, unix=None, raw_chars=True):
     """Apply raw character transform before applying escape."""
 
-    return _wcparse.raw_escape(pattern, unix)
+    return _wcparse.raw_escape(pattern, unix, raw_chars)
 
 
 def escape(pattern, unix=None):


Test patch:
diff --git a/tests/test_glob.py b/tests/test_glob.py
index db15534..1d9750e 100644
--- a/tests/test_glob.py
+++ b/tests/test_glob.py
@@ -1039,15 +1039,36 @@ class TestGlobCornerCaseMarked(Testglob):
 class TestGlobEscapes(unittest.TestCase):
     """Test escaping."""
 
-    def check_escape(self, arg, expected, raw=False, unix=None):
+    def check_escape(self, arg, expected, raw=False, unix=None, raw_chars=True):
         """Verify escapes."""
 
+        flags = 0
+        if unix is False:
+            flags = glob.FORCEWIN
+        elif unix is True:
+            flags = glob.FORCEUNIX
+
         if raw:
-            self.assertEqual(glob.raw_escape(arg, unix=unix), expected)
-            self.assertEqual(glob.raw_escape(os.fsencode(arg), unix=unix), os.fsencode(expected))
+            self.assertEqual(glob.raw_escape(arg, unix=unix, raw_chars=raw_chars), expected)
+            self.assertEqual(glob.raw_escape(os.fsencode(arg), unix=unix, raw_chars=raw_chars), os.fsencode(expected))
+            file = (util.norm_pattern(arg, False, True) if raw_chars else arg).replace('\\\\', '\\')
+            self.assertTrue(
+                glob.globmatch(
+                    file,
+                    glob.raw_escape(arg, unix=unix, raw_chars=raw_chars),
+                    flags=flags
+                )
+            )
         else:
             self.assertEqual(glob.escape(arg, unix=unix), expected)
             self.assertEqual(glob.escape(os.fsencode(arg), unix=unix), os.fsencode(expected))
+            self.assertTrue(
+                glob.globmatch(
+                    arg,
+                    glob.escape(arg, unix=unix),
+                    flags=flags
+                )
+            )
 
     def test_escape(self):
         """Test path escapes."""
@@ -1057,20 +1078,36 @@ class TestGlobEscapes(unittest.TestCase):
         check('[', r'\[')
         check('?', r'\?')
         check('*', r'\*')
-        check('[[_/*?*/_]]', r'\[\[_/\*\?\*/_]]')
-        check('/[[_/*?*/_]]/', r'/\[\[_/\*\?\*/_]]/')
+        check('[[_/*?*/_]]', r'\[\[_/\*\?\*/_\]\]')
+        check('/[[_/*?*/_]]/', r'/\[\[_/\*\?\*/_\]\]/')
 
     def test_raw_escape(self):
         """Test path escapes."""
 
         check = self.check_escape
-        check('abc', 'abc', raw=True)
-        check('[', r'\[', raw=True)
-        check('?', r'\?', raw=True)
-        check('*', r'\*', raw=True)
-        check('[[_/*?*/_]]', r'\[\[_/\*\?\*/_]]', raw=True)
-        check('/[[_/*?*/_]]/', r'/\[\[_/\*\?\*/_]]/', raw=True)
+        check(r'abc', 'abc', raw=True)
+        check(r'[', r'\[', raw=True)
+        check(r'?', r'\?', raw=True)
+        check(r'*', r'\*', raw=True)
+        check(r'[[_/*?*/_]]', r'\[\[_/\*\?\*/_\]\]', raw=True)
+        check(r'/[[_/*?*/_]]/', r'/\[\[_/\*\?\*/_\]\]/', raw=True)
         check(r'\x3f', r'\?', raw=True)
+        check(r'\\\\[^what]\\name\\temp', r'\\\\[^what]\\name\\temp', raw=True, unix=False)
+        check('//[^what]/name/temp', r'//[^what]/name/temp', raw=True, unix=False)
+
+    def test_raw_escape_no_raw_chars(self):
+        """Test path escapes with no raw character translations."""
+
+        check = self.check_escape
+        check(r'abc', 'abc', raw=True, raw_chars=False)
+        check(r'[', r'\[', raw=True, raw_chars=False)
+        check(r'?', r'\?', raw=True, raw_chars=False)
+        check(r'*', r'\*', raw=True, raw_chars=False)
+        check(r'[[_/*?*/_]]', r'\[\[_/\*\?\*/_\]\]', raw=True, raw_chars=False)
+        check(r'/[[_/*?*/_]]/', r'/\[\[_/\*\?\*/_\]\]/', raw=True, raw_chars=False)
+        check(r'\x3f', r'\\x3f', raw=True, raw_chars=False)
+        check(r'\\\\[^what]\\name\\temp', r'\\\\[^what]\\name\\temp', raw=True, raw_chars=False, unix=False)
+        check('//[^what]/name/temp', r'//[^what]/name/temp', raw=True, raw_chars=False, unix=False)
 
     @unittest.skipUnless(sys.platform.startswith('win'), "Windows specific test")
     def test_escape_windows(self):
@@ -1079,10 +1116,11 @@ class TestGlobEscapes(unittest.TestCase):
         check = self.check_escape
         check('a:\\?', r'a:\\\?')
         check('b:\\*', r'b:\\\*')
-        check(r'\\\\?\\c:\\?', r'\\\\?\\c:\\\?')
-        check(r'\\\\*\\*\\*', r'\\\\*\\*\\\*')
+        check('\\\\?\\c:\\?', r'\\\\?\\c:\\\?')
+        check('\\\\*\\*\\*', r'\\\\*\\*\\\*')
         check('//?/c:/?', r'//?/c:/\?')
         check('//*/*/*', r'//*/*/\*')
+        check('//[^what]/name/temp', r'//[^what]/name/temp')
 
     def test_escape_forced_windows(self):
         """Test forced windows escapes."""
@@ -1090,10 +1128,16 @@ class TestGlobEscapes(unittest.TestCase):
         check = self.check_escape
         check('a:\\?', r'a:\\\?', unix=False)
         check('b:\\*', r'b:\\\*', unix=False)
-        check(r'\\\\?\\c:\\?', r'\\\\?\\c:\\\?', unix=False)
-        check(r'\\\\*\\*\\*', r'\\\\*\\*\\\*', unix=False)
+        check('\\\\?\\c:\\?', r'\\\\?\\c:\\\?', unix=False)
+        check('\\\\*\\*\\*', r'\\\\*\\*\\\*', unix=False)
         check('//?/c:/?', r'//?/c:/\?', unix=False)
         check('//*/*/*', r'//*/*/\*', unix=False)
+        check(
+            '//./Volume{b75e2c83-0000-0000-0000-602f00000000}/temp',
+            r'//./Volume\{b75e2c83-0000-0000-0000-602f00000000\}/temp',
+            unix=False
+        )
+        check('//[^what]/name/temp', r'//[^what]/name/temp', unix=False)
 
     def test_escape_forced_unix(self):
         """Test forced windows Unix."""
@@ -1101,10 +1145,11 @@ class TestGlobEscapes(unittest.TestCase):
         check = self.check_escape
         check('a:\\?', r'a:\\\?', unix=True)
         check('b:\\*', r'b:\\\*', unix=True)
-        check(r'\\\\?\\c:\\?', r'\\\\\\\\\?\\\\c:\\\\\?', unix=True)
-        check(r'\\\\*\\*\\*', r'\\\\\\\\\*\\\\\*\\\\\*', unix=True)
+        check('\\\\?\\c:\\?', r'\\\\\?\\c:\\\?', unix=True)
+        check('\\\\*\\*\\*', r'\\\\\*\\\*\\\*', unix=True)
         check('//?/c:/?', r'//\?/c:/\?', unix=True)
         check('//*/*/*', r'//\*/\*/\*', unix=True)
+        check('//[^what]/name/temp', r'//\[\^what\]/name/temp', unix=True)
 
 
 @unittest.skipUnless(sys.platform.startswith('win'), "Windows specific test")
diff --git a/tests/test_wcparse.py b/tests/test_wcparse.py
index 2c17e0e..e037737 100644
--- a/tests/test_wcparse.py
+++ b/tests/test_wcparse.py
@@ -110,3 +110,23 @@ class TestWcparse(unittest.TestCase):
         """Test that tilde position gives 1 when tilde is found and `NEGATE` is enabled."""
 
         self.assertEqual(_wcparse.tilde_pos('!~pattern', _wcparse.GLOBTILDE | _wcparse.REALPATH | _wcparse.NEGATE), 1)
+
+    def test_unc_pattern(self):
+        """Test UNC pattern."""
+
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/UNC/server/mount').group(0), '//?/UNC/server/mount')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/UNC/server/mount/').group(0), '//?/UNC/server/mount/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/UNC/server/mount/path').group(0), '//?/UNC/server/mount/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//./UNC/server/mount/path').group(0), '//./UNC/server/mount/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/UNC/c:').group(0), '//?/UNC/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/UNC/c:/').group(0), '//?/UNC/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/c:').group(0), '//?/c:')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/c:/').group(0), '//?/c:/')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//?/what').group(0), '//?/what')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//server/mount').group(0), '//server/mount')
+        self.assertEqual(_wcparse.RE_WIN_DRIVE[0].match('//server/mount/').group(0), '//server/mount/')
+        self.assertIsNone(_wcparse.RE_WIN_DRIVE[0].match('//server'))
+        self.assertEqual(
+            _wcparse.RE_WIN_DRIVE[0].match('//?/GLOBAL/UNC/server/mount/temp').group(0),
+            '//?/GLOBAL/UNC/server/mount/'
+        )