WAD DIR /HL still gets names wrong

May 20, 2008
11,414
99
Syracuse, NY, USA
I'm running build 18. Below, V: is a SUBST for H:\work. This happens in any subdirectory of any SUBST.
Code:
v:\empty> dir /hl

 Volume in drive V is DATA           Serial number is c007:d3e4
 Directory of  V:\empty\*

2016-05-14  22:00         <DIR>    .
2016-05-14  22:00         <DIR>    ..
2016-09-07  00:05         <DIR>    foo
                                    = V:\empty\work\empty\foo
2015-02-16  01:18         <DIR>    x64
                                    = V:\empty\work\empty\x64
2016-05-14  21:59               0  a
                                    = V:\empty\work\empty\a
                   0 bytes in 1 file and 4 dirs
       8,056,176,640 bytes free
 
May 20, 2008
11,414
99
Syracuse, NY, USA
Not a TCC bug - it's what the Windows API is returning.
That may be the case, but it's wrong. The two valid fully qualified names for one of those directories are these.

v:\empty\foo
and
h:\work\empty\foo

This one is meaningless.

V:\empty\work\empty\foo

Which API gives it?
 
Aug 3, 2016
376
9
Netherlands
Some remarks upfront:

- Hardlinks are ONLY possible on the same volume.
- Hardlinks are on sytem level, not userlevel
- a SUBST'ed folder is not a hardlink, neither is a network drive
- every file on the local filesystem is a hardlink in itself; it's only "interesting" if there are more than one to the same file.
- Windows comes with a hardlink utility: FSUTIL.exe. It behaves different on Win10 and Win7

A hardlink will get reported without a diskname (like "\Windows\notepad.exe"). So if in the output there is a drivename, it's "interpretation".
That's what you see here going wrong. The "non-interpreted" part (\work\empty\foo) is alright, but the "V:"-part gets interpreted wrong somewhere
(I guess something like @path[%1] / @path [%cd%], but then on programmers-level

FSUTIL syntax example:
fsutil hardlink list c:\Windows\notepad.exe
Output:
Code:
\Windows\notepad.exe
\Windows\winsxs\amd64_microsoft-windows-notepadwin_31bf3856ad364e35_6.1.7601.23403_none_a1830d5f2ac33b80\notepad.exe
 
Last edited:
May 20, 2008
11,414
99
Syracuse, NY, USA
Thanks, Maarten. It makes a little sense now. Maybe TCC should not implement DIR's /HL in a SUBST, or internally use @TRUENAME on everything in a SUBST.

Code:
v:\> echo %@truename[v:\empty\foo\]
H:\work\empty\foo\

v:\> fsutil hardlink list h:\work\empty\foo\
\work\empty\foo

v:\> fsutil hardlink list v:\empty\foo\
Error:  The directory is not a subdirectory of the root directory.

The FSUTIL utility requires a local NTFS volume.
 
Aug 3, 2016
376
9
Netherlands
I used @truename[ ] too in testing :-)

Actualy: I started with TRUENAME in a CMD-box, but this command no longer exists (a long time ago TRUENAME was an undocumented, hidden command in COMMAND.COM)
 
May 20, 2008
11,414
99
Syracuse, NY, USA
Another observation ... Above I pointed out that DIR /HL doesn't get names right in a subdirectory of a SUBST. In addition, it doesn't seem to do anything in the root directory of a SUBST.
Code:
w:\> subst
P:\: => L:\projects
S:\: => C:\Windows\system32
T:\: => H:\temp
U:\: => G:\uty
V:\: => H:\work
W:\: => C:\Windows

w:\> dir /m /k /hl no*
2009-07-13  21:14         179,712  notepad.exe

w:\> c:\Windows\

c:\windows> dir /m /k /hl no*
2009-07-13  21:14         179,712  notepad.exe
                                    = C:\Windows\System32\notepad.exe
                                    = C:\Windows\winsxs\x86_microsoft-windows-notepadwin_31bf3856ad364e35_6.1.7600.16385_none_42a023025c60a33a\notepad.exe
                                    = C:\Windows\winsxs\x86_microsoft-windows-notepad_31bf3856ad364e35_6.1.7600.16385_none_6ef0e39ed15350e4\notepad.exe
 
