diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -161,6 +161,30 @@ not exist or is inaccessible. +.. function:: getknownfolders() + + Return a dict containing paths to Windows known folders like My Documents. + The keys are camel case, the values are either unicode objects or None + if a path for a known folder could not be retrieved. Some of the paths + may not exist. + + Availability: Windows (Vista and newer) + + .. versionadded:: 3.4 + + +.. function:: getshellfolders() + + Return a dict containing paths to Windows shell folders like My Documents. + The keys are all lower case, the values are either unicode objects or None + if a path for a shell folder could not be retrieved. Some of the paths + may not exist. + + Availability: Windows. + + .. versionadded:: 3.4 + + .. function:: isabs(path) Return ``True`` if *path* is an absolute pathname. On Unix, that means it diff --git a/Lib/ntpath.py b/Lib/ntpath.py --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -662,3 +662,17 @@ except ModuleNotFoundError: # Use genericpath.isdir as imported above. pass + +try: + from nt import getshellfolders +except ImportError: + def getshellfolders(): + """Dummy method""" + return {} + +try: + from nt import getknownfolders +except ImportError: + def getknownfolders(): + """Dummy method""" + return {} diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -10474,6 +10474,284 @@ Py_RETURN_NONE; } +#ifdef MS_WINDOWS + +/* #define NTDDI_VERSION NTDDI_VISTA */ +#include + +static int +_set_shellfolder_path(PyObject *d, int folder, char *name) +{ + Py_UNICODE buf[MAX_PATH]; + HRESULT rc; + PyObject *o; + + rc = SHGetFolderPathW(NULL, folder | CSIDL_FLAG_DONT_VERIFY, + NULL, SHGFP_TYPE_CURRENT, buf); + if (rc == S_OK) { + if ((o = PyUnicode_FromUnicode(buf, wcslen(buf))) == NULL) { + return -1; + } + } else { + o = Py_None; + Py_INCREF(o); + } + if (PyDict_SetItemString(d, name, o) != 0) { + Py_DECREF(o); + return -1; + } + Py_DECREF(o); + return 0; +} + +PyDoc_STRVAR(win32_getshellfolders__doc__, +"getshellfolders() -> dict\n\ +\n\ +Return a dict containing paths to Windows shell folders like My Documents.\n\ +The keys are all lower case, the values are either unicode objects or None\n\ +if a path for a shell folder couldn't be found."); + +static PyObject* +win32_getshellfolders(PyObject *self, PyObject *noargs) +{ + PyObject *d; + + if ((d = PyDict_New()) == NULL) { + return NULL; + } + + #define SetShellFolderPath(cons, name) \ + if (_set_shellfolder_path(d, cons, name) != 0) { \ + Py_DECREF(d); \ + return NULL; \ + } + + /* CSIDL_MYDOCUMENTS is an alias for CSIDL_PERSONAL */ + SetShellFolderPath(CSIDL_DESKTOP, "desktop") + SetShellFolderPath(CSIDL_INTERNET, "internet") + SetShellFolderPath(CSIDL_PROGRAMS, "programs") + SetShellFolderPath(CSIDL_CONTROLS, "controls") + SetShellFolderPath(CSIDL_PRINTERS, "printers") + SetShellFolderPath(CSIDL_PERSONAL, "personal") + SetShellFolderPath(CSIDL_FAVORITES, "favorites") + SetShellFolderPath(CSIDL_STARTUP, "startup") + SetShellFolderPath(CSIDL_RECENT, "recent") + SetShellFolderPath(CSIDL_SENDTO, "sendto") + SetShellFolderPath(CSIDL_BITBUCKET, "bitbucket") + SetShellFolderPath(CSIDL_STARTMENU, "startmenu") + SetShellFolderPath(CSIDL_MYDOCUMENTS, "mydocuments") + SetShellFolderPath(CSIDL_MYMUSIC, "mymusic") + SetShellFolderPath(CSIDL_MYVIDEO, "myvideo") + SetShellFolderPath(CSIDL_DESKTOPDIRECTORY, "desktopdirectory") + SetShellFolderPath(CSIDL_DRIVES, "drives") + SetShellFolderPath(CSIDL_NETWORK, "network") + SetShellFolderPath(CSIDL_NETHOOD, "nethood") + SetShellFolderPath(CSIDL_FONTS, "fonts") + SetShellFolderPath(CSIDL_TEMPLATES, "templates") + SetShellFolderPath(CSIDL_COMMON_STARTMENU, "common_startmenu") + SetShellFolderPath(CSIDL_COMMON_PROGRAMS, "common_programs") + SetShellFolderPath(CSIDL_COMMON_STARTUP, "common_startup") + SetShellFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY, "common_desktopdirectory") + SetShellFolderPath(CSIDL_APPDATA, "appdata") + SetShellFolderPath(CSIDL_PRINTHOOD, "printhood") + SetShellFolderPath(CSIDL_LOCAL_APPDATA, "local_appdata") + SetShellFolderPath(CSIDL_ALTSTARTUP, "altstartup") + SetShellFolderPath(CSIDL_COMMON_ALTSTARTUP, "common_altstartup") + SetShellFolderPath(CSIDL_COMMON_FAVORITES, "common_favorites") + SetShellFolderPath(CSIDL_INTERNET_CACHE, "internet_cache") + SetShellFolderPath(CSIDL_COOKIES, "cookies") + SetShellFolderPath(CSIDL_HISTORY, "history") + SetShellFolderPath(CSIDL_COMMON_APPDATA, "common_appdata") + SetShellFolderPath(CSIDL_WINDOWS, "windows") + SetShellFolderPath(CSIDL_SYSTEM, "system") + SetShellFolderPath(CSIDL_PROGRAM_FILES, "program_files") + SetShellFolderPath(CSIDL_MYPICTURES, "mypictures") + SetShellFolderPath(CSIDL_PROFILE, "profile") + SetShellFolderPath(CSIDL_SYSTEMX86, "systemx86") + SetShellFolderPath(CSIDL_PROGRAM_FILESX86, "program_filesx86") + SetShellFolderPath(CSIDL_PROGRAM_FILES_COMMON, "program_files_common") + SetShellFolderPath(CSIDL_PROGRAM_FILES_COMMONX86, "program_files_commonx86") + SetShellFolderPath(CSIDL_COMMON_TEMPLATES, "common_templates") + SetShellFolderPath(CSIDL_COMMON_DOCUMENTS, "common_documents") + SetShellFolderPath(CSIDL_COMMON_ADMINTOOLS, "common_admintools") + SetShellFolderPath(CSIDL_ADMINTOOLS, "admintools") + SetShellFolderPath(CSIDL_CONNECTIONS, "connections") + SetShellFolderPath(CSIDL_COMMON_MUSIC, "common_music") + SetShellFolderPath(CSIDL_COMMON_PICTURES, "common_pictures") + SetShellFolderPath(CSIDL_COMMON_VIDEO, "common_video") + SetShellFolderPath(CSIDL_RESOURCES, "resources") + SetShellFolderPath(CSIDL_RESOURCES_LOCALIZED, "resources_localized") + SetShellFolderPath(CSIDL_COMMON_OEM_LINKS, "common_oem_links") + SetShellFolderPath(CSIDL_CDBURN_AREA, "cdburn_area") + SetShellFolderPath(CSIDL_COMPUTERSNEARME, "computersnearme") + + #undef SetShellFolderPath + + return d; +} + +#if (NTDDI_VERSION >= NTDDI_VISTA) +/* SHGetKnownFolders is only available on Vista and newer */ + +static int +_set_knownfolder_path(PyObject *d, KNOWNFOLDERID fid, DWORD flags, char *name) +{ + PWSTR path; + HRESULT rc; + PyObject *o; + + rc = SHGetKnownFolderPath(&fid, flags, NULL, &path); + if (rc == S_OK) { + o = PyUnicode_FromUnicode(path, wcslen(path)); + CoTaskMemFree(path); + if (o == NULL) { + return -1; + } + } else { + o = Py_None; + Py_INCREF(o); + } + if (PyDict_SetItemString(d, name, o) != 0) { + Py_DECREF(o); + return -1; + } + Py_DECREF(o); + return 0; +} + +PyDoc_STRVAR(win32_getknownfolders__doc__, +"getknownfolders() -> dict\n\ +\n\ +Return a dict containing paths to Windows shell folders like My Documents.\n\ +The keys are all lower case, the values are either unicode objects or None\n\ +if a path for a shell folder couldn't be found."); + +static PyObject* +win32_getknownfolders(PyObject *self, PyObject *noargs) +{ + PyObject *d; + + if ((d = PyDict_New()) == NULL) { + return NULL; + } + + #define SetKnownFolderPath(rfid, name) \ + if (_set_knownfolder_path(d, rfid, KF_FLAG_DONT_VERIFY, name) != 0) { \ + Py_DECREF(d); \ + return NULL; \ + } + + SetKnownFolderPath(FOLDERID_NetworkFolder, "NetworkFolder") + SetKnownFolderPath(FOLDERID_ComputerFolder, "ComputerFolder") + SetKnownFolderPath(FOLDERID_InternetFolder, "InternetFolder") + SetKnownFolderPath(FOLDERID_ControlPanelFolder, "ControlPanelFolder") + SetKnownFolderPath(FOLDERID_PrintersFolder, "PrintersFolder") + SetKnownFolderPath(FOLDERID_SyncManagerFolder, "SyncManagerFolder") + SetKnownFolderPath(FOLDERID_SyncSetupFolder, "SyncSetupFolder") + SetKnownFolderPath(FOLDERID_ConflictFolder, "ConflictFolder") + SetKnownFolderPath(FOLDERID_SyncResultsFolder, "SyncResultsFolder") + SetKnownFolderPath(FOLDERID_RecycleBinFolder, "RecycleBinFolder") + SetKnownFolderPath(FOLDERID_ConnectionsFolder, "ConnectionsFolder") + SetKnownFolderPath(FOLDERID_Fonts, "Fonts") + SetKnownFolderPath(FOLDERID_Desktop, "Desktop") + SetKnownFolderPath(FOLDERID_Startup, "Startup") + SetKnownFolderPath(FOLDERID_Programs, "Programs") + SetKnownFolderPath(FOLDERID_StartMenu, "StartMenu") + SetKnownFolderPath(FOLDERID_Recent, "Recent") + SetKnownFolderPath(FOLDERID_SendTo, "SendTo") + SetKnownFolderPath(FOLDERID_Documents, "Documents") + SetKnownFolderPath(FOLDERID_Favorites, "Favorites") + SetKnownFolderPath(FOLDERID_NetHood, "NetHood") + SetKnownFolderPath(FOLDERID_PrintHood, "PrintHood") + SetKnownFolderPath(FOLDERID_Templates, "Templates") + SetKnownFolderPath(FOLDERID_CommonStartup, "CommonStartup") + SetKnownFolderPath(FOLDERID_CommonPrograms, "CommonPrograms") + SetKnownFolderPath(FOLDERID_CommonStartMenu, "CommonStartMenu") + SetKnownFolderPath(FOLDERID_PublicDesktop, "PublicDesktop") + SetKnownFolderPath(FOLDERID_ProgramData, "ProgramData") + SetKnownFolderPath(FOLDERID_CommonTemplates, "CommonTemplates") + SetKnownFolderPath(FOLDERID_PublicDocuments, "PublicDocuments") + SetKnownFolderPath(FOLDERID_RoamingAppData, "RoamingAppData") + SetKnownFolderPath(FOLDERID_LocalAppData, "LocalAppData") + SetKnownFolderPath(FOLDERID_LocalAppDataLow, "LocalAppDataLow") + SetKnownFolderPath(FOLDERID_InternetCache, "InternetCache") + SetKnownFolderPath(FOLDERID_Cookies, "Cookies") + SetKnownFolderPath(FOLDERID_History, "History") + SetKnownFolderPath(FOLDERID_System, "System") + SetKnownFolderPath(FOLDERID_SystemX86, "SystemX86") + SetKnownFolderPath(FOLDERID_Windows, "Windows") + SetKnownFolderPath(FOLDERID_Profile, "Profile") + SetKnownFolderPath(FOLDERID_Pictures, "Pictures") + SetKnownFolderPath(FOLDERID_ProgramFilesX86, "ProgramFilesX86") + SetKnownFolderPath(FOLDERID_ProgramFilesCommonX86, "ProgramFilesCommonX86") + SetKnownFolderPath(FOLDERID_ProgramFilesX64, "ProgramFilesX64") + SetKnownFolderPath(FOLDERID_ProgramFilesCommonX64, "ProgramFilesCommonX64") + SetKnownFolderPath(FOLDERID_ProgramFiles, "ProgramFiles") + SetKnownFolderPath(FOLDERID_ProgramFilesCommon, "ProgramFilesCommon") + SetKnownFolderPath(FOLDERID_UserProgramFiles, "UserProgramFiles") + SetKnownFolderPath(FOLDERID_UserProgramFilesCommon, "UserProgramFilesCommon") + SetKnownFolderPath(FOLDERID_AdminTools, "AdminTools") + SetKnownFolderPath(FOLDERID_CommonAdminTools, "CommonAdminTools") + SetKnownFolderPath(FOLDERID_Music, "Music") + SetKnownFolderPath(FOLDERID_Videos, "Videos") + SetKnownFolderPath(FOLDERID_Ringtones, "Ringtones") + SetKnownFolderPath(FOLDERID_PublicPictures, "PublicPictures") + SetKnownFolderPath(FOLDERID_PublicMusic, "PublicMusic") + SetKnownFolderPath(FOLDERID_PublicVideos, "PublicVideos") + SetKnownFolderPath(FOLDERID_PublicRingtones, "PublicRingtones") + SetKnownFolderPath(FOLDERID_ResourceDir, "ResourceDir") + SetKnownFolderPath(FOLDERID_LocalizedResourcesDir, "LocalizedResourcesDir") + SetKnownFolderPath(FOLDERID_CommonOEMLinks, "CommonOEMLinks") + SetKnownFolderPath(FOLDERID_CDBurning, "CDBurning") + SetKnownFolderPath(FOLDERID_UserProfiles, "UserProfiles") + SetKnownFolderPath(FOLDERID_Playlists, "Playlists") + SetKnownFolderPath(FOLDERID_SamplePlaylists, "SamplePlaylists") + SetKnownFolderPath(FOLDERID_SampleMusic, "SampleMusic") + SetKnownFolderPath(FOLDERID_SamplePictures, "SamplePictures") + SetKnownFolderPath(FOLDERID_SampleVideos, "SampleVideos") + SetKnownFolderPath(FOLDERID_PhotoAlbums, "PhotoAlbums") + SetKnownFolderPath(FOLDERID_Public, "Public") + SetKnownFolderPath(FOLDERID_ChangeRemovePrograms, "ChangeRemovePrograms") + SetKnownFolderPath(FOLDERID_AppUpdates, "AppUpdates") + SetKnownFolderPath(FOLDERID_AddNewPrograms, "AddNewPrograms") + SetKnownFolderPath(FOLDERID_Downloads, "Downloads") + SetKnownFolderPath(FOLDERID_PublicDownloads, "PublicDownloads") + SetKnownFolderPath(FOLDERID_SavedSearches, "SavedSearches") + SetKnownFolderPath(FOLDERID_QuickLaunch, "QuickLaunch") + SetKnownFolderPath(FOLDERID_Contacts, "Contacts") + SetKnownFolderPath(FOLDERID_SidebarParts, "SidebarParts") + SetKnownFolderPath(FOLDERID_SidebarDefaultParts, "SidebarDefaultParts") + SetKnownFolderPath(FOLDERID_PublicGameTasks, "PublicGameTasks") + SetKnownFolderPath(FOLDERID_GameTasks, "GameTasks") + SetKnownFolderPath(FOLDERID_SavedGames, "SavedGames") + SetKnownFolderPath(FOLDERID_Games, "Games") + SetKnownFolderPath(FOLDERID_SEARCH_MAPI, "SEARCH_MAPI") + SetKnownFolderPath(FOLDERID_SEARCH_CSC, "SEARCH_CSC") + SetKnownFolderPath(FOLDERID_Links, "Links") + SetKnownFolderPath(FOLDERID_UsersFiles, "UsersFiles") + SetKnownFolderPath(FOLDERID_UsersLibraries, "UsersLibraries") + SetKnownFolderPath(FOLDERID_SearchHome, "SearchHome") + SetKnownFolderPath(FOLDERID_OriginalImages, "OriginalImages") + SetKnownFolderPath(FOLDERID_DocumentsLibrary, "DocumentsLibrary") + SetKnownFolderPath(FOLDERID_MusicLibrary, "MusicLibrary") + SetKnownFolderPath(FOLDERID_PicturesLibrary, "PicturesLibrary") + SetKnownFolderPath(FOLDERID_VideosLibrary, "VideosLibrary") + SetKnownFolderPath(FOLDERID_RecordedTVLibrary, "RecordedTVLibrary") + SetKnownFolderPath(FOLDERID_HomeGroup, "HomeGroup") + SetKnownFolderPath(FOLDERID_DeviceMetadataStore, "DeviceMetadataStore") + SetKnownFolderPath(FOLDERID_Libraries, "Libraries") + SetKnownFolderPath(FOLDERID_PublicLibraries, "PublicLibraries") + SetKnownFolderPath(FOLDERID_UserPinned, "UserPinned") + SetKnownFolderPath(FOLDERID_ImplicitAppShortcuts, "ImplicitAppShortcuts") + + #undef SetKnownFolderPath + + return d; +} + +#endif /* VISTA */ + +#endif /* MS_WINDOWS */ static PyMethodDef posix_methods[] = { {"access", (PyCFunction)posix_access, @@ -10884,7 +11162,13 @@ {"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL}, {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__}, {"_getdiskusage", win32__getdiskusage, METH_VARARGS, win32__getdiskusage__doc__}, -#endif + {"getshellfolders", win32_getshellfolders, METH_NOARGS, + win32_getshellfolders__doc__}, +#if (NTDDI_VERSION >= NTDDI_VISTA) + {"getknownfolders", win32_getknownfolders, METH_NOARGS, + win32_getknownfolders__doc__}, +#endif +#endif /* MS_WINDOWS */ #ifdef HAVE_GETLOADAVG {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__}, #endif