I know, you don't want to check for \\?\
and remove it, but as Remy explains in his answer, that's the easiest solution. However, you should be careful, because local paths and network paths have different prefixes. As you know, a local path starts with \\?\
, but a network path starts with \\?\UNC\
(as described here), for example:
\\?\UNC\My server\My share\Directory
As a result, based on your code, my solution to remove the prefixes is as follows:
char existingTarget[MAX_PATH];
HANDLE hFile = CreateFileA(linkPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
DWORD ret = GetFinalPathNameByHandleA(hFile, existingTarget, MAX_PATH, FILE_NAME_OPENED);
CloseHandle(hFile);
// Check whether existingTarget is large enough to hold the final path.
if (ret < MAX_PATH)
{
// The local path prefix is also a prefix of the network path prefix.
// Therefore, look for the network path prefix first.
// Please note that backslashes have to be escaped.
std::string targetPath(existingTarget);
if (targetPath.substr(0, 8).compare("\\\\?\\UNC\\") == 0)
{
// In case of a network path, replace `\\?\UNC\` with `\\`.
targetPath = "\\" + targetPath.substr(7);
}
else if (targetPath.substr(0, 4).compare("\\\\?\\") == 0)
{
// In case of a local path, crop `\\?\`.
targetPath = targetPath.substr(4);
}
}
}
If needed, you can still use memmove()
to copy targetPath
into another variable.