4

When I try to create a directory junction to a windows drive that does not yet exist, I get the following message:

C:\>mklink H H:\ /J
Local volumes are required to complete the operation.

I want to have a directory on windows that connect every drive letter to a corresponding letter in that directory. I want to share media from any external device through an application without having to change settings when "new" drive letters show up.

It seems like Symbolic links can point to non-existent targets because the operating system does not check to see if the target exists, but they cant link to nonexistent drives. Are there any known solutions to setting up such a directory junction?

One solution is to make a directory symbolic link (by using the /D flag instead of the /J flag), but that is not what I am looking for, I want a directory junction.

3
  • Why is a directory junction not good enough?
    – LPChip
    Dec 7, 2014 at 18:09
  • What about the /h option (hard-link)? You can archieve that while using a substitude drive (subst h:)
    – LPChip
    Dec 7, 2014 at 18:11
  • @LPChip (1) I want a directory junction (/J flag) so that the links are resolved server-side if I want to share this directory through a network. (2) I will try the /h option and give some feedback (I first have to sort out some admin privileges, sigh) Dec 7, 2014 at 19:51

1 Answer 1

5

Only Junctions are possible for this
Use SUBST to trick the OS.
It's quite important to use a parent folder with /deny Everyone:(S,RD) to block the OS from crawling in endless loop while doing maintenance. Like Search, Search indexer, Antivirus, File History, who knows what else.

details and script below


I see you got understanding of most of the following, so let's just sum it up for others.

Symlinks
Directory Sym-links and Junctions are very different things.
The major difference which should concern you is, that you can't access sym-links on remote computer which links to local paths of that remote computer. Sym-link to F:\ on remote computer will try to open local PC's F:\ instead.
Sym-link is like a link file which contains info about the real object's path. You can sym-link to whatever, even relative paths.
You can create a directory sym-link to a nonexistent drive, but that will not help you over LAN

Junction is a NTFS thing. But while a Junction must be on NTFS, it can point to a folder on other FS. It "re-directs" access to the junctioned folder. You can access junctions on remote machines pointing to remote folders.
Watch out for permissions. both of target Directory and Junction. (icacls with /L)

For files, there are file sym-links and hardlinks. There are no hardlinks for Directory, but Junction is quite a close thing to it. Hardlinks are multiple file records pointing to the same position on a drive. For that reason, you can't hardlink across drives.

Note: Junctions shouldn't be created to link dynamic places. It's working ok, even if a different FS is mounted as the same letter, but it's not a supported way. You should create a share for each drive. But that would make a mess in Network Locations and there would be no way to control access using permissions.


This is a cut from my customization script. It's portable, put it in a bat file and run as Admin.

  • creates Drives share, with Junction points to drives of letters from the whole alphabet. Share Drives will be accessible by any Authenticated user. (not Guest and User without password) Users will have the same access as if logged in locally, but UAC will not come to give elevated access even for Admins.
  • creates Download-Private share for current user's Downloads - just remove the section if you don't want it
  • Folders of these two Shares are placed in "%PUBLIC%\Private shares" e.g. "c:\Users\Public\Private shares" This folder will be directly inaccessible to avoid background services to end up in a loop. You can still access folders inside it directly by writing full path in address bar, or by creating a windows shortcut to it
  • to tweak permissions for the whole folder edit "Private shares", but to tweak for certain drive letters, you must use icacls with /L parameter

echo. & echo === "Private shares"

echo *** Creating Folders
rem --- Private shares - inheriting Authenticated Users access from Public folder
if not exist "%PUBLIC%\Private shares" mkdir "%PUBLIC%\Private shares"
rem - remove DENY temporarily
icacls "%PUBLIC%\Private shares" /remove:d Everyone 2>nul
if not exist "%PUBLIC%\Private shares\Drives" mkdir "%PUBLIC%\Private shares\Drives"

echo *** Creating Downloads-Private share
echo *   Creating link
mklink /J "%PUBLIC%\Private shares\Downloads-%USERNAME%" "%USERPROFILE%\Downloads"
echo *   Creating shares
net share Downloads-Private /delete 2>nul
net share Downloads-Private="%PUBLIC%\Private shares\Downloads-%USERNAME%" /unlimited /remark:"Only for authenticated users" /grant:everyone,FULL

