DIR reports meaningless SYMLINK information

Feb 12, 2019
10
0
DIR %USERPROFILE%\AppData\Local\microsoft\windowsapps shows a bunch of "SYMLINKS" though they're actually IO_REPARSE_TAG_APPEXECLINK, not SYMLINK. But I digress.

What's supposed to appear in the brackets on the right? For an actual symbolic link it appears to be the target e.g.
7/31/2019 19:01 <SYMLINK> python3.7.exe [C:\Users\howardk\AppData\Local\microsoft\windowsapps\python3.7.exe]
but there's 20+ IO_REPARSE_TAG_* definitions. What's expected for non-symlinks tags?

Do you just fill in the absolute path for the reparse point if there's an error, or it's a tag you don't recognize, or...? Current behavior seems kinda pointless.

DIR /REPARSE:TAGNAME to show APPEXECLINK etc instead of SYMLINK for all would be nice.
DIR /REPARSE:VERBOSE to show more details about the reparse point in the brackets would be nice.

Enhancement request?...
 
May 20, 2008
11,415
99
Syracuse, NY, USA
Can someone explain all this to me?

TCC v24 shows this.

Code:
c:\users\vefatica\appdata\local\microsoft\windowsapps> dir /k /m excel.exe
2019-08-31  14:02               0  excel.exe [C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe]

c:\users\vefatica\appdata\local\microsoft\windowsapps> attrib excel.exe
___A____L________  C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe

TCC v25 shows this.

Code:
c:\users\vefatica\appdata\local\microsoft\windowsapps> dir /k /m excel.exe
2019-08-31  14:02               0  excel.exe

c:\users\vefatica\appdata\local\microsoft\windowsapps> attrib excel.exe
___A_____________  C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe

CMD shows this.

Code:
C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps> dir excel.exe
 Volume in drive C is OS
 Volume Serial Number is 547B-A92D

 Directory of C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps

2019-08-31  14:02                 0 excel.exe
               1 File(s)              0 bytes
               0 Dir(s)  458,879,655,936 bytes free

C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps> attrib excel.exe
The target of the symbolic link C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe does not exist

There must be something right about this EXCEL.EXE because CMD can execute it. TCC can't (why not?).

Code:
c:\users\vefatica\appdata\local\microsoft\windowsapps> excel.exe
TCC: (Sys) The file cannot be accessed by the system.
 "C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe"
 

rconn

Administrator
Staff member
May 14, 2008
12,364
150
TCC attempts to determine the file (subsystem) type so it can execute it properly. Windows is returning an error (1920 - "The file cannot be accessed by the system"), so TCC doesn't go any further.

CMD doesn't make that call (or support all the subsystem types), and only tries to call CreateProcess (which works).

But my question is - why do you think that TCC *should* be executing that (well hidden) file?
 
May 20, 2008
11,415
99
Syracuse, NY, USA
But my question is - why do you think that TCC *should* be executing that (well hidden) file?
Which well hidden file?

"C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe" is the one TCC gets from %PATH.

It's a IO_REPARSE_TAG_APPEXECLINK.

That link points to C:\Program Files\WindowsApps\Microsoft.Office.Desktop.Excel_16051.11929.20254.0_x86__8wekyb3d8bbwe\Office16\EXCEL.exe.
 
May 20, 2008
11,415
99
Syracuse, NY, USA
You can avoid the 1920 error like this (for example).

Code:
 HANDLE hFile = CreateFile(L"c:\\users\\vefatica\\appdata\\local\\microsoft\\windowsapps\\excel.exe", 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);

With some defs and typedefs you can find HERE (or you may have already) you can get the target of the link. For example (this is crude):

Code:
    HANDLE hFile = CreateFile(L"c:\\users\\vefatica\\appdata\\local\\microsoft\\windowsapps\\excel.exe", 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);

    BYTE buf[4096];
    DWORD dwReturned;

    BOOL bOK = DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buf, 4096, &dwReturned, NULL);

    if ( bOK )
        wprintf(L"Returned: %lu bytes\n", dwReturned);
    else
    {
        wprintf(L"DeviceIoControl failed; last error = %lu\n", GetLastError());
        return -1;
    }

    REPARSE_DATA_BUFFER *p = (REPARSE_DATA_BUFFER*) buf;

    wprintf(L"Reparse tag: %x\n", p->ReparseTag);

    WCHAR *q = (WCHAR*) p->AppExecLinkReparseBuffer.StringList; // multi-string list

    for ( INT i=0; i<p->AppExecLinkReparseBuffer.StringCount; i++ )
    {
        wprintf(L"String %d: %s\n", i, q);
        while ( *q++ != 0 );
    }

It produces this.

Code:
Returned: 420 bytes
Reparse tag: 8000001b
String 0: Microsoft.Office.Desktop_8wekyb3d8bbwe
String 1: Microsoft.Office.Desktop_8wekyb3d8bbwe!Excel
String 2: C:\Program Files\WindowsApps\Microsoft.Office.Desktop.Excel_16051.11929.20254.0_x86__8wekyb3d8bbwe\Office16\EXCEL.exe
 

rconn

Administrator
Staff member
May 14, 2008
12,364
150
Which well hidden file?

"C:\Users\vefatica\AppData\Local\Microsoft\WindowsApps\excel.exe" is the one TCC gets from %PATH.

It's a IO_REPARSE_TAG_APPEXECLINK.

That link points to C:\Program Files\WindowsApps\Microsoft.Office.Desktop.Excel_16051.11929.20254.0_x86__8wekyb3d8bbwe\Office16\EXCEL.exe.

How is it not? An undocumented file type in a hidden/system directory returning a Windows error?
 
