[PATCH v57 0/1] MR10192: kernelbase: Handle extended length path prefix in GetLongPathNameW
``` Support the \\?\ prefix by skipping it during path resolution while preserving it in the output. Added specific handling for extended UNC paths (\\?\UNC\) to mirror standard UNC behavior, ensuring these paths are treated as network shares and not local devices. Some paths that use the extended length path were filtered out as UNC paths - but not all of them are UNC. There can be UNC path that use extended length path but not all extended length paths are UNC paths. ``` Signed-off-by: Vishnunithyasoundhar S svishnunithyasoundhar@gmail.com -- v57: kernelbase: Handle extended length path prefix in GetLongPathNameW https://gitlab.winehq.org/wine/wine/-/merge_requests/10192
From: Vishnunithyasoundhar S <svishnunithyasoundhar@gmail.com> Support the \\?\ prefix by skipping it during path resolution while preserving it in the output. Added specific handling for extended UNC paths (\\?\UNC\) to mirror standard UNC behavior, ensuring these paths are treated as network shares and not local devices. Some paths that use the extended length path were filtered out as UNC paths - but not all of them are UNC. There can be UNC path that use extended length path but not all extended length paths are UNC paths. Added test. Signed-off-by: Vishnunithyasoundhar S <svishnunithyasoundhar@gmail.com> --- dlls/kernel32/tests/path.c | 17 ++++++++++++++--- dlls/kernelbase/file.c | 27 +++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c index aa1833504d8..1b60de6d692 100644 --- a/dlls/kernel32/tests/path.c +++ b/dlls/kernel32/tests/path.c @@ -1255,6 +1255,8 @@ static void test_GetLongPathNameW(void) static const WCHAR prefix[] = { '\\','\\','?','\\', 0}; static const WCHAR backslash[] = { '\\', 0}; static const WCHAR letterX[] = { 'X', 0}; + WCHAR shortpath2[MAX_PATH]; + WCHAR longpath[MAX_PATH]; SetLastError(0xdeadbeef); length = GetLongPathNameW(NULL,NULL,0); @@ -1298,12 +1300,9 @@ static void test_GetLongPathNameW(void) /* With prefix */ SetLastError(0xdeadbeef); length = GetLongPathNameW(shortpath, NULL, 0); - todo_wine - { ok(length == 0, "Expected 0, got %ld\n", length); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %ld\n", GetLastError()); - } file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -1327,6 +1326,18 @@ static void test_GetLongPathNameW(void) length = GetLongPathNameW(shortpath, NULL, 0); ok(length == expanded, "Expected %ld, got %ld\n", expanded, length); + /* Test that extended prefix is preserved in output when converting from + * short to long path */ + shortpath2[0] = 0; + length = GetShortPathNameW(dirpath, shortpath2, ARRAY_SIZE(shortpath2)); + ok(length > 0, "GetShortPathNameW failed: %lu\n", GetLastError()); + ok(lstrcmpiW(dirpath, shortpath2) != 0, "short path name isn't created, got %s\n", debugstr_w(shortpath2)); + + SetLastError(0xdeadbeef); + length = GetLongPathNameW(shortpath2, longpath, ARRAY_SIZE(longpath)); + ok(length > 0, "GetLongPathNameW failed: %lu\n", GetLastError()); + ok(lstrcmpiW(longpath, dirpath) == 0, "Expected path: %s, got: %s\n", wine_dbgstr_w(dirpath), wine_dbgstr_w(longpath)); + /* NULL buffer with length crashes on Windows */ if (0) GetLongPathNameW(shortpath, NULL, 20); diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 83977a2c40b..3d029c3d503 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -2096,7 +2096,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetLongPathNameA( LPCSTR shortpath, LPSTR longpat */ DWORD WINAPI DECLSPEC_HOTPATCH GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen ) { - WCHAR tmplongpath[1024]; + WCHAR tmplongpath[32767]; DWORD sp = 0, lp = 0, tmplen; WIN32_FIND_DATAW wfd; UNICODE_STRING nameW; @@ -2116,7 +2116,30 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetLongPathNameW( LPCWSTR shortpath, LPWSTR longp return 0; } - if (shortpath[0] == '\\' && shortpath[1] == '\\') + /* Handle \\?\ prefix (Extended Length Path) */ + if (lstrlenW(shortpath) >= 4 && shortpath[0] == '\\' && shortpath[1] == '\\' + && shortpath[2] == '?' && shortpath[3] == '\\') + { + if (wcsnicmp(shortpath + 4, L"UNC\\", 4) == 0) + { + FIXME("UNC Extended pathname %s\n", debugstr_w(shortpath)); + tmplen = lstrlenW(shortpath); + if (tmplen < longlen) + { + if (longpath != shortpath) lstrcpyW(longpath, shortpath); + return tmplen; + } + return tmplen + 1; + } + else if ( isalpha(shortpath[4]) && shortpath[5] == ':') + { + lstrcpynW(tmplongpath, shortpath, 7); + lp = 6; + sp = 6; + } + } + + if (sp == 0 && shortpath[0] == '\\' && shortpath[1] == '\\') { FIXME( "UNC pathname %s\n", debugstr_w(shortpath) ); tmplen = lstrlenW( shortpath ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10192
On Fri Apr 3 20:04:23 2026 +0000, Vishnunithyasoundhar S wrote:
changed this line in [version 47 of the diff](/wine/wine/-/merge_requests/10192/diffs?diff_id=257621&start_sha=267d9f37cec72f59a0358c255be5fbcb283054c4#ccbcb1301019e22467910d31043560ed0d42aafe_1339_1338) fixed consistency.
changed to %lu -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135419
On Fri Apr 3 20:04:23 2026 +0000, Vishnunithyasoundhar S wrote:
changed this line in [version 47 of the diff](/wine/wine/-/merge_requests/10192/diffs?diff_id=257621&start_sha=267d9f37cec72f59a0358c255be5fbcb283054c4#6c845445f68f8d3b54ba3798c9bb9e781b28b2ec_2137_2141) Done.
Ran into a smol hiccup with `lstrcpynW( ... , ..., 6) ` \[Fixed now\] I didnt know `lstrcpynW` the `iMaxLength ` also accounts for the null character that it adds to the end so it was only copying 5 characters and putting a null at the 6th position XD After tinkering and realizations made it `lstrcpynW( ... , ..., 7) ` and let the rest of the flow overwrite on that null so that it wont matter. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135421
On Fri Apr 3 20:04:24 2026 +0000, Vishnunithyasoundhar S wrote:
changed this line in [version 47 of the diff](/wine/wine/-/merge_requests/10192/diffs?diff_id=257621&start_sha=267d9f37cec72f59a0358c255be5fbcb283054c4#6c845445f68f8d3b54ba3798c9bb9e781b28b2ec_2120_2121) done
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135422
On Fri Apr 3 20:04:25 2026 +0000, Vishnunithyasoundhar S wrote:
changed this line in [version 47 of the diff](/wine/wine/-/merge_requests/10192/diffs?diff_id=257621&start_sha=267d9f37cec72f59a0358c255be5fbcb283054c4#6c845445f68f8d3b54ba3798c9bb9e781b28b2ec_2121_2121) fixed formatting manually. I was using zed's format selection before and it seems it wasnt up to the mark (Or the default settings bad)
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135423
On Wed Apr 8 05:51:46 2026 +0000, Vishnunithyasoundhar S wrote:
Understood. I will look into them thanks Changed length of tmplongpath to maximum that can be reached by extended file length path
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135424
On Fri Apr 3 13:59:11 2026 +0000, Akihiro Sagawa wrote:
Ideally, those failures should be verified, but if you're confident that your change cannot affect them, it's fine to ignore them. Personally, I would at least take a quick look to confirm that the failing tests don't use the API you modified. I see. Yeah I have confirmed that they are not using the API I have modified.
{width=900 height=220} I have addressed all of your comments @sgwaki . Would appreciate your review. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10192#note_135433
participants (2)
-
Vishnunithyasoundhar S -
Vishnunithyasoundhar S (@svishnunithyasoundhar)