Skip to content

Commit 00dae38

Browse files
committed
dynamically import from api-ms-win-core-path-l1-1-0.dll
1 parent 35217ab commit 00dae38

File tree

2 files changed

+52
-98
lines changed

2 files changed

+52
-98
lines changed

Modules/posixmodule.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626

2727
#ifdef MS_WINDOWS
2828
# include <windows.h>
29-
# include <pathcch.h>
29+
# if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)
30+
# include <pathcch.h>
31+
# endif
3032
# include <winioctl.h>
3133
# include <lmcons.h> // UNLEN
3234
# include "osdefs.h" // SEP

Python/fileutils.c

+49-97
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
#ifdef MS_WINDOWS
99
# include <malloc.h>
1010
# include <windows.h>
11-
# include <pathcch.h> // PathCchCombineEx
11+
# if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)
12+
# define PATHCCH_ALLOW_LONG_PATHS 0x01
13+
# else
14+
# include <pathcch.h> // PathCchCombineEx
15+
# endif
1216
extern int winerror_to_errno(int);
1317
#endif
1418

@@ -2107,123 +2111,71 @@ _Py_abspath(const wchar_t *path, wchar_t **abspath_p)
21072111
#endif
21082112
}
21092113

2110-
// The Windows Games API family does not provide these functions
2111-
// so provide our own implementations. Remove them in case they get added
2112-
// to the Games API family
2113-
// Note that this implementation does not handle all the same cases as the real
2114-
// function, but we expect games are very unlikely to encounter the more obscure
2115-
// cases.
2114+
// The Windows Games API family implements the PathCch* APIs in the Xbox OS,
2115+
// but does not expose them yet. Load them dynamically until
2116+
// 1) they are officially exposed
2117+
// 2) we stop supporting older versions of the GDK which do not expose them
21162118
#if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)
21172119
HRESULT
21182120
PathCchSkipRoot(const wchar_t *path, const wchar_t **rootEnd)
21192121
{
2120-
if (path[0] == '\\') {
2121-
/* relative path with root e.g. \Windows */
2122-
if (path[1] != '\\') {
2123-
*rootEnd = path + 1;
2124-
return S_OK;
2122+
static int initialized = 0;
2123+
typedef HRESULT(__stdcall *PPathCchSkipRoot) (PCWSTR pszPath,
2124+
PCWSTR *ppszRootEnd);
2125+
static PPathCchSkipRoot _PathCchSkipRoot;
2126+
2127+
if (initialized == 0) {
2128+
HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
2129+
LOAD_LIBRARY_SEARCH_SYSTEM32);
2130+
if (pathapi) {
2131+
_PathCchSkipRoot = (PPathCchSkipRoot)GetProcAddress(
2132+
pathapi, "PathCchSkipRoot");
21252133
}
2126-
2127-
/* UNC drives e.g. \\server\share or \\?\UNC\server\share */
2128-
const wchar_t *end = path + 2;
2129-
if (!wcsnicmp(end, L"?\\UNC\\", 6)) {
2130-
end += 6;
2131-
}
2132-
2133-
end = wcschr(end, '\\');
2134-
if (!end) {
2135-
*rootEnd = path + wcslen(path);
2136-
return S_OK;
2134+
else {
2135+
_PathCchSkipRoot = NULL;
21372136
}
2138-
end = wcschr(end + 1, '\\');
2139-
*rootEnd = (!end) ? path + wcslen(path) : end + 1;
2140-
return S_OK;
2137+
initialized = 1;
21412138
}
2142-
/* absolute / relative path with drive, e.g. C: or C:\ */
2143-
else if (isalpha(path[0]) && path[1] == ':') {
2144-
*rootEnd = (path[2] == '\\') ? path + 3 : path + 2;
2145-
return S_OK;
2146-
}
2147-
2148-
/* relative path */
2149-
return E_INVALIDARG;
2150-
}
21512139

2152-
static HRESULT
2153-
PathCchStripToRoot(wchar_t *path, size_t size)
2154-
{
2155-
wchar_t *end;
2156-
if (PathCchSkipRoot(path, &end) == S_OK) {
2157-
if (*end == '\0') {
2158-
return S_FALSE;
2159-
}
2160-
*end = '\0';
2140+
if (!_PathCchSkipRoot) {
2141+
return E_NOINTERFACE;
21612142
}
21622143

2163-
return E_INVALIDARG;
2144+
return _PathCchSkipRoot(path, rootEnd);
21642145
}
21652146

2166-
static wchar_t*
2167-
PathAddBackslashW(wchar_t *path)
2168-
{
2169-
size_t len;
2170-
if (!path) {
2171-
return NULL;
2172-
}
2173-
len = wcslen(path);
2174-
if (len && path[len - 1] != '\\') {
2175-
path[len++] = '\\';
2176-
path[len] = '\0';
2177-
}
2178-
return path + len;
2179-
}
2180-
2181-
#ifndef PATHCCH_ALLOW_LONG_PATHS
2182-
#define PATHCCH_ALLOW_LONG_PATHS 0x01
2183-
#endif
2184-
21852147
static HRESULT
21862148
PathCchCombineEx(wchar_t *buffer, size_t bufsize, const wchar_t *dirname,
21872149
const wchar_t *relfile, unsigned long flags)
21882150
{
2189-
(void)flags;
2190-
2191-
if ((isalpha(relfile[0]) && relfile[1] == ':') ||
2192-
(relfile[0] == '\\' && relfile[1] == '\\'))
2193-
{
2194-
dirname = relfile;
2195-
relfile = NULL;
2196-
}
2197-
2198-
size_t dir_len = wcslen(dirname);
2199-
size_t file_len = relfile ? wcslen(relfile) : 0;
2200-
/* path is at max dirname + filename + backslash + \0 */
2201-
size_t new_len = dir_len + file_len + 2;
2202-
if (new_len > bufsize) {
2203-
return E_INVALIDARG;
2204-
}
2205-
2206-
size_t combined_length = dir_len;
2207-
wcscpy(buffer, dirname);
2208-
if (!relfile || !relfile[0]) {
2209-
if(wcsncmp(buffer, L"\\\\?\\", 4)) {
2210-
buffer += 4;
2151+
static int initialized = 0;
2152+
typedef HRESULT(__stdcall *PPathCchCombineEx) (PWSTR pszPathOut,
2153+
size_t cchPathOut,
2154+
PCWSTR pszPathIn,
2155+
PCWSTR pszMore,
2156+
unsigned long dwFlags);
2157+
static PPathCchCombineEx _PathCchCombineEx;
2158+
2159+
if (initialized == 0) {
2160+
HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
2161+
LOAD_LIBRARY_SEARCH_SYSTEM32);
2162+
if (pathapi) {
2163+
_PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(
2164+
pathapi, "PathCchCombineEx");
22112165
}
2212-
if (isalpha(buffer[0]) && buffer[1] == ':' && !buffer[2]) {
2213-
PathAddBackslashW(buffer);
2166+
else {
2167+
_PathCchCombineEx = NULL;
22142168
}
2169+
initialized = 1;
22152170
}
2216-
else {
2217-
if (relfile[0] == '\\' && relfile[1] != '\\')
2218-
{
2219-
PathCchStripToRoot(buffer, combined_length);
2220-
relfile++;
2221-
}
2222-
PathAddBackslashW(buffer);
2223-
wcscat(buffer, relfile);
2171+
2172+
if (!_PathCchCombineEx) {
2173+
return E_NOINTERFACE;
22242174
}
2225-
return S_OK;
2175+
2176+
return _PathCchCombineEx(buffer, bufsize, dirname, relfile, flags);
22262177
}
2178+
22272179
#endif /* defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP) */
22282180

22292181
// The caller must ensure "buffer" is big enough.

0 commit comments

Comments
 (0)