echo *** Creating Drives share
echo *   Creating link
for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    subst %%a: \
    mklink /J "%PUBLIC%\Private shares\Drives\%%a" %%a:\
    subst %%a: /d
)

echo *   Creating shares
net share Drives /delete 2>nul
rem - /grant:everyone,FULL --- No worry, this is on Microsoft's recommendation. Grant full access to shares and handle access through permissions. It's more portable, safer and simpler.
net share Drives="%PUBLIC%\Private shares\Drives" /unlimited /remark:"Only for authenticated users" /grant:everyone,FULL

echo *** Changing "Private share" permissions
rem - this is the same way as Windows is handling legacy folders inside Users directory
rem   this must be done, or many services will keep crawling though an endless path loop
icacls "%PUBLIC%\Private shares" /deny Everyone:(S,RD)

If you need to remove the folder which is created using this script, you need to unlock it using Properties-Permission, or by this command run as Admin: icacls "%PUBLIC%\Private shares" /remove:d Everyone
Don't keep this folder unlocked, delete it right after, or lock it again using icacls "%PUBLIC%\Private shares" /deny Everyone:(S,RD)


EDIT 2019: I am using PowerShell for this now. This is the part, which creates all drives shares (it does nearly the same as Batch above):

$aclFSR_Syn_ReadData = [System.Security.AccessControl.FileSystemRights]::Synchronize -bor [System.Security.AccessControl.FileSystemRights]::ReadData
$aclInh_None = [System.Security.AccessControl.InheritanceFlags]::None
$aclProp_NoFlags = [System.Security.AccessControl.PropagationFlags]::None
$aclT_Deny = [System.Security.AccessControl.AccessControlType]::Deny
$aclRule_Interactive_SRD_NoInh_Deny = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList 'INTERACTIVE', $aclFSR_Syn_ReadData, $aclInh_None, $aclProp_NoFlags, $aclT_Deny

$PathPrivate = 'C:\PATH\TO\SHARED_LOCAL_FOLDER

$aclDrives = Get-Acl -Path "$PathPrivate\Drives"

# - remove DENY temporarily
[void]$aclDrives.RemoveAccessRuleAll($aclRule_Interactive_SRD_NoInh_Deny)
Set-Acl -Path "$PathPrivate\Drives" -AclObject $aclDrives

# --- Drives Share
Write-Host "`n - Drives Share"

Write-Host "Linking drives: " -NoNewline
foreach ($d in @("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")) {
    Write-Host "$d, " -NoNewline
    if (-not (Get-PSDrive -Name $d -ErrorAction SilentlyContinue)) {
        New-PSDrive -Name $d -PSProvider FileSystem -Root '\' | Out-Null
        $tmpDrive = $true
    } else { $tmpDrive = $false }
    if (-not (Test-Path -Path "$PathPrivate\Drives\$d")) { New-Item -Path "$PathPrivate\Drives\$d" -ItemType Junction -Value "${d}:\" | Out-Null }
    if ($tmpDrive) { Remove-PSDrive -Name $d }
}
Write-Host ''

Remove-SmbShare -Name 'Drives' -Confirm:$false -ErrorAction SilentlyContinue
New-SmbShare -Name 'Drives' -Path "$PathPrivate\Drives" -Description 'Only for authenticated users' -FullAccess Everyone | Out-Null

Write-Host "Applying permissions for Drives"
# - Blocking access to Private share folder to avoid searcher loops
[void]$aclDrives.AddAccessRule($aclRule_Interactive_SRD_NoInh_Deny)

# - limit access to authorized accounts only (optional)
# [void]$aclDrives.AddAccessRule($YOUR_ACL_RULE_TO_LIMIT_THE_SHARE)

Set-Acl -Path "$PathPrivate\Drives" -AclObject $aclDrives
2
  • If someone can confirm that this script works, I will mark this as the correct answer. I don't currently have a windows machine. Jun 20, 2016 at 14:18
  • Astounding answer.
    – T.Todua
    Jan 6, 2021 at 18:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .