GetShortPathName() doesn’t return short path name

Another amazing write up from Nitin Dhawan, Senior Support Engineer, Windows SDK team, EMEA/INDIA

Background of the issue

======================

This Issue was reported as, GetShortPathName() returned C:\veryverylongpath as short path for a given path C:\veryverylongpath, while expectation was that it should return something like C:\veryve~1 as the short path name. Due to this reason, the business logic of the application was failing

 

Solution Found

=============

 

Nitin worked with a sample to find out why the short path name is not returned and what can be done to correct the behavior.

  

Here is the summary with explanation to find the reason and resolve the issue.

 

Copy ShortPath.exe to c:\sample. The source is at the end of the blog.

C:\sample>dir

Volume in drive C is OSDisk

Volume Serial Number is 68AA-BF4B

 

Directory of C:\sample

 

10/08/2013 10:55 AM <DIR> .

10/08/2013 10:55 AM <DIR> ..

10/08/2013 10:53 AM 30,208 ShortPath.exe

               1 File(s) 30,208 bytes

               2 Dir(s) 272,271,319,040 bytes free

 

C:\sample>md LongFolderName

 

C:\sample>dir /X

Volume in drive C is OSDisk

Volume Serial Number is 68AA-BF4B

 

Directory of C:\sample

 

10/08/2013 10:56 AM <DIR> .

10/08/2013 10:56 AM <DIR> ..

10/08/2013 10:56 AM <DIR> LONGFO~1 LongFolderName ß expected, short path is created

10/08/2013 10:53 AM 30,208 SHORTP~1.EXE ShortPath.exe

               1 File(s) 30,208 bytes

               3 Dir(s) 272,271,319,040 bytes free

 

; /X option shows the short path created as well.

; details of /X option using dir /?

; /X This displays the short names generated for non-8dot3 file names. 

; The format is that of /N with the short name inserted before the long name.

; If no short name is present, blanks are displayed in its place.

 

C:\sample>fsutil 8dot3name query

The registry state of NtfsDisable8dot3NameCreation is 2, the default (Volume level setting).

C:\sample>fsutil 8dot3name query c:

The volume state for Disable8dot3 is 0 (8dot3 name creation is enabled).

The registry state of NtfsDisable8dot3NameCreation is 2, the default (Volume level setting).

Based on the above two settings, 8dot3 name creation is enabled on c:.

C:\sample>ShortPath.exe LongFolderName

The full path name is: C:\sample\LongFolderName

The short name for LongFolderName is LONGFO~1

The long name for LONGFO~1 is LongFolderName

 

C:\sample>ShortPath.exe c:\sample\LongFolderName

The full path name is: c:\sample\LongFolderName

The short name for c:\sample\LongFolderName is c:\sample\LONGFO~1

The long name for c:\sample\LONGFO~1 is c:\sample\LongFolderName

 

C:\sample>fsutil.exe behavior set disable8dot3 1

 

C:\sample>fsutil 8dot3name query

The registry state of NtfsDisable8dot3NameCreation is 1 (Disable 8dot3 name creation on all volumes).

 

C:\sample>fsutil 8dot3name query c:

The volume state for Disable8dot3 is 0 (8dot3 name creation is enabled).

The registry state of NtfsDisable8dot3NameCreation is 1 (Disable 8dot3 name creation on all volumes).

Based on the above two settings, 8dot3 name creation is disabled on c:.

 

C:\sample>md NewFolderName

 

C:\sample>dir /X

Volume in drive C is OSDisk

Volume Serial Number is 68AA-BF4B

 

Directory of C:\sample

 

10/08/2013 10:58 AM <DIR> .

10/08/2013 10:58 AM <DIR> ..

10/08/2013 10:56 AM <DIR> LONGFO~1 LongFolderName

10/08/2013 10:58 AM <DIR> NewFolderName ß short path is not created because it was disabled.

10/08/2013 10:53 AM 30,208 SHORTP~1.EXE ShortPath.exe

               1 File(s) 30,208 bytes

               4 Dir(s) 272,271,319,040 bytes free

 

 

C:\sample>ShortPath.exe NewFolderName

The full path name is: C:\sample\NewFolderName

The short name for NewFolderName is NewFolderName

The long name for NewFolderName is NewFolderName

 

C:\sample>ShortPath.exe c:\sample\NewFolderName

The full path name is: c:\sample\NewFolderName

The short name for c:\sample\NewFolderName is c:\sample\NewFolderName

The long name for c:\sample\NewFolderName is c:\sample\NewFolderName

 

C:\sample>fsutil.exe behavior set disable8dot3 2

 

C:\sample>fsutil 8dot3name query

The registry state of NtfsDisable8dot3NameCreation is 2, the default (Volume level setting).

 

C:\sample>fsutil 8dot3name query c:

The volume state for Disable8dot3 is 0 (8dot3 name creation is enabled).

The registry state of NtfsDisable8dot3NameCreation is 2, the default (Volume level setting).

Based on the above two settings, 8dot3 name creation is enabled on c:.

 

C:\sample>md AnotherLongFolderName

 

C:\sample>dir /X

Volume in drive C is OSDisk

Volume Serial Number is 68AA-BF4B

 

Directory of C:\sample

 

10/08/2013 11:01 AM <DIR> .

10/08/2013 11:01 AM <DIR> ..

10/08/2013 11:01 AM <DIR> ANOTHE~1 AnotherLongFolderName ß created short path name

10/08/2013 10:56 AM <DIR> LONGFO~1 LongFolderName

10/08/2013 10:58 AM <DIR> NewFolderName

10/08/2013 10:53 AM 30,208 SHORTP~1.EXE ShortPath.exe

               1 File(s) 30,208 bytes

               5 Dir(s) 272,271,265,792 bytes free

 

C:\sample>ShortPath.exe AnotherLongFolderName

The full path name is: C:\sample\AnotherLongFolderName

The short name for AnotherLongFolderName is ANOTHE~1

The long name for ANOTHE~1 is AnotherLongFolderName

 

C:\sample>ShortPath.exe c:\sample\AnotherLongFolderName

The full path name is: c:\sample\AnotherLongFolderName

The short name for c:\sample\AnotherLongFolderName is c:\sample\ANOTHE~1

The long name for c:\sample\ANOTHE~1 is c:\sample\AnotherLongFolderName

 

 

How to set the short path name for the folder/file that were not created because the 8dot3 name creation was disable?

fsutil provide a way to do it as below:

 

C:\sample>fsutil file setshortname

Usage : fsutil file setshortname <filename> <shortname>

   Eg : fsutil file setshortname C:\testfile.txt testfile

 

C:\sample>fsutil file setshortname NewFolderName NewF~2

 

C:\sample>dir /X

Volume in drive C is OSDisk

Volume Serial Number is 68AA-BF4B

 

Directory of C:\sample

 

10/08/2013 11:03 AM <DIR> .

10/08/2013 11:03 AM <DIR> ..

10/08/2013 11:01 AM <DIR> ANOTHE~1 AnotherLongFolderName

10/08/2013 10:56 AM <DIR> LONGFO~1 LongFolderName

10/08/2013 10:58 AM <DIR> NEWF~2 NewFolderName ß short path name is set

10/08/2013 10:53 AM 30,208 SHORTP~1.EXE ShortPath.exe

               1 File(s) 30,208 bytes

               5 Dir(s) 272,271,306,752 bytes free

C:\sample>ShortPath.exe NewFolderName

The full path name is: C:\sample\NewFolderName

The short name for NewFolderName is NEWF~2

The long name for NEWF~2 is NewFolderName

 

C:\sample>ShortPath.exe c:\sample\NewFolderName

The full path name is: c:\sample\NewFolderName

The short name for c:\sample\NewFolderName is c:\sample\NEWF~2

The long name for c:\sample\NEWF~2 is c:\sample\NewFolderName

 

<Sample code for ShortPath.exe>

// Source - https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx

// ShortPath.cpp : Defines the entry point for the console application.

//

 

#include"stdafx.h"

#include<windows.h>

#include<tchar.h>

#include<stdio.h>

 

#define BUFSIZE 4096

#define LONG_DIR_NAME TEXT("E:\\longdirectoryname\\Prj\\file")

 

void _tmain(int argc, TCHAR *argv[])

{

    DWORD retval=0;

    BOOL success;

    TCHAR buffer[BUFSIZE]=TEXT("");

    TCHAR buf[BUFSIZE]=TEXT("");

    TCHAR** lppPart={NULL};

 

   if( argc != 2 )

   {

      _tprintf(TEXT("Usage: %s [file]\n"), argv[0]);

      return;

   }

 

// Retrieve the full path name for a file.

// The file does not need to exist.

 

    retval = GetFullPathName(argv[1],

                 BUFSIZE,

                 buffer,

                 lppPart);

   

    if (retval == 0)

    {

        // Handle an error condition.

        printf ("GetFullPathName failed (%d)\n", GetLastError());

        return;

    }

    else

    {

        _tprintf(TEXT("The full path name is: %s\n"), buffer);

        if (lppPart != NULL && *lppPart != 0)

        {

            _tprintf(TEXT("The final component in the path name is: %s\n"), *lppPart);

        }

    }

 

       //TCHAR*lppath = TEXT("C:\\Program Files (x86)\\Avaya\\BI");

       TCHAR*lppath = argv[1];

 

// Create a long directory name for use with the next two examples.

 

    //success = CreateDirectory(lppath,

    // NULL);

 

    //if (!success)

    //{

    // // Handle an error condition.

    // printf ("CreateDirectory failed (%d)\n", GetLastError());

    // return;

    //}

 

 

// Retrieve the short path name. 

 

    retval = GetShortPathName(lppath,

                  buf,

                  BUFSIZE);

 

    if (retval == 0)

    {

        // Handle an error condition.

         printf ("GetShortPathName failed (%d)\n", GetLastError());

         return;

    }

    else _tprintf(TEXT("The short name for %s is %s\n"),

                  lppath, buf);

 

 

// Retrieve the long path name. 

 

    retval = GetLongPathName(buf,

              buffer,

              BUFSIZE);

 

    if (retval == 0)

    {

        // Handle an error condition.

         printf ("GetLongPathName failed (%d)\n", GetLastError());

         return;

    }

    else _tprintf(TEXT("The long name for %s is %s\n"), buf, buffer);

 

// Clean up the directory.

 

    //success = RemoveDirectory(lppath);

    //if (!success)

    //{

    // // Handle an error condition.

    // printf ("RemoveDirectory failed (%d)\n", GetLastError());

    // return;

    //}

}

 

 

</Sample code for ShortPath.exe>

 

Keywords- GetLongPathName , GetShortPathName , 8dot3 , fsutil, NTFS

 

References-

https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx

https://support.microsoft.com/kb/121007

https://technet.microsoft.com/en-us/library/ff621566.aspx

https://technet.microsoft.com/en-us/library/cc778996.aspx

 

Written by: Nitin Dhawan

Reviewed by: Jeff Lambert

 

 

 

WINDOWS SDK TEAM