[Bug 56399] New: cmd.exe's %~s modifier (short DOS path) expands to mixed short/long format
https://bugs.winehq.org/show_bug.cgi?id=56399 Bug ID: 56399 Summary: cmd.exe's %~s modifier (short DOS path) expands to mixed short/long format Product: Wine Version: 9.2 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: cmd Assignee: wine-bugs(a)winehq.org Reporter: tncgyp+uypezc35u0dyxed6tszn0wk59xjphxb2gcxycxno8mxg4od 48(a)sharklasers.com Distribution: --- Try the following: cd /tmp && printf 'for %%%%P in ("%%ProgramFiles%%\Internet Explorer") do winepath.exe -s %%%%P\r\n' > shortpath.bat && wine cmd.exe /c shortpath.bat && printf 'for %%%%P in ("%%ProgramFiles%%\Internet Explorer") do echo %%%%~sP\r\n' > shortpath.bat && wine cmd.exe /c shortpath.bat && rm shortpath.bat && cd "$OLDPWD" The first batch file uses winepath.exe -s and returns 'C:\PROG~5P2\INTE~H1A'. The second batch file uses cmd.exe's %~s modifier and returns 'C:\PROG~5P2\Internet Explorer'. Wine's cmd.exe %~s modifier seems to be broken. It should produce the same path as winepath.exe -s. The second batch file works as expected with MS cmd.exe in a WinXP VM and a Win7 VM. Tested on wine 9.2 with fresh prefixes and: - WINEARCH=win32 and wine cmd.exe - WINEARCH=win64 and wine cmd.exe - WINEARCH=win64 and wine64 cmd.exe -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 Eric Pouech <eric.pouech(a)gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |eric.pouech(a)gmail.com --- Comment #1 from Eric Pouech <eric.pouech(a)gmail.com> --- do you have a real application that suffers from this? -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 --- Comment #2 from tncgyp+uypezc35u0dyxed6tszn0wk59xjphxb2gcxycxno8mxg4od48(a)sharklasers.com --- Well, I want to write a script that changes the startup behavior of a Windows 95 program. One of the tasks of this script is to modify a configuration file that contains paths. Since the program itself was once ported from DOS, the paths are in short format. At first I wanted to use VBScript for this, but it turned out that wine's wscript.exe doesn't implement the .ShortPath method. Therefore I switched to batch and found this bug. At the moment it doesn't seem to be possible to solve the problem using a script that can run under both Wine and Windows. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 --- Comment #3 from tncgyp+uypezc35u0dyxed6tszn0wk59xjphxb2gcxycxno8mxg4od48(a)sharklasers.com --- The problematic code is in: wine/programs/cmd/batch.c, function WCMD_HandleTildeModifiers @ line 546 /* 4. Handle 's' : Use short paths (File doesn't have to exist) */ if (wmemchr(firstModifier, 's', modifierLen) != NULL) { if (finaloutput[0] != 0x00) lstrcatW(finaloutput, L" "); /* Convert fullfilename's path to a short path - Save filename away as only path is valid, name may not exist which causes GetShortPathName to fail if it is provided */ if (filepart) { lstrcpyW(thisoutput, filepart); *filepart = 0x00; GetShortPathNameW(fullfilename, fullfilename, ARRAY_SIZE(fullfilename)); lstrcatW(fullfilename, thisoutput); } } The first question is, why does the conversion always take place without the file at the end of the path? This is always wrong for file names with more than 8 characters. The second question is why a directory at the end of the path is recognized as a file? To solve the first question, my proposal would be the following change: /* 4. Handle 's' : Use short paths (File doesn't have to exist) */ if (wmemchr(firstModifier, 's', modifierLen) != NULL) { if (finaloutput[0] != 0x00) lstrcatW(finaloutput, L" "); if (exists) { GetShortPathNameW(fullfilename, fullfilename, ARRAY_SIZE(fullfilename)); } else { WIN32_FILE_ATTRIBUTE_DATA dirInfo; int i_end = lstrlenW(fullfilename); int i_cut = i_end; i = i_end; while (i-- > 0) { /* Cut the last element of the path chain until the path resolves to a existing directory */ if (fullfilename[i] == L'\\' || fullfilename[i] == L'/') { /* Undo the previous cut */ if (i_cut < i_end) fullfilename[i_cut] = L'\\'; fullfilename[i] = 0x00; i_cut = i; if (GetFileAttributesExW(fullfilename, GetFileExInfoStandard, &dirInfo) != FALSE) { /* Keep the non-existing end of the path chain and append it to the new short path */ lstrcpyW(&thisoutput[1], &fullfilename[i_cut + 1]); thisoutput[0] = L'\\'; GetShortPathNameW(fullfilename, fullfilename, ARRAY_SIZE(fullfilename)); lstrcatW(fullfilename, thisoutput); break; } } } } } Unfortunately I can't test this at the moment so I would be happy if someone could perhaps take this on. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 --- Comment #4 from Eric Pouech <eric.pouech(a)gmail.com> --- the hard part here is to ensure that the modification will not break any other existing program the claim cmd %~s should behave as winepath has to be proven (esp. when part of the path don't exist) -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 --- Comment #5 from tncgyp+uypezc35u0dyxed6tszn0wk59xjphxb2gcxycxno8mxg4od48(a)sharklasers.com --- I wouldn't say in general that cmd %~s should behave like winepath -s. Wine's cmd %~s should behave like Microsoft's cmd %~s. That means the existing part of the path is converted to short format and the non-existing part remains unchanged. After some playing around I can say that winepath -s seems to do exactly that, i.e. winepath -s is at least significantly closer to Microsoft's cmd %~s than Wine's current cmd %~s. All winepath -s does to achieve this is to call GetShortPathNameW, nothing else. The proposed modification therefore simplifies to: /* 4. Handle 's' : Use short paths (File doesn't have to exist) */ if (wmemchr(firstModifier, 's', modifierLen) != NULL) { if (finaloutput[0] != 0x00) lstrcatW(finaloutput, L" "); GetShortPathNameW(fullfilename, fullfilename, ARRAY_SIZE(fullfilename)); } I think this modification can only break batch scripts written exclusively for Wine that rely on the current cmd %~s behavior. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
https://bugs.winehq.org/show_bug.cgi?id=56399 --- Comment #6 from tncgyp+uypezc35u0dyxed6tszn0wk59xjphxb2gcxycxno8mxg4od48(a)sharklasers.com --- Addendum: Ok, I was also able to create cases where GetShortPathNameW fails, so forgot about my last post. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
participants (1)
-
WineHQ Bugzilla