On Wed, Jan 10, 2018 at 12:59 PM, Albert-Jan Roskam
<sjeik_ap...@hotmail.com> wrote:
>
> I tried:
>>>> from os.path import _getfullpathname
>>>> _getfullpathname(r"H:")
> 'h:\\path\\to\\folder'
>>>> import os
>>>> os.getcwd()
> 'h:\\path\\to\\folder'
>
> I expected h:\ to be \\server\share\foo.

You called _getfullpathname (WinAPI GetFullPathName), not
_getfinalpathname (WinAPI GetFinalPathNameByHandle). GetFullPathName
works on the path as a string without touching the filesystem.
GetFinalPathNameByHandle reconstructs a path when given a handle to a
file or directory.

> The fact that the current working directory was returned was even more 
> unexpected.

"H:" or "H:relative/path" is relative to the working directory on
drive H:. The process only has one working directory, but
GetFullPathName also checks for environment variables such as "=H:".
The C runtime's _chdir function sets these magic variables, as does
Python's os.chdir function (we don't call C _chdir). WinAPI
SetCurrentDirectory does not set them. For example:

    >>> os.chdir('Z:/Temp')
    >>> win32api.GetEnvironmentVariable('=Z:')
    'Z:\\Temp'
    >>> os.path._getfullpathname('Z:relative')
    'Z:\\Temp\\relative'

> Why would anybody *want* the drive letters? They are only useful because (a) 
> they save on
> keystrokes (b) they bypass the annoying limitation of the cd command on 
> windows, ie. it
> does not work with UNC paths.

Windows itself has no problem using a UNC path as the working
directory. That's a limit of the CMD shell.

SUBST drives can be used to access long paths. Since the substitution
occurs in the kernel, it avoids the MAX_PATH 260-character limit. Of
course, you can also use junctions and symlinks to access long paths,
or in Windows 10 simply enable long-path support.

> I know net use, pushd, subst. I use 'net use' for more or less permanent 
> drives and
> pushd/popd to get a temporary drive, available letter (cd nuisance).

`net.exe use` and CMD's PUSHD command (with a UNC path) both call
WinAPI WNetAddConnection2 to create a mapped network drive. The
difference is that net.exe can supply alternate credentials and create
a persistent mapping, while PUSHD uses the current user's credentials
and creates a non-persistent mapping.

If your account gets logged on with a UAC split token, the standard
and elevated tokens actually have separate logon sessions with
separate local-device mappings. You can enable a policy to link the
two logon sessions. Set a DWORD value of 1 named
"EnableLinkedConnections" in the key
"HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System", and
reboot.

subst.exe creates substitute paths using WinAPI DefineDosDevice.
Unlike the WNet API, this function doesn't use MPR (multiple provider
router) to create a direct link for the network provider (e.g.
\Device\LanmanRedirectory); doesn't create a linked connection when
EnableLinkedConnections is defined; and can't create a persistent
drive with stored credentials (though you can use an account logon
script for this). On the plus side, a drive mapped via subst.exe can
target any path.

> Interesting code! I have used the following, which uses SHGetFolderPath, ie. 
> without 'Known'.
> from win32com.shell import shell, shellcon
> desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0)

SHGetFolderPath is usually fine, but still, it's outdated and
deprecated. win32com.shell doesn't wrap SHGetKnownFolderPath for some
reason, but you can still use the new known-folder API without ctypes.
Just create a KnownFolderManager instance. For example:

    import pythoncom
    from win32com.shell import shell

    kfmgr = pythoncom.CoCreateInstance(shell.CLSID_KnownFolderManager, None,
                pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IKnownFolderManager)

    desktop_path = kfmgr.GetFolder(shell.FOLDERID_Desktop).GetPath()

This doesn't work as conveniently for getting known folders of other
users. While the high-level SHGetKnownFolderPath function takes care
of loading the user profile and impersonating, we have to do this
ourselves when using a KnownFolderManager instance.

That said, to correct my previous post, you have to be logged on with
SeTcbPrivilege access (e.g. a SYSTEM service) to get and set other
users' known folders without their password. (If you have the password
you can use a regular logon instead of an S4U logon, and that works
fine.)

> Working with ctypes.wintypes is quite complex!

I wouldn't say ctypes is complex in general. But calling LsaLogonUser
is complex due to all of the structs that include variable-sized
buffers. And working with COM via ctypes is also complex, which is why
comtypes exists.
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to