如何检查目录符号 link 的目标是否存在?

How to check whether the target of a directory symbolic link exists?

我正在开发面向 Windows XP 的 Windows 应用程序。

我的应用需要将符号 link 解析为文件和文件夹。要检查目标是否存在,我可以使用 CreateFile 作为文件的符号 link。但是我在Google和MSDN上搜索了一整天后,发现如果需要获取一个目录的句柄,需要使用标志FILE_FLAG_BACKUP_SEMANTICS。这需要我的应用程序请求更高的权限。我知道很多用户对这种行为不满意,所以我需要找到另一种方法来检查目录符号 link 的目标是否存在。

我也看过Symbolic Link Effects on File Systems Functions。我可以用来测试文件或目录是否存在的其他函数都检查符号 link 本身,而不是它的目标。我已经尝试了一些函数,比如 _access_s。他们也只检查符号 link 本身。

所以我的问题是是否有任何方法可以在不需要更高权限的情况下检查目录符号 link 的目标是否存在。

I could use CreateFile for symbolic file to get the file handle and then check the file is exist or not.

如果在调用 CreateFile 中未指定 FILE_FLAG_OPEN_REPARSE_POINT 并且您获得文件句柄,这意味着存在符号 link/mount 点目标。所以已经不需要检查什么了。如果调用失败,因为目标不存在,最后一个错误将是 ERROR_FILE_NOT_FOUNDERROR_PATH_NOT_FOUND(也可能是 ERROR_BAD_PATHNAME

关于 FILE_FLAG_BACKUP_SEMANTICS - 这是 CreateFile api. this api internal call NtCreateFile. the FILE_FLAG_BACKUP_SEMANTICS mapped to FILE_OPEN_FOR_BACKUP_INTENT CreateOptions flag. this flag checked inside IopCheckBackupRestorePrivilege

的非常糟糕的设计

This function will determine if the caller is asking for any accesses that may be satisfied by Backup or Restore privileges, and if so, perform the privilege checks. If the privilege checks succeed, then the appropriate bits will be moved out of the RemainingDesiredAccess field in the AccessState structure and placed into the PreviouslyGrantedAccess field.

Note that access is not denied if the caller does not have either or both of the privileges, since he may be granted the desired access via the security descriptor on the object.

因此,即使调用者没有备份或恢复权限,也不会产生问题。

但是 NtCreateFile 有接下来的两个选项:FILE_DIRECTORY_FILEFILE_NON_DIRECTORY_FILE - 这让我们指定我们想要 create/open 文件还是目录。如果我们(可能)创建新项目 - 我们需要指定我们是要创建目录(必须设置 FILE_DIRECTORY_FILE)还是不创建目录(FILE_NON_DIRECTORY_FILE,但默认情况下假设这种情况 - 所以可选)。当我们打开文件时——这两个标志都是可选的——如果我们没有同时指定——这意味着我们不关心我们打开的是文件还是目录。如果我们关心这个 - 需要指定其中一个标志。

但是如果查看 CreateFile 可见不存在显式映射到 FILE_DIRECTORY_FILEFILE_NON_DIRECTORY_FILE 的选项。 CreateFile 用于此 .. FILE_FLAG_BACKUP_SEMANTICS 选项。在我看来,这是非常不合逻辑的,但事实就是如此。当 FILE_FLAG_BACKUP_SEMANTICS 未设置 CreateFile 时,为 NtCreateFile 传递 FILE_NON_DIRECTORY_FILE 选项。当它设置时 - 通过 FILE_OPEN_FOR_BACKUP_INTENT 不通过 FILE_NON_DIRECTORY_FILE。这允许您打开文件或目录。并且没有设置 FILE_DIRECTORY_FILE 的选项 - 因为此 CreatrFile 无法创建新目录。

所以 FILE_DIRECTORY_FILEFILE_NON_DIRECTORY_FILE 有单独的选项,CreateFile 滥用 FILE_FLAG_BACKUP_SEMANTICS 这里有双重意义