Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/lfn.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

BOOL IsFATName(LPTSTR pName);


/* WFFindFirst -
*
* returns:
Expand Down Expand Up @@ -86,8 +85,16 @@ WFFindFirst(

if (lpFind->hFindFile != INVALID_HANDLE_VALUE) {
lpFind->dwAttrFilter = dwAttrFilter;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary as lpFind->fd.dwFileAttributes was already combined with ATTR_USED.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lpFind->fd.dwFileAttributes are combined with ATTR_USED, then ATTR_JUNCTION/ATTR_SYMBOLIC are added (which are not part of ATTR_USED), then this compare occurs. The intention was not to compare against ATTR_JUNCTION/ATTR_SYMBOLIC. Another approach would be to perform this compare, and if the entry is filtered call FindNext (which adds them); if the entry is not filtered then add them here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to the alternate approach which avoids the back-and-forth conversion, effectively setting ATTR_JUNCTION/ATTR_SYMBOLIC after the decision to return the entry has already been made.

if ((~dwAttrFilter & lpFind->fd.dwFileAttributes) == 0L ||
WFFindNext(lpFind)) {
if ((~dwAttrFilter & lpFind->fd.dwFileAttributes) == 0L) {
if (lpFind->fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
if (lpFind->fd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) {
lpFind->fd.dwFileAttributes |= ATTR_JUNCTION;
} else if (lpFind->fd.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
lpFind->fd.dwFileAttributes |= ATTR_SYMBOLIC;
}
}
return(TRUE);
} else if (WFFindNext(lpFind)) {
return(TRUE);
} else {
WFFindClose(lpFind);
Expand All @@ -103,8 +110,8 @@ WFFindFirst(
/* WFFindNext -
*
* Performs a single file FindNext operation. Only returns TRUE if a
* file matching the dwAttrFilter is found. On failure WFFindClose is
* called.
* file matching the dwAttrFilter is found. On failure the caller is
* expected to call WFFindClose.
*/
BOOL
WFFindNext(LPLFNDTA lpFind)
Expand Down Expand Up @@ -139,7 +146,16 @@ WFFindNext(LPLFNDTA lpFind)
lstrcpy(lpFind->fd.cFileName, lpFind->fd.cAlternateFileName);
}

if (lpFind->fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
if (lpFind->fd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) {
lpFind->fd.dwFileAttributes |= ATTR_JUNCTION;
} else if (lpFind->fd.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
lpFind->fd.dwFileAttributes |= ATTR_SYMBOLIC;
}
}

Wow64RevertWow64FsRedirection(oldValue);

lpFind->err = 0;
return TRUE;
}
Expand Down
81 changes: 72 additions & 9 deletions src/treectl.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ ScanDirLevel(PDNODE pParentNode, LPTSTR szPath, DWORD view)
{
BOOL bFound;
LFNDTA lfndta;
BOOL bExclude;

/* Add '*.*' to the current path. */
lstrcpy(szMessage, szPath);
Expand All @@ -178,9 +179,18 @@ ScanDirLevel(PDNODE pParentNode, LPTSTR szPath, DWORD view)

while (bFound)
{
/* Is this a junction and are those displayed? */
bExclude = FALSE;
if ((view & ATTR_JUNCTION) == 0 &&
(lfndta.fd.dwFileAttributes & ATTR_JUNCTION)) {

bExclude = TRUE;
}

/* Is this not a '.' or '..' directory? */
if (!ISDOTDIR(lfndta.fd.cFileName) &&
(lfndta.fd.dwFileAttributes & ATTR_DIR)) {
(lfndta.fd.dwFileAttributes & ATTR_DIR) &&
!bExclude) {

pParentNode->wFlags |= TF_HASCHILDREN;
bFound = FALSE;
Expand Down Expand Up @@ -482,6 +492,39 @@ wfYield()
}
}

/////////////////////////////////////////////////////////////////////
//
// Name: WFFindNextNonJunction
//
// Synopsis: Returns the next non-junction entry, which may be the
// current entry. Continually calls WFFindNext so long as
// the current entry is a junction.
//
// lpFind Pointer to the find context, which may (or may
// not) be advanced to a later entry.
//
// Return: TRUE = non-junction successfully found
// FALSE = no non-junction remaining.
BOOL
WFFindNextNonJunction(LPLFNDTA lpFind)
{
BOOL bFound;

bFound = TRUE;

while (bFound)
{
// If it's not a junction, return it.
if (!(lpFind->fd.dwFileAttributes & ATTR_JUNCTION))
{
return bFound;
}

bFound = WFFindNext(lpFind);
}

return bFound;
}


/////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -663,6 +706,14 @@ ReadDirLevel(
lstrcpy(szMessage, szPath);

bFound = WFFindFirst(&lfndta, szMessage, dwAttribs);

//
// if junctions are not displayed, continue to the next non-junction
//
if (bFound && !(dwAttribs & ATTR_JUNCTION))
{
bFound = WFFindNextNonJunction(&lfndta);
}
}

// for net drive case where we can't actually see what is in these
Expand Down Expand Up @@ -787,7 +838,7 @@ ReadDirLevel(
goto DONE;
}
} else if (dwView & VIEW_PLUSES) {
ScanDirLevel(pNode, szPath, dwAttribs & ATTR_HS);
ScanDirLevel(pNode, szPath, dwAttribs & (ATTR_HS | ATTR_JUNCTION));
}
}

Expand Down Expand Up @@ -837,6 +888,14 @@ ReadDirLevel(
else
{
bFound = WFFindNext(&lfndta); // get it from dos

//
// if junctions are not displayed, continue to the next non-junction
//
if (bFound && !(dwAttribs & ATTR_JUNCTION))
{
bFound = WFFindNextNonJunction(&lfndta);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block and the one above at line 676 are doing essentially the same thing. Can we create a method to "SkipJunctionPoints" or something like that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

Expand Down Expand Up @@ -932,7 +991,7 @@ StealTreeData(
// we need to match on these attributes as well as the name
//
dwView = GetWindowLongPtr(GetParent(hwndTC), GWL_VIEW) & VIEW_PLUSES;
dwAttribs = GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS) & ATTR_HS;
dwAttribs = GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS) & (ATTR_HS | ATTR_JUNCTION);

//
// get the dir of this new window for compare below
Expand All @@ -948,7 +1007,7 @@ StealTreeData(
(hwndT != hwndTC) &&
!GetWindowLongPtr(hwndT, GWL_READLEVEL) &&
(dwView == (DWORD)(GetWindowLongPtr(hwndSrc, GWL_VIEW) & VIEW_PLUSES)) &&
(dwAttribs == (DWORD)(GetWindowLongPtr(hwndSrc, GWL_ATTRIBS) & ATTR_HS))) {
(dwAttribs == (DWORD)(GetWindowLongPtr(hwndSrc, GWL_ATTRIBS) & (ATTR_HS | ATTR_JUNCTION)))) {

SendMessage(hwndSrc, FS_GETDIRECTORY, COUNTOF(szSrc), (LPARAM)szSrc);
StripBackslash(szSrc);
Expand Down Expand Up @@ -1084,7 +1143,8 @@ FillTreeListbox(HWND hwndTC,

if (pNode) {

dwAttribs = ATTR_DIR | (GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS) & ATTR_HS);
dwAttribs = GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS);
dwAttribs = ATTR_DIR | (dwAttribs & (ATTR_HS | ATTR_JUNCTION));
cNodes = 0;
bCancelTree = FALSE;

Expand Down Expand Up @@ -1155,7 +1215,8 @@ FillOutTreeList(HWND hwndTC,

SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);

dwAttribs = ATTR_DIR | (GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS) & ATTR_HS);
dwAttribs = GetWindowLongPtr(GetParent(hwndTC), GWL_ATTRIBS);
dwAttribs = ATTR_DIR | (dwAttribs & (ATTR_HS | ATTR_JUNCTION));

// get path to node that already exists in tree; will start reading from there
GetTreePath(pNode, szExists);
Expand Down Expand Up @@ -1861,6 +1922,7 @@ ExpandLevel(HWND hWnd, WPARAM wParam, INT nIndex, LPTSTR szPath)
INT iExpandInView;
INT iCurrentIndex;
RECT rc;
DWORD dwAttribs;

//
// Don't do anything while the tree is being built.
Expand Down Expand Up @@ -1916,8 +1978,9 @@ ExpandLevel(HWND hWnd, WPARAM wParam, INT nIndex, LPTSTR szPath)

if (IsTheDiskReallyThere(hWnd, szPath, FUNC_EXPAND, FALSE))
{
ReadDirLevel(hWnd, pNode, szPath, pNode->nLevels + 1, nIndex,
(DWORD)(ATTR_DIR | (GetWindowLongPtr(GetParent(hWnd), GWL_ATTRIBS) & ATTR_HS)),
dwAttribs = GetWindowLongPtr(GetParent(hWnd), GWL_ATTRIBS);
dwAttribs = ATTR_DIR | (dwAttribs & (ATTR_HS | ATTR_JUNCTION));
ReadDirLevel(hWnd, pNode, szPath, pNode->nLevels + 1, nIndex, dwAttribs,
(BOOL)wParam, NULL, IS_PARTIALSORT(DRIVEID(szPath)));
}

Expand Down Expand Up @@ -2355,7 +2418,7 @@ TreeControlWndProc(
lstrcpy(szPath, (LPTSTR)lParam);
ScanDirLevel( (PDNODE)pNodeT,
szPath,
(GetWindowLongPtr(hwndParent, GWL_ATTRIBS) & ATTR_HS));
(GetWindowLongPtr(hwndParent, GWL_ATTRIBS) & (ATTR_HS | ATTR_JUNCTION)));

//
// Invalidate the window so the plus gets drawn if needed
Expand Down
20 changes: 1 addition & 19 deletions src/wfdirrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -906,25 +906,7 @@ CreateDTABlockWorker(
//
// be safe, zero unused DOS dta bits
//
lfndta.fd.dwFileAttributes &= ATTR_USED;

//
// if reparse point, figure out whether it is a junction point
if (lfndta.fd.dwFileAttributes & ATTR_REPARSE_POINT)
{
DWORD tag = DecodeReparsePoint(szPath, pName, szLinkDest, COUNTOF(szLinkDest));

if (tag == IO_REPARSE_TAG_MOUNT_POINT)
lfndta.fd.dwFileAttributes |= ATTR_JUNCTION;

else if (tag == IO_REPARSE_TAG_SYMLINK)
lfndta.fd.dwFileAttributes |= ATTR_SYMBOLIC;

else
{
// DebugBreak();
}
}
lfndta.fd.dwFileAttributes &= (ATTR_USED | ATTR_JUNCTION | ATTR_SYMBOLIC);

//
// filter unwanted stuff here based on current view settings
Expand Down