May 20, 2008
11,414
99
Syracuse, NY, USA
And, no surprise, LINKS behaves the same.
Code:
w:\> subst
P:\: => L:\projects
S:\: => C:\Windows\system32
T:\: => H:\temp
U:\: => G:\uty
V:\: => H:\work
W:\: => C:\Windows

w:\> links notepad.exe

w:\> c:\windows\

c:\windows> links notepad.exe
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe
C:\Windows\winsxs\x86_microsoft-windows-notepadwin_31bf3856ad364e35_6.1.7600.16385_none_42a023025c60a33a\notepad.exe
C:\Windows\winsxs\x86_microsoft-windows-notepad_31bf3856ad364e35_6.1.7600.16385_none_6ef0e39ed15350e4\notepad.exe
 
May 20, 2008
11,414
99
Syracuse, NY, USA
... which is odd because (given the limitations previously discussed) FindFirstFileNameW (et al.) is OK with files in the root of a SUBST. This code produces the expected four links. (Likewise if I CD to W:\ and use an unqualified file name.)
Code:
   DWORD dwLen;
   WCHAR szFile[MAX_PATH];
   HANDLE hFind = FindFirstFileNameW(L"w:\\notepad.exe", 0, &(dwLen = MAX_PATH), szFile);
   if ( hFind != NULL )
       do Printf(L"%s\r\n", szFile);
           while ( FindNextFileNameW(hFind, &(dwLen = MAX_PATH), szFile) );
   FindClose(hFind);
 
Aug 3, 2016
376
9
Netherlands
Nice find! You should consider a career as a beta-tester :-)
I think this has also to do with the "interpretation" part: there is no path to interpret (if that is a correct English word...) in these cases.
 
  • Like
Reactions: evensenm
May 20, 2008
11,414
99
Syracuse, NY, USA
Nice find! You should consider a career as a beta-tester :-)
I think this has also to do with the "interpretation" part: there is no path to interpret (if that is a correct English word...) in these cases.
I think it'd work if you passed the filename, as specified by the user (the API doesn't seem to mind if that involves a SUBST and a qualified or unqualified filename), then prepend to the result the real drive letter (only) with a colon.

For example, the API can deal with "w:\notepad.exe" (or "notepad.exe" if the current directory is w:\) and would return
Code:
\Windows\System32\notepad.exe
\Windows\notepad.exe
\Windows\winsxs\x86_microsoft-windows-notepadwin_31bf3856ad364e35_6.1.7600.16385_none_42a023025c60a33a\notepad.exe
\Windows\winsxs\x86_microsoft-windows-notepad_31bf3856ad364e35_6.1.7600.16385_none_6ef0e39ed15350e4\notepad.exe

After discovering that w: is a SUBST for c:\windows, prepend only the "c:".
 
May 20, 2008
11,414
99
Syracuse, NY, USA
The original example is better in build 19.
Code:
v:\empty> dir /hl /m /k
2016-05-14  22:00         <DIR>    .
2016-05-14  22:00         <DIR>    ..
2016-09-07  00:05         <DIR>    foo
                                    = H:\work\empty\foo
2015-02-16  01:18         <DIR>    x64
                                    = H:\work\empty\x64
2016-05-14  21:59               0  a
                                    = H:\work\empty\a

But not with LINKS.
Code:
v:\> links v:\empty\foo
v:\empty\work\empty\foo
And not with LINKS or DIR /LH in the root of a SUBST.
Code:
v:\> links w:\notepad.exe

v:\> w:

w:\> links notepad.exe

w:\> dir /m /k /hl notepad.exe
2009-07-13  21:14         179,712  notepad.exe

w:\> v:

v:\> dir /m /k /hl w:\notepad.exe
2009-07-13  21:14         179,712  notepad.exe
 
Aug 3, 2016
376
9
Netherlands
... which is odd because (given the limitations previously discussed) FindFirstFileNameW (et al.) is OK with files in the root of a SUBST. This code produces the expected four links. (Likewise if I CD to W:\ and use an unqualified file name.)
Code:
   DWORD dwLen;
   WCHAR szFile[MAX_PATH];
   HANDLE hFind = FindFirstFileNameW(L"w:\\notepad.exe", 0, &(dwLen = MAX_PATH), szFile);
   if ( hFind != NULL )
       do Printf(L"%s\r\n", szFile);
           while ( FindNextFileNameW(hFind, &(dwLen = MAX_PATH), szFile) );
   FindClose(hFind);


Don't know which programming language this is (I'm not a programmer) . As far as I can see it, you are halfway in writing your own Take Command :-)

EDIT: Which of course then should be called "FAKE Command" ( FAtica's Kernel Eplorations )
Sorry, could not resist. :-D
I mean no harm, of course


Are those (FindFirstFileNameW, FindNextFileNameW) the API's you can call with @WINAPI ?
 
May 20, 2008
11,414
99
Syracuse, NY, USA
Don't know which programming language this is (I'm not a programmer) . As far as I can see it, you are halfway in writing your own Take Command :-)

EDIT: Which of course then should be called "FAKE Command" ( FAtica's Kernel Eplorations )
Sorry, could not resist. :-D
I mean no harm, of course


Are those (FindFirstFileNameW, FindNextFileNameW) the API's you can call with @WINAPI ?
Halfway? ... more like 1/1000000 of the way!

Those are functions in the Win32 API (for the "C" language). Don't be confused by the "32"; "Win32" is just a name. I'm quite sure those particular functions will not work with @WINAPI. For example, you could get started like this
Code:
v:\> echo %@winapi[kernel32.dll,FindFirstFileNameW,"c:\windows\notepad.exe",0,PDWORD=260,BUFFER]
\Windows\notepad.exe
But now, TCC has discarded (hope I'm wrong) the actual number that the function returned ... that number being a HANDLE to the search, and being required by the next function, FindNextFileNameW.

Perhaps a future TCC might get around this by letting pointer specs (locations in memory) be the names of environment variables where the input comes from and the output goes. Maybe something like this

set bufsize=260
set set buf="c:\windows\notepad.exe"
set FindHandle=%@winapi[kernel32.dll,FindFirstFileNameW,"c:\windows\notepad.exe",0,PDWORD=%%bufsize,BUFFER=%%buf]

Then you'd have FileHandle to use in the next function, the number of characters in the filename in %bufsize, and the name of the file in %buf.

But I'd bet (1) this would be hard and (2) it'll never make it to the top of Rex's to-do list.
 
Aug 3, 2016
376
9
Netherlands
Those are functions in the Win32 API (for the "C" language). Don't be confused by the "32"; "Win32" is just a name. I'm quite sure those particular functions will not work with @WINAPI. For example, you could get started like this
Code:
v:\> echo %@winapi[kernel32.dll,FindFirstFileNameW,"c:\windows\notepad.exe",0,PDWORD=260,BUFFER]
\Windows\notepad.exe
But now, TCC has discarded (hope I'm wrong) the actual number that the function returned ... that number being a HANDLE to the search, and being required by the next function, FindNextFileNameW.

I love the width and the depth of knowledge in this forum!
Your explanation is very clear (that is: I could understand it) Thanks for elaborating!

But now, TCC has discarded (hope I'm wrong) the actual number that the function returned ... that number being a HANDLE to the search, and being required by the next function, FindNextFileNameW.

Perhaps a future TCC might get around this by letting pointer specs (locations in memory) be the names of environment variables where the input comes from and the output goes. Maybe something like this

set bufsize=260
set set buf="c:\windows\notepad.exe"
set FindHandle=%@winapi[kernel32.dll,FindFirstFileNameW,"c:\windows\notepad.exe",0,PDWORD=%%bufsize,BUFFER=%%buf]

Then you'd have FileHandle to use in the next function, the number of characters in the filename in %bufsize, and the name of the file in %buf.

But I'd bet (1) this would be hard and (2) it'll never make it to the top of Rex's to-do list.

By the sound of it (the way I understand it), the @WINAPI call starts some sort of a session and retrieves information. My guess is this handle is session-based; the next time you ask the same question, you will get another handle (like @fileopen does)
When the @WINAPI call is done, the session will be closed and the handle "deleted" (or whatever happens with handles) and cannot be used for subsequent "calls".
So I think that will be very hard to build-in, indeed.

Well, that is my theory anyway (with zero facts to prove it ..)
 
May 20, 2008
11,414
99
Syracuse, NY, USA
By the sound of it (the way I understand it), the @WINAPI call starts some sort of a session and retrieves information. My guess is this handle is session-based; the next time you ask the same question, you will get another handle (like @fileopen does)
When the @WINAPI call is done, the session will be closed and the handle "deleted" (or whatever happens with the handle) and cannot be used for subsequent "calls".
So I think that will be very hard to build-in, indeed.

TCC is just calling the functions you specified It has no idea what you're trying to do or how the functions you call may interact with each other. As for sessions, it's more like this.

FindFirstFileNameW creates a session (a "find" session, if you like). That session is identified by a number (a HANDLE) which that function returns. In order to continue finding file names (with FindNextFileNameW) you have to identify the "find" session by giving FindNextFileNameW that handle. The HANDLE doesn't change; it continues to identify the find session until you're done (at which time you should use FindClose() on it so it doesn't hang around using 4 bytes of memory). TCC would have to let you know what that handle is so you can use it when you call FindNextFileNameW. I don't think that can be done as things are. When you use BUFFER in @WINAPI, @WINAPI[...] won't evaluate to the return value of the function; instead @WINAPI[...]'s value will be the string that the function put into the BUFFER
 
Aug 3, 2016
376
9
Netherlands
I had to read it 3 times, but now I understand.
It does not seem like a good idea to open up the API's this way. Things get messy on the TCC side and things get messy on the user side (they have to "handle" (sic!) all the handles and calls. No problem when a few, selected ones are exposed (like the @fileopen -family) but in general ..

I wasn't asking for this functionality, btw. Just trying to understand how things work...
 
Similar threads
Thread starter Title Forum Replies Date
E Fixed Bug with DIR /Z displaying descriptions Support 8
J Paths shown in DIR /B Support 2
K Fixed Prompt display will be shifted after use dir to display a filename with Chinese. (v25.00.28 x64) Support 18
Jesse Heines How to? How to display picture creation date with dir command Support 6
vefatica WAD DIR.BTM? Support 11
DrusTheAxe DIR reports meaningless SYMLINK information Support 14
C show file description? with dir? Support 8
vefatica DIR /F and streams? Support 7
rps Multi-column DIR /v not displaying all files. Support 5
R How to? Dir specific file search patterns with spaces in the pathnames? Support 6
rps Dir /Nfv -> Alt-F2 Support 2
rps @FILESIZE[....,a] allocated size not matching Dir results Support 8
A TCMD - Dir Command puts out blank lines? Support 16
S Problems with dir command in the debugger Support 5
M TCC incorrect dir output since Windows 1803 Support 6
x13 Problem listing repository files using DIR http(s)://... Support 8
cxxl dir /s works in mysterious ways :( Support 4
vefatica Help nit (FFIND and DIR with /S) Support 0
N Fixed Strange dir behavior Support 6
JohnQSmith Weird DIR output (missing lines) Support 1
C 7zip with date range .vs. filelist created with dir and daterange Support 0
D Towards shared (dir-)history lists Support 3
vefatica DIR /S /HL? Support 4
H Fixed DIR /G returns wrong sizes Support 2
nickles WAD dir.htm Support 2
vefatica DO dir in /s /a:+d /d"g:\" * ( ... ) Support 26
vefatica DIR \\.\...? Support 4
M Fixed DIR /S /B1 ignores "/S" Support 5
C tcmd.ini not loading from program dir? Support 5
D Fixed Dir /Nm:n has changed Support 1
rps How to? dir /s unexpected results Support 10
vefatica Update to current install dir? Support 8
cgunhouse Problem with "dir /=" Support 4
T dir /h error in empty directory Support 22
P WAD TC 15.0.1.58 x64 crasches with a simple dir command Support 18
CWBillow dir /4 strange Support 2
samintz WAD DIR /B1 and /X Support 2
nickles dir behaves inconsistently Support 5
vefatica DIR, streams, and wildcards? Support 1
vefatica DIR /: /u ... streams not counted? Support 7
vefatica Documentation DIR /B /S /: Support 2
samintz How to? DIR listing for exact match Support 1
dcantor WAD dir "ftp:// ..." fails in TCC 15 Support 7
T How to? dir/pdir - 2nd level down only Support 7
MikeBaas How to? DIR: supress extensions? Support 5
old coot dir /s dies on my C: drive Support 2
A WAD Dir daterange + multiple path wildcards crashes tcc Support 2
old coot TC DIR command has trouble on my SSD Support 2
M Fixed character set in dir/copy Support 3
C odd behavior of "dir" Support 0

Similar threads