1

I was under impression that if I had a UNC path like this:

\\SRVR-A\Home\UserA\Documents\TestFolder

and I wanted to extend it passed the MAX_PATH limit, I could do this:

\\?\UNC\SRVR-A\Home\UserA\Documents\TestFolder

But when I run the following on Windows XP, it fails with the error code ERROR_INVALID_NAME:

TCHAR buffDummy;
DWORD dwNeededLn = ::GetLongPathName(
    L"\\\\?\\UNC\\SRVR-A\\Home\UserA\\Documents\\TestFolder",
    &buffDummy, 0);
if(dwNeededLn == 0)
{
    //Error
    int nErrorCode = ::GetLastError();
}

Am I missing something?

PS. That folder exists and the API works fine if I do \\SRVR-A\Home\UserA\Documents\TestFolder instead.

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • The purpose of `GetLongPathName` is to translate a short name eg. `c:\progra~2\MICROS~2.0` into a long name eg. `C:\Program Files\Microsoft Visual Studio 10`. So I'm not clear what your intent is here... – user1793036 Jun 06 '14 at 04:22
  • @user1793036: This is not the point of this question. – c00000fd Jun 06 '14 at 04:50
  • Do you only see this problem with `GetLongPathName` or are you also having trouble with other API functions such as `CreateFile`? Does it work on later versions of Windows? (Might just be a bug...) – Harry Johnston Jun 06 '14 at 05:00
  • @HarryJohnston: I didn't experiment with all of them to know for sure. AFAIK, other (kernel) APIs I tried seems to work OK. And yes, it works on Windows 7 & later. And even if it's a bug, there's really no other API to deal with short 8.3 names, is there? – c00000fd Jun 06 '14 at 06:01
  • Well, there's no guarantee that there is any way to work around any given bug. You might simply not be able to do this on Windows XP. (It is past end-of-life, after all.) – Harry Johnston Jun 07 '14 at 02:51
  • [This approach](http://stackoverflow.com/a/4763171/886887) might work. – Harry Johnston Jun 07 '14 at 02:53

2 Answers2

1

The function ::GetLongPathName() is really two functions: ::GetLongPathNameA() (ANSI) and ::GetLongPathNameW() (Wide).

In the include file fileapi.h there is some code:

#ifdef UNICODE
#define GetLongPathName  GetLongPathNameW
#else
#define GetLongPathName  GetLongPathNameA
#endif // !UNICODE

Only GetLongPathNameW() handles the longer path names.

You need to ensure that "UNICODE" is defined, or else to specifically call GetLongPathNameW(), not GetLongPathName()

I did some testing on my home LAN.

CALCITE is an external hard disk. It runs some type of Unix/Linux variant but I haven't tinkered with it. It has an IP of 192.168.1.2. I'm running the test on a Win7 Professional desktop using VC Express 2013.

#include <iostream>
#include <string>
#include <Windows.h>

void Test(const std::wstring &sName)
{
    std::wcout << sName << L" ==> ";

    const size_t nBuffsize = 1024;
    wchar_t szBuff[nBuffsize] = { 0 };
    if (::GetLongPathNameW(sName.c_str(), szBuff, nBuffsize))
        std::wcout << szBuff << std::endl;
    else
        std::wcout << L"Error: " << ::GetLastError() << std::endl;
}

int main() 
{
    Test(L"\\\\CALCITE\\public\\x.txt");
    Test(L"\\\\?\\UNC\\CALCITE\\public\\x.txt");
    Test(L"\\\\?\\UNC\\192.168.1.2\\public\\x.txt");

    Test(L"\\\\CALCITE\\public\\bad name.txt");
    Test(L"\\\\CALCITE\\Bad path\\x.txt");

    return 0;
}

The results:

 \\CALCITE\public\x.txt ==> \\CALCITE\public\x.txt
 \\?\UNC\CALCITE\public\x.txt ==> \\?\UNC\CALCITE\public\x.txt
 \\?\UNC\192.168.1.2\public\x.txt ==> \\?\UNC\192.168.1.2\public\x.txt
 \\CALCITE\public\bad name.txt ==> Error: 2 
 \\CALCITE\Bad path\x.txt ==> Error: 67

Error 2 is ERROR_FILE_NOT_FOUND

Error 67 is ERROR_BAD_NET_NAME

Michael J
  • 7,631
  • 2
  • 24
  • 30
  • Yes, I am using `GetLongPathNameW`. Sorry, I thought it's a given these days. (Plus the `L""` part should give it out.) I can't imagine anyone using ANSI, or non-Unicode strings. So, I'm curious, can you reproduce the same behavior on your end? – c00000fd Jun 06 '14 at 06:23
  • I'm having this issue with Windows XP. It works fine on Windows 7. – c00000fd Jun 07 '14 at 16:51
1

The hint is really in a quote from the MSDN page: "On many file systems, a short file name contains a tilde (~) character. However, not all file systems follow this convention".

With a remote file system, you don't know the underlying file system. You can't guess what its method for short file name generation is, or even if there is such a notion (it's really a Windows-specific concept, after all)

Thus, GetLongPathName should be expected to work at all. Now it may appear to work in some cases, but that's probably an unfortunate accident - applying local rules to a remote name may work if the systems are sufficiently alike.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • OK. So following your logic... I need to have a way to convert a path from a short 8.3 format to a long format. How would you do that? PS. I don't know the underlying format of the input path. – c00000fd Jun 06 '14 at 09:04
  • I wouldn't do it. If the remote server calls the file `\\10.0.0.1\Share\Foo~1.htm`, then that's the name it has. You can't even figure out **if** it has a long name, let alone what that name would be. – MSalters Jun 06 '14 at 09:09
  • I'm not talking about remote servers. "_I don't know the underlying format of the input path._" – c00000fd Jun 06 '14 at 09:11
  • Well, it's not hard to figure out from a path whether it's remote (Starts with `\\server` or `\\?\UNC`). In that case, don't try to convert names. – MSalters Jun 06 '14 at 09:45
  • Yes, that may be the only way to deal with it. Do you know though if `\\?\UNC\` part is case-sensitive? – c00000fd Jun 06 '14 at 18:58
  • It isn't a question of guessing what the long name is given a short name. That isn't possible even on a local file system! SMB includes support for querying the long name of a file, as shown by the fact that the call works for the OP if he uses `\\server\share` instead of `\\?\UNC\server\share`. The problem is simply that, for some reason, the function fails to support the latter format. – Harry Johnston Jun 07 '14 at 02:49
  • @HarryJohnston: SMB does, but the UNC name isn't necessarily a SMB share. – MSalters Jun 07 '14 at 07:42
  • Can someone confirm that `\\?\UNC` part is case-sensitive? – c00000fd Jun 07 '14 at 16:52
  • @MSalters: but it is in this case, so when GetLongPathName asks the file system to convert the short name to the long name it ought to work. It wouldn't make sense for GetLongPathName to say "well, I don't know for sure that I'll be able to retrieve the long file name for this path, so I won't even try". (c00000fd: I should be able to check that tomorrow when I'm back at the office.) – Harry Johnston Jun 07 '14 at 22:42
  • @c00000fd: On Windows 7, `\\?\UNC` does not appear to be case sensitive. I also can't find any indication in the Windows Research Kernel that it is case sensitive on Windows 2003, though that's not conclusive. There might be special cases. – Harry Johnston Jun 08 '14 at 22:14