Eryk Sun <[email protected]> added the comment:
Sorry, I mistakenly left out ERROR_BAD_NETPATH (53). It's at least used with
mapped drives. For example, I have drive "M:" mapped to WebDAV
"//live.sysinternals.com/tools", and I see this error if I disconnect the
network:
>>> try: nt._getfinalpathname('M:/')
... except OSError as e: print(e.winerror)
...
53
whereas if I access the underlying UNC path directly the error in this case is
ERROR_BAD_NET_NAME (67):
>>> try: nt._getfinalpathname('//live.sysinternals.com/tools')
... except OSError as e: print(e.winerror)
...
67
(Not that this case would normally succeed. A WebDAV share fails the internal
request to get a normalized name, as expected for most network providers, but
with an unexpected error code that's not handled by the API. It would succeed
if we changed _getfinalpathname to fall back on getting the final name as
opened, which skips expanding short component names.)
---
Discussion
The Multiple UNC Provider device (i.e. "\??\UNC" -> "\Device\Mup") resolves a
UNC path prefix to a network provider (e.g. "Microsoft Windows Network" for
SMB) by checking all providers in a registered order until one claims to handle
the path. Typically a provider claims the server/share prefix, but the claimed
prefix can be just the server, or a variable path length. Typically, if the
"server" component isn't found, a provider returns STATUS_BAD_NETWORK_PATH. If
the "share" component isn't found, it returns STATUS_BAD_NETWORK_NAME. However,
since the request is to MUP, the final status is whatever MUP returns. As far
as I can tell, post-Vista MUP prefix resolution returns STATUS_BAD_NETWORK_NAME
even if all providers return STATUS_BAD_NETWORK_PATH.
That said, MUP prefix resolution isn't used for mapped drives. A mapped drive
sends the request directly to the provider that created the drive. Prior to
Vista, this used to be a top-level named device such as
"\Device\LanmanRedirector" (SMB). Since Vista, all redirected create/open
requests are routed through MUP, but it doesn't use prefix resolution in this
case. It has a sneaky way of implementing this. The provider's device name
nowadays is an object SymbolicLink that targets MUP, but with a reserved
component that indicates the redirector to use, e.g. "\Device\LanmanRedirector"
-> "\Device\Mup\;LanmanRedirector". (A valid server name cannot begin with a
semicolon, so this syntax is reserved by MUP. It also supports an optional
second reserved component, with the drive name and logon session ID, such as
";Z:0000000000001234". These reserved components are removed from the parsed
path, i.e. they are not included in the final path.) Nothing stops us from
using this undocumented fea
ture manually in a UNC path, as demonstrated by the examples below.
The following shows that MUP parses ";LanmanRedirector" as the redirector name,
not the "server" component.
>>> os.path.samefile('//localhost/C$', '//;LanmanRedirector/localhost/C$')
True
The following shows that an explicit redirector path does not use prefix
resolution. This open fails because there's no WebDAV server on localhost.
>>> try: os.stat('//;WebDavRedirector/localhost/C$')
... except OSError as e: print(e.winerror)
...
53
The following shows that MUP fails an open with STATUS_OBJECT_PATH_INVALID
(i.e. ERROR_BAD_PATHNAME, 161) if the redirector name is unknown:
>>> try: os.stat('//;Lanman/localhost/C$')
... except OSError as e: print(e.winerror)
...
161
When we misspell the server name as "localhos", we see that the error for an
explicit redirector path, as is used in a mapped drive, is ERROR_BAD_NETPATH
(53):
>>> try: os.stat('//;LanmanRedirector/localhos/C$')
... except OSError as e: print(e.winerror)
...
53
If we omit the explicit redirector name, then MUP tries prefix resolution, and
the error is instead ERROR_BAD_NET_NAME (67):
>>> try: os.stat('//localhos/C$')
... except OSError as e: print(e.winerror)
...
67
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue38081>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com