May 20, 2008
11,415
99
Syracuse, NY, USA
How is it not? An undocumented file type in a hidden/system directory returning a Windows error?
I'm not sure what to say. I didn't invent this scenario. I'm trying to help. Microsoft chose to put those links (of undocumented type) in the PATH, so that's what TCC finds first when I give a command like "excel". TCC can't open the file and it gives up. I wanted excel to run and it doesn't.
 
May 20, 2008
11,415
99
Syracuse, NY, USA
@vefatica

Maybe a BIT more info about the IO_REPARSE_TAG_APPEXECLINK here (if you need):

https://tyranidslair.blogspot.com/2019/09/overview-of-windows-execution-aliases.html
Interesting! If that's correct, then the info I found is a bit inaccurate. I found this:

Code:
        // Structure for IO_REPARSE_TAG_APPEXECLINK
        struct
        {
            ULONG StringCount;                  // Number of the strings in the StringList, separated by '\0'
            WCHAR StringList[1];                // Multistring (strings separated by '\0', terminated by '\0\0')
        } AppExecLinkReparseBuffer;

The strings acutally number 4 and there's not a double NUL at the end. And the ULONG 3 at the beginning of the data may well be a version number. This can be seen with Windows's FSUTIL.EXE.

Code:
c:\users\vefatica\appdata\local\microsoft\windowsapps> fsutil reparsepoint query excel.exe
Reparse Tag Value : 0x8000001b
Tag value: Microsoft

Reparse Data Length: 0x0000019c
Reparse Data:
0000:  03 00 00 00 4d 00 69 00  63 00 72 00 6f 00 73 00  ....M.i.c.r.o.s.
0010:  6f 00 66 00 74 00 2e 00  4f 00 66 00 66 00 69 00  o.f.t...O.f.f.i.
0020:  63 00 65 00 2e 00 44 00  65 00 73 00 6b 00 74 00  c.e...D.e.s.k.t.
0030:  6f 00 70 00 5f 00 38 00  77 00 65 00 6b 00 79 00  o.p._.8.w.e.k.y.
0040:  62 00 33 00 64 00 38 00  62 00 62 00 77 00 65 00  b.3.d.8.b.b.w.e.
0050:  00 00 4d 00 69 00 63 00  72 00 6f 00 73 00 6f 00  ..M.i.c.r.o.s.o.
0060:  66 00 74 00 2e 00 4f 00  66 00 66 00 69 00 63 00  f.t...O.f.f.i.c.
0070:  65 00 2e 00 44 00 65 00  73 00 6b 00 74 00 6f 00  e...D.e.s.k.t.o.
0080:  70 00 5f 00 38 00 77 00  65 00 6b 00 79 00 62 00  p._.8.w.e.k.y.b.
0090:  33 00 64 00 38 00 62 00  62 00 77 00 65 00 21 00  3.d.8.b.b.w.e.!.
00a0:  45 00 78 00 63 00 65 00  6c 00 00 00 43 00 3a 00  E.x.c.e.l...C.:.
00b0:  5c 00 50 00 72 00 6f 00  67 00 72 00 61 00 6d 00  \.P.r.o.g.r.a.m.
00c0:  20 00 46 00 69 00 6c 00  65 00 73 00 5c 00 57 00   .F.i.l.e.s.\.W.
00d0:  69 00 6e 00 64 00 6f 00  77 00 73 00 41 00 70 00  i.n.d.o.w.s.A.p.
00e0:  70 00 73 00 5c 00 4d 00  69 00 63 00 72 00 6f 00  p.s.\.M.i.c.r.o.
00f0:  73 00 6f 00 66 00 74 00  2e 00 4f 00 66 00 66 00  s.o.f.t...O.f.f.
0100:  69 00 63 00 65 00 2e 00  44 00 65 00 73 00 6b 00  i.c.e...D.e.s.k.
0110:  74 00 6f 00 70 00 2e 00  45 00 78 00 63 00 65 00  t.o.p...E.x.c.e.
0120:  6c 00 5f 00 31 00 36 00  30 00 35 00 31 00 2e 00  l._.1.6.0.5.1...
0130:  31 00 31 00 39 00 32 00  39 00 2e 00 32 00 30 00  1.1.9.2.9...2.0.
0140:  32 00 35 00 34 00 2e 00  30 00 5f 00 78 00 38 00  2.5.4...0._.x.8.
0150:  36 00 5f 00 5f 00 38 00  77 00 65 00 6b 00 79 00  6._._.8.w.e.k.y.
0160:  62 00 33 00 64 00 38 00  62 00 62 00 77 00 65 00  b.3.d.8.b.b.w.e.
0170:  5c 00 4f 00 66 00 66 00  69 00 63 00 65 00 31 00  \.O.f.f.i.c.e.1.
0180:  36 00 5c 00 45 00 58 00  43 00 45 00 4c 00 2e 00  6.\.E.X.C.E.L...
0190:  65 00 78 00 65 00 00 00  30 00 00 00              e.x.e...0...
 
May 20, 2008
11,415
99
Syracuse, NY, USA
Yes, I can't understand the EOF with the 0x30 (ASCII = 0) between ... definitive not 2 escaped 0 (null, byte 0) (ASCII = NUL) in a row ...
The whole thing is Unicode, so the '0' (actually L'0' in C) is 0x3000. And the 0x0000 after it is the Unicode NUL terminating the fourth and final Unicode string (L"0").

I imagine that whole thing came right out of the file system. Conveniences like EOFs and double NULs at the end of multiple strings are probably wasteful. All the user needs to know (and does) is the number of bytes of data.
 
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
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 WAD DIR /HL still gets names wrong Support 16
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