diff --git a/src/lfn.c b/src/lfn.c index 4e28ca18..6b63da0b 100644 --- a/src/lfn.c +++ b/src/lfn.c @@ -18,7 +18,6 @@ BOOL IsFATName(LPTSTR pName); - /* WFFindFirst - * * returns: @@ -86,8 +85,16 @@ WFFindFirst( if (lpFind->hFindFile != INVALID_HANDLE_VALUE) { lpFind->dwAttrFilter = dwAttrFilter; - 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); @@ -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) @@ -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; } diff --git a/src/treectl.c b/src/treectl.c index 43926564..45c2ddc3 100644 --- a/src/treectl.c +++ b/src/treectl.c @@ -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); @@ -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; @@ -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; +} ///////////////////////////////////////////////////////////////////// @@ -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 @@ -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)); } } @@ -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); + } } } @@ -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 @@ -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); @@ -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; @@ -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); @@ -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. @@ -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))); } @@ -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 diff --git a/src/wfdirrd.c b/src/wfdirrd.c index 47b8e8be..8448cbd3 100644 --- a/src/wfdirrd.c +++ b/src/wfdirrd.c @@ -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