Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MAX_PATH issue...w/ Explorer too

31 views
Skip to first unread message

cfx

unread,
Jun 27, 2005, 6:58:59 PM6/27/05
to
We've come across an issue with filename sizes exceeding MAX_PATH. Our
programs parses directory structures, and makes assumptions that they won't
exceed MAX_PATH. One of our clients ran across an issue where this isn't the
case. He has a path which is 248 characters in short file name version, but
267 in long file name version. And if we feed it to Explorer (typing it
manually in the Address bar) as the long version, Explorer chokes on it as
well (can't open the subfolder, error message of the file not existing,
etc.).

So are we supposed to assume that MAX_PATH only applies if the filename is
in short version? Any suggestions, tips, experience would be appreciated...


Eugene Gershnik

unread,
Jun 27, 2005, 7:09:30 PM6/27/05
to
cfx wrote:
> So are we supposed to assume that MAX_PATH only applies if the
> filename is in short version? Any suggestions, tips, experience would
> be appreciated...

NT+ is fully capable of dealing with filenames of any size. Win32 on NT can
also do this using the \\?\ hack. Almost every filename-related article in
MSDN mentiones this. However, 99.9% of software out there does this

char filename[MAX_PATH];

and breaks horribly when this is not the case. Even if you fix your
application (wich is a good idea in any case) chances are that your client
will have problems with other software. For his own sanity strongly suggest
to him to rearrange his directory structure. ;-)

In your own code MAX_PATH is never necessary. All Win32 API's expose some
way to query the required size so you can allocate dynamic buffer
accordingly.

--
Eugene
http://www.gershnik.com


Arkady Frenkel

unread,
Jun 28, 2005, 4:34:06 AM6/28/05
to
Additionally , good candidate for bug send to Microsoft , that shouldn't
exist
MAX_PATH for sure.
Arkady

"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:%23pn9G12...@TK2MSFTNGP09.phx.gbl...

Christian Kaiser

unread,
Jun 28, 2005, 3:45:10 AM6/28/05
to
Eugene,

I scanned my source I'm currently working on for MAX_PATH, and already at
the first place I looked at, GetModuleFilename() doesn't have a way to
return the needed size...(well the return value can be used, but will lead
to double work if the file name is exactly one char less than the passed
buffer) :)

Next problem is the CRT function makepath(), which has no replacement in
Win32 (ver 0x400).

Here I stop and wait for customers to complain. No one has ever complained
(and we have a lot of customers). I agree it might happen, but it seldom
does.

Christian

Eugene Gershnik

unread,
Jun 28, 2005, 3:50:59 AM6/28/05
to
Arkady Frenkel wrote:
> Additionally , good candidate for bug send to Microsoft , that
> shouldn't exist
> MAX_PATH for sure.

It's a whole sequence of bugs. I used to have some weird folder structures
for testing like very long paths, filenames that differ in case only (on NFS
shares) and filed called "..." and such (created using NT native API). Each
version of Windows came with explorer that behaved differently with them.
IIRC Win2k version was the most stable and correct one while XP added many
new bugs. I never checked it with 2k3 or XP SP2 though.


--
Eugene
http://www.gershnik.com


Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 3:56:05 AM6/28/05
to
Hi Eugene!

>>So are we supposed to assume that MAX_PATH only applies if the
>>filename is in short version? Any suggestions, tips, experience would
>>be appreciated...
>
> NT+ is fully capable of dealing with filenames of any size.

This is not correct...

See: Naming a File
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp

<quote>
The Unicode versions of several functions permit a maximum path length
of approximately 32,000 characters composed of components up to 255
characters in length.
</quote>

The following sample demonstartes the described behaviuor:

<code>
int _tmain()
{
TCHAR *szDirName = new TCHAR[300];
_tcscpy(szDirName, _T("C:\\"));
int i;
for (i=3; i<300; i++)
szDirName[i] = 'A';

BOOL bRet;
i=299;
do
{
szDirName[i] = 0;
bRet = CreateDirectory(szDirName, NULL);
if (bRet == FALSE)
_tprintf(_T("FAILED: %d characters (GetLastError: %d)\n"), i,
GetLastError());
else
{
_tprintf(_T("Ok: %d characters\n"), i);
RemoveDirectory(szDirName);
}
i--;
} while ( (CreateDirectory(szDirName, NULL) == FALSE) && (i> 3) );
}
</code>

For my machine (XP-SP1) it produces the following output:
FAILED: 299 characters (GetLastError: 3)
FAILED: 298 characters (GetLastError: 3)
FAILED: 297 characters (GetLastError: 3)
FAILED: 296 characters (GetLastError: 3)
FAILED: 295 characters (GetLastError: 3)
FAILED: 294 characters (GetLastError: 3)
FAILED: 293 characters (GetLastError: 3)
FAILED: 292 characters (GetLastError: 3)
FAILED: 291 characters (GetLastError: 3)
FAILED: 290 characters (GetLastError: 3)
FAILED: 289 characters (GetLastError: 3)
FAILED: 288 characters (GetLastError: 3)
FAILED: 287 characters (GetLastError: 3)
FAILED: 286 characters (GetLastError: 3)
FAILED: 285 characters (GetLastError: 3)
FAILED: 284 characters (GetLastError: 3)
FAILED: 283 characters (GetLastError: 3)
FAILED: 282 characters (GetLastError: 3)
FAILED: 281 characters (GetLastError: 3)
FAILED: 280 characters (GetLastError: 3)
FAILED: 279 characters (GetLastError: 3)
FAILED: 278 characters (GetLastError: 3)
FAILED: 277 characters (GetLastError: 3)
FAILED: 276 characters (GetLastError: 3)
FAILED: 275 characters (GetLastError: 3)
FAILED: 274 characters (GetLastError: 3)
FAILED: 273 characters (GetLastError: 3)
FAILED: 272 characters (GetLastError: 3)
FAILED: 271 characters (GetLastError: 3)
FAILED: 270 characters (GetLastError: 3)
FAILED: 269 characters (GetLastError: 3)
FAILED: 268 characters (GetLastError: 3)
FAILED: 267 characters (GetLastError: 3)
FAILED: 266 characters (GetLastError: 3)
FAILED: 265 characters (GetLastError: 3)
FAILED: 264 characters (GetLastError: 3)
FAILED: 263 characters (GetLastError: 3)
FAILED: 262 characters (GetLastError: 3)
FAILED: 261 characters (GetLastError: 3)
FAILED: 260 characters (GetLastError: 3)
FAILED: 259 characters (GetLastError: 206)
FAILED: 258 characters (GetLastError: 206)
FAILED: 257 characters (GetLastError: 206)
FAILED: 256 characters (GetLastError: 206)
FAILED: 255 characters (GetLastError: 206)
FAILED: 254 characters (GetLastError: 206)
FAILED: 253 characters (GetLastError: 206)
FAILED: 252 characters (GetLastError: 206)
FAILED: 251 characters (GetLastError: 206)
FAILED: 250 characters (GetLastError: 206)
FAILED: 249 characters (GetLastError: 206)
FAILED: 248 characters (GetLastError: 206)
Ok: 247 characters


--
Greetings
Jochen

My blog about Win32 and .NET
http://blog.kalmbachnet.de/

Eugene Gershnik

unread,
Jun 28, 2005, 4:16:23 AM6/28/05
to
Christian Kaiser wrote:
> Eugene,
>
> I scanned my source I'm currently working on for MAX_PATH, and
> already at the first place I looked at, GetModuleFilename() doesn't
> have a way to return the needed size...(well the return value can be
> used, but will lead to double work if the file name is exactly one
> char less than the passed buffer) :)

And why is it bad? Are you calling GetModuleFileName() in a tight loop that
affects your application performance? If so it is usually trivial to hoist
it out of there. Otherwise the difference between 1ms and 10ms in rarely
executed code shouldn't matter. Here (somehwat modified so typos are
possible) is the function I often use

std::tstring Common::GetModuleFileName(HINSTANCE hModule)
{
std::vector<TCHAR> buf(MAX_PATH);
while(true)
{
const DWORD res = ::GetModuleFileName(hModule, &buf[0],
(DWORD)buf.size());
if (res == 0)
throw Win32Exception(GetLastError());
if (res < buf.size())
break;
buf.resize(res + 1);
}
return &buf[0];
}

You may want to try it and see if it makes any difference in your
application performance.

> Next problem is the CRT function makepath(), which has no replacement
> in Win32 (ver 0x400).

Did you check what it is doing in its sources? In most cases the
manipulations it does to add "\\" or insert "." are unnecessary since your
know they are already there.

std::tstring full_name = drive + path + fname + ext;

If you really need its added value copy paste its code and replace raw
buffers it uses with std::[w]string.

> Here I stop and wait for customers to complain. No one has ever
> complained (and we have a lot of customers).

True but factor in those customers who figured out the problem, fixed their
directory structure, said few unpleasant words about your company and went
on with their lifes. An informal statistics at my workplace tells that for
each customer who calls and complains there are lots who don't and just
avoid/return the product.

> I agree it might happen,
> but it seldom does.

True again mostly because "everybody does it" so users avoid "dangerous"
situations. There is a long list of such issues including failing to work
under non-privileged account, failing to work in a terminal server session,
requiring that disk named C: be present etc. etc.

My personal view is that it is not hard to write correct code if you put
your mind to it. As a user I try to avoid software that exhibits any of
these problems.

--
Eugene
http://www.gershnik.com


Eugene Gershnik

unread,
Jun 28, 2005, 4:23:42 AM6/28/05
to
Jochen Kalmbach [MVP] wrote:
> Hi Eugene!
>
>>> So are we supposed to assume that MAX_PATH only applies if the
>>> filename is in short version? Any suggestions, tips, experience
>>> would be appreciated...
>>
>> NT+ is fully capable of dealing with filenames of any size.
>
> This is not correct...
>
> See: Naming a File
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp

Your example and link talk about Win32. I am not sure what the real NT limit
is but I suspect it is determined by filesystem only. As for Win32 your are
right there is the limit mentioned in the link you posted.


--
Eugene
http://www.gershnik.com

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 4:39:54 AM6/28/05
to
Hi Eugene!

>>>NT+ is fully capable of dealing with filenames of any size.
>>
>>This is not correct...
>>
>>See: Naming a File
>>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
>
> Your example and link talk about Win32. I am not sure what the real NT limit
> is but I suspect it is determined by filesystem only. As for Win32 your are
> right there is the limit mentioned in the link you posted.

What is your topic? x64???
What is your filesystem? NTFS???

What is the difference between Win32 and NT?

My example is compiled for AMD64 (x64) and running on W2k3-Sp1 x64 Edition!

Please show me any real-world windows software, which has *not* the
described limit!

Or is your discussion just _pure_ theory?

Eugene Gershnik

unread,
Jun 28, 2005, 4:42:09 AM6/28/05
to
Eugene Gershnik wrote:
> Jochen Kalmbach [MVP] wrote:
>> Hi Eugene!
>>
>>>> So are we supposed to assume that MAX_PATH only applies if the
>>>> filename is in short version? Any suggestions, tips, experience
>>>> would be appreciated...
>>>
>>> NT+ is fully capable of dealing with filenames of any size.
>>
>> This is not correct...
>>
>> See: Naming a File
>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
>
> Your example and link talk about Win32. I am not sure what the real
> NT limit is but I suspect it is determined by filesystem only.

After some digging it appears that internally on current 32-bit versions of
the NT based OSes and assuming NTFS filesystem there is a limit of 255
characters per path component and around 32k for the full path. Not sure if
this is the same of 64-bit OSes and of course MS is free to change them at
any time.


--
Eugene
http://www.gershnik.com

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 4:47:21 AM6/28/05
to
Hi Eugene!

> After some digging it appears that internally on current 32-bit versions of
> the NT based OSes and assuming NTFS filesystem there is a limit of 255
> characters per path component and around 32k for the full path. Not sure if
> this is the same of 64-bit OSes and of course MS is free to change them at
> any time.

See my other post: It is a limit of windows (either 32 or 64-bit...)

Eugene Gershnik

unread,
Jun 28, 2005, 5:06:14 AM6/28/05
to
Jochen Kalmbach [MVP] wrote:
> Hi Eugene!
>>>> NT+ is fully capable of dealing with filenames of any size.
>>>
>>> This is not correct...
>>>
>>> See: Naming a File
>>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
>>
>> Your example and link talk about Win32. I am not sure what the real
>> NT limit is but I suspect it is determined by filesystem only. As for
>> Win32
>> your are right there is the limit mentioned in the link you posted.
>
> What is your topic? x64???
> What is your filesystem? NTFS???
>
> What is the difference between Win32 and NT?

To answer shortly: the difference between NtCreateFile and CreateFile. Long
answer can be found in
http://www.sysinternals.com/WindowsInternals.html

> My example is compiled for AMD64 (x64) and running on W2k3-Sp1 x64
> Edition!

You compiled pure Win32 code without even using \\?\. Your conclusions may
be right (see my other post) but your code has nothing to do with it.

> Or is your discussion just _pure_ theory?

Not really. Though if your world is limited to Win32 it may appear so. Note
that I carefully made the distinction between NT and Win32 in my original
post. Where I was wrong is in saying "of any size".

> Please show me any real-world windows software, which has *not* the
> described limit!

I am not sure how you expect me to show you software in the newsgroup post.
However, note the implication for security software. If it is possible
(using whatever low-level means) to create a path inaccessible to normal
administration tools this would be an ideal place to store various (bad)
things.

--
Eugene
http://www.gershnik.com

Arkady Frenkel

unread,
Jun 28, 2005, 6:18:39 AM6/28/05
to
But did really you have folder more than 260 as OP wrote ?
As he wrote user succeed to create such
Arkady

"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:%23TBHiY7...@TK2MSFTNGP09.phx.gbl...

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 5:17:25 AM6/28/05
to
Hi Eugene!

> You compiled pure Win32 code without even using \\?\. Your conclusions may
> be right (see my other post) but your code has nothing to do with it.

What is the counterpart of "pure win32"-code?

Also using the "\\?\" prefix has no other effect...

>>Or is your discussion just _pure_ theory?
>
> Not really. Though if your world is limited to Win32 it may appear so.

I only know windows-world... maybe it is just a nameing-convention?
For me win16 (including Win9x/Me) is gone and x/IA64 is also "windows
development"... So I don´t see your point ;-)

> Note
> that I carefully made the distinction between NT and Win32 in my original
> post.

Today I can´t see the difference (maybe I missed soimething)


>>Please show me any real-world windows software, which has *not* the
>>described limit!
>
> I am not sure how you expect me to show you software in the newsgroup post.
> However, note the implication for security software. If it is possible
> (using whatever low-level means) to create a path inaccessible to normal
> administration tools this would be an ideal place to store various (bad)
> things.

I just talk about "normal" windows development (which is offical
documented).

Eugene Gershnik

unread,
Jun 28, 2005, 5:35:16 AM6/28/05
to
Jochen Kalmbach [MVP] wrote:
> Hi Eugene!
>
>> You compiled pure Win32 code without even using \\?\. Your
>> conclusions may be right (see my other post) but your code has
>> nothing to do with it.
>
> What is the counterpart of "pure win32"-code?

[...]

> I only know windows-world... maybe it is just a nameing-convention?
> For me win16 (including Win9x/Me) is gone and x/IA64 is also "windows
> development"... So I don´t see your point ;-)

[...]

> Today I can´t see the difference (maybe I missed soimething)

Google for "Native API". I really respect you and your expertise but you
obviously are not familiar with this particular area.

> I just talk about "normal" windows development (which is offical
> documented).

Well normal is in the eyes of the beholder. ;-) Also note that parts of
native API that are used to manipulate files are documented.

And again, you conclusions appear to be right.


--
Eugene
http://www.gershnik.com

Eugene Gershnik

unread,
Jun 28, 2005, 5:25:32 AM6/28/05
to
Arkady Frenkel wrote:
> But did really you have folder more than 260 as OP wrote ?
> As he wrote user succeed to create such

Sure. IIRC you need to create it piecewise using the API (both cmd.exe and
explorer check).
Then if you have Unix Samba servers or use SFU you can get very long paths
on network shares.


--
Eugene
http://www.gershnik.com


Arkady Frenkel

unread,
Jun 28, 2005, 6:50:20 AM6/28/05
to
Eugene , be aware that cfx ( OP ) wrote that his user succeed in that , I
strongly believe that cfx didn't give him ( user ) s/w using Native API for
file/directory creation :)
Arkady

"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:uW7I2S8e...@TK2MSFTNGP10.phx.gbl...

Eugene Gershnik

unread,
Jun 28, 2005, 5:54:30 AM6/28/05
to
Arkady Frenkel wrote:
> Eugene , be aware that cfx ( OP ) wrote that his user succeed in that
> , I strongly believe that cfx didn't give him ( user ) s/w using
> Native API for file/directory creation :)

Sure. We were discussing whether the limits cited at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
are the real limit for NT based systems (it appears they are).

The OP question was about MAX_PATH which is easily exceeded by the data at
this link. (255 per component, ~32k total)
I am sure Jochen would agree that a "normal" Win32 application can create a
path bigger than 260 characters.


--
Eugene
http://www.gershnik.com


Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 6:05:06 AM6/28/05
to
Hi Eugene!

>>Today I can´t see the difference (maybe I missed soimething)
>
> Google for "Native API". I really respect you and your expertise but you
> obviously are not familiar with this particular area.

If you mean the Zw/Ntxxx and other functions then maybe we use a
different naming...
For me everything is windows-development... (incl. DDK)
And also some "native" API as well documented (or at least MS started to
do so, for example: NtQueryInformationProcess, ...)

>>I just talk about "normal" windows development (which is offical
>>documented).
>
> Well normal is in the eyes of the beholder. ;-) Also note that parts of
> native API that are used to manipulate files are documented.

Yes. I think we are talking about the same stuff... (=> windows).

> And again, you conclusions appear to be right.

I don´t know if the "native" (your meaning) API also has this limit...

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 6:13:39 AM6/28/05
to
Hi Eugene!
>>Today I canæ„’ see the difference (maybe I missed soimething)

>
> Google for "Native API". I really respect you and your expertise but you
> obviously are not familiar with this particular area.

Sorry for the confusion!

Because my native language is _not_ english, I was not used the term of
"native API" (of course I have also the book "native API referecne..."
;-) so I should have been aware of the difference...)

But most win32-apiæ„€ are just some kind of wrapper around the native APIs...

It might be true that "RtlDosPathNameToNtPathName" has some kind of
limitation for file-paths and "NtCreateFile" will create it without any
problems (I have not checked it!).

So again, sorry for the "naming-confusion" from my side!

Eugene Gershnik

unread,
Jun 28, 2005, 6:18:43 AM6/28/05
to
Jochen Kalmbach [MVP] wrote:
> Hi Eugene!
>>> Today I can´t see the difference (maybe I missed soimething)
>>
>> Google for "Native API". I really respect you and your expertise but
>> you obviously are not familiar with this particular area.
>
> If you mean the Zw/Ntxxx and other functions then maybe we use a
> different naming...
> For me everything is windows-development... (incl. DDK)
> And also some "native" API as well documented (or at least MS started
> to do so, for example: NtQueryInformationProcess, ...)

Well then you should see the difference between what Win32 and NT allow. For
example NT allows me (IIRC - it has been a long time) to create a disk file
called "con" while Win32 doesn't. Their restrictions on path length *could*
be different too.
However, from a small test I just wrote it appears that it is not so. There
is also the remark from MSDN about \\?\
"They indicate that the path should be passed to the system with minimal
modification" which indicates that the limits on \\?\ are true system
limits.


--
Eugene
http://www.gershnik.com


Eugene Gershnik

unread,
Jun 28, 2005, 6:26:11 AM6/28/05
to
Jochen Kalmbach [MVP] wrote:

> So again, sorry for the "naming-confusion" from my side!

No problem ;-)

--
Eugene
http://www.gershnik.com


Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 5:31:38 PM6/28/05
to
Hi Eugene!

> "They indicate that the path should be passed to the system with minimal
> modification" which indicates that the limits on \\?\ are true system
> limits.

But it seems that the errors which are returned by "CreateDirectory" are
only because of some limit checking inside "CreateDirectory" (see CCP).

Maybe there is also an limit in FAT/NTFS...

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 5:47:04 PM6/28/05
to
> But it seems that the errors which are returned by "CreateDirectory" are
> only because of some limit checking inside "CreateDirectory" (see CCP).

I meant: NtCreateFile is able to create a long dir-name...

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 5:51:23 PM6/28/05
to
Hi Arkady!

> Eugene , be aware that cfx ( OP ) wrote that his user succeed in that , I
> strongly believe that cfx didn't give him ( user ) s/w using Native API for
> file/directory creation :)

You can create a directory with 262 characters with "CreateDirectory"
(with the use of the "\\?\" prefix).

I tried it with "\\?\c:\AAAAA...."

And explorer is *not* able to step into this directory nor is explorer
able to delete this directory!

The only way to remove it is to open a command-prompt and do the following:

rmdir \\?\c:\AAAAA...

Jochen Kalmbach [MVP]

unread,
Jun 28, 2005, 5:56:14 PM6/28/05
to
Hi cfx!

> So are we supposed to assume that MAX_PATH only applies if the filename is
> in short version? Any suggestions, tips, experience would be appreciated...

In general you can say:

<quote>


The Unicode versions of several functions permit a maximum path length
of approximately 32,000 characters composed of components up to 255
characters in length.
</quote>

You also should know that explorer is *not* a good example of this
documented behaviour...

If you create a directory with 255 chars inside _one_ component, then
explorer is not able to access this directory!

Example: C:\AAAAAA.... (255 times 'A')

Explorer refuses to open this folder or delete it...

You can only delete it with the command prompt by using the "long-version":

rmdir \\?\c:\AAAAAA....

Gareth Haslip

unread,
Jun 28, 2005, 6:07:39 PM6/28/05
to
This topic has got me curious... I tried using NtCreateFile to make a file >
255 chars in name and it does indeed fail...

Here's my code in case anyone else fancies trying:

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

//

#define UNICODE

#include "windows.h"

#include <iostream>

#pragma comment(lib,"C:\\WINDDK\\DDK_WI~1\\lib\\wxp\\i386\\ntdll.lib")

#pragma comment(lib,"C:\\WINDDK\\DDK_WI~1\\lib\\wxp\\i386\\ntoskrnl.lib")

typedef LONG NTSTATUS;

typedef struct _UNICODE_STRING {

USHORT Length;

USHORT MaximumLength;

#ifdef MIDL_PASS

[size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;

#else // MIDL_PASS

PWSTR Buffer;

#endif // MIDL_PASS

} UNICODE_STRING;

typedef UNICODE_STRING *PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {

ULONG Length;

HANDLE RootDirectory;

PUNICODE_STRING ObjectName;

ULONG Attributes;

PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR

PVOID SecurityQualityOfService; // Points to type
SECURITY_QUALITY_OF_SERVICE

} OBJECT_ATTRIBUTES;

typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

typedef struct _IO_STATUS_BLOCK {

union {

NTSTATUS Status;

PVOID Pointer;

};

ULONG_PTR Information;

} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

extern "C" NTSTATUS __stdcall

NtCreateFile(

OUT PHANDLE FileHandle,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes,

OUT PIO_STATUS_BLOCK IoStatusBlock,

IN PLARGE_INTEGER AllocationSize OPTIONAL,

IN ULONG FileAttributes,

IN ULONG ShareAccess,

IN ULONG CreateDisposition,

IN ULONG CreateOptions,

IN PVOID EaBuffer OPTIONAL,

IN ULONG EaLength

);

extern "C" void __stdcall

RtlInitUnicodeString(

IN OUT PUNICODE_STRING DestinationString,

IN PCWSTR SourceString

);

extern "C" void __stdcall

RtlFreeUnicodeString(

IN PUNICODE_STRING UnicodeString

);

#define InitializeObjectAttributes( p, n, a, r, s ) { \

(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \

(p)->RootDirectory = r; \

(p)->Attributes = a; \

(p)->ObjectName = n; \

(p)->SecurityDescriptor = s; \

(p)->SecurityQualityOfService = NULL; \

}

#define OBJ_CASE_INSENSITIVE 0x00000040L

#define FILE_NON_DIRECTORY_FILE 0x00000040

#define FILE_ATTRIBUTE_VALID_FLAGS 0x00007fb7

#define OBJ_KERNEL_HANDLE 0x00000200L

#define FILE_SUPERSEDE 0x00000000

void CreateUnicode(PUNICODE_STRING pString, wchar_t* pText)

{

RtlInitUnicodeString(pString, pText);


return;

}

int main(int argc, char* argv[])

{

if(strcmp(argv[0], "create") && argc == 3)

{

// get current folder

char temp;

DWORD requiredLength = GetCurrentDirectoryA(1, &temp);

char* buffer = new char[requiredLength];

DWORD didItWork = GetCurrentDirectoryA(requiredLength, buffer);

strupr(buffer);

std::string strTemp = std::string(argv[2]);

strTemp.insert(0,"____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________");

// strTemp.insert(0,"________");

strTemp.insert(0,"\\");

// strTemp.insert(0,buffer);

strTemp.insert(0,"\\Device\\HarddiskVolume1");

const char* strbuffer = strTemp.c_str();

size_t len = strlen(strbuffer)+1;

wchar_t* wideString = new wchar_t[len];

size_t numConverted = mbstowcs(wideString, strbuffer, len);

//

// Create/open the file.

//

UNICODE_STRING fileUniStr;

RtlInitUnicodeString(&fileUniStr, wideString);

OBJECT_ATTRIBUTES ObjectAttributes;

IO_STATUS_BLOCK IoStatusBlock;

NTSTATUS Status;

InitializeObjectAttributes(&ObjectAttributes,

&fileUniStr,

OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,

NULL,

NULL );

HANDLE hFile;

Status = NtCreateFile(&hFile,

DELETE,

&ObjectAttributes,

&IoStatusBlock,

NULL,

FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_READ,

FILE_SUPERSEDE,

FILE_NON_DIRECTORY_FILE,

NULL,

0);

/* HANDLE hFile = CreateFile(

wideString,

0, //DWORD dwDesiredAccess,

FILE_SHARE_DELETE, //DWORD dwShareMode,

NULL, //LPSECURITY_ATTRIBUTES lpSecurityAttributes,

CREATE_NEW, //DWORD dwCreationDisposition,

FILE_ATTRIBUTE_NORMAL, //DWORD dwFlagsAndAttributes,

NULL//HANDLE hTemplateFile

);

DWORD errorCode = GetLastError();

*/ delete buffer;

delete wideString;

printf("long file created...");

}

if(strcmp(argv[0], "list"))

{

}

return 0;

}


"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:eZp31S8e...@TK2MSFTNGP10.phx.gbl...

Gareth Haslip

unread,
Jun 28, 2005, 6:18:51 PM6/28/05
to
I can agree with this, although a filename can be 255 long in explorer, it
refuses to open a folder of length 255! Surely this is a bug?


"Jochen Kalmbach [MVP]" <nospam-Joch...@holzma.de> wrote in message
news:O%23GB4wC...@TK2MSFTNGP15.phx.gbl...

Eugene Gershnik

unread,
Jun 28, 2005, 9:12:40 PM6/28/05
to
Gareth Haslip wrote:
> This topic has got me curious... I tried using NtCreateFile to make a
> file > 255 chars in name and it does indeed fail...

Note that the 255 limit applies only to each *component* of the path. The
entire path can be longer.
Here a simple example that uses only regular Win32. WARNING ruuning it will
create folders that you won't be able to delete using explorer, cmd or even
cygwin. The only way to delete them appears to be through API.

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

int main()
{
std::wstring filename = L"\\\\?\\c:\\temp";
int i;
for (i = 0; i < 100; ++i)
{
filename = filename + L"\\abscdef";
if (!CreateDirectoryW(filename.c_str(), 0))
break;
}
std::wcout << "i=" << i << '\n' << filename;
}

Also note that you have to use Unicode version of the API.


--
Eugene
http://www.gershnik.com


Eugene Gershnik

unread,
Jun 28, 2005, 10:01:29 PM6/28/05
to
Jochen Kalmbach [MVP] wrote:
> Hi Eugene!
>
>> "They indicate that the path should be passed to the system with
>> minimal modification" which indicates that the limits on \\?\ are
>> true system limits.
>
> But it seems that the errors which are returned by "CreateDirectory"
> are only because of some limit checking inside "CreateDirectory" (see
> CCP).

Too much to see. There could be checks anywhere including file system driver
so cursory look at the top level function is not enough.

The 255 chars per component appears to be a limit of NTFS (and pretty much
all other file systems). From what I read NTFS has no inherent limit on the
total path length. So it appears that ~32k total limit is probably an
artifact of some internal buffer size. That's why I thought that 64-bit
Windows may relax this restriction. (I cannot check as I am still waiting
for the last part of my new 64-bit system to arrive ;-) )


--
Eugene
http://www.gershnik.com


cfx

unread,
Jun 29, 2005, 2:02:00 AM6/29/05
to
Wow...didn't think my OP would spawn such interesting discussion. Having
been able to create these long folders in Explorer ourselves, we realize we
had to address the problem in our own software. We are going with Eugene's
suggestion to dynamically allocate filename buffers. 389 instances of
MAX_PATH in our code...it's gonna be a fun week for us.

--

"cfx" <Fir...@msn.com> wrote in message
news:Tw%ve.10068$NX4....@newsread1.news.pas.earthlink.net...
> We've come across an issue with filename sizes exceeding MAX_PATH. Our
> programs parses directory structures, and makes assumptions that they
> won't exceed MAX_PATH. One of our clients ran across an issue where this
> isn't the case. He has a path which is 248 characters in short file name
> version, but 267 in long file name version. And if we feed it to Explorer
> (typing it manually in the Address bar) as the long version, Explorer
> chokes on it as well (can't open the subfolder, error message of the file
> not existing, etc.).

Doron Holan [MS]

unread,
Jun 29, 2005, 3:40:29 AM6/29/05
to
the 32K limit has todo with the definition of UNICODE_STRING, where the
length of the string in bytes is contained in a USHORT. Since the size of a
USHORT didn't change on win64, the limit did not change iether.

d

--
Please do not send e-mail directly to this alias. this alias is for
newsgroup purposes only.
This posting is provided "AS IS" with no warranties, and confers no rights.


"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:OOMh45Ef...@tk2msftngp13.phx.gbl...

Alexander Grigoriev

unread,
Jun 29, 2005, 10:45:58 AM6/29/05
to
Given WIN32_FIND_DATA structure, filesystems with component length >
MAX_PATH are unusable in Windows.

"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:eZp31S8e...@TK2MSFTNGP10.phx.gbl...

Eugene Gershnik

unread,
Jun 29, 2005, 4:07:59 PM6/29/05
to
cfx wrote:
> Wow...didn't think my OP would spawn such interesting discussion.
> Having been able to create these long folders in Explorer ourselves,
> we realize we had to address the problem in our own software. We are
> going with Eugene's suggestion to dynamically allocate filename
> buffers. 389 instances of MAX_PATH in our code...it's gonna be a fun
> week for us.

Note that you will also have to use Unicode versions of relevant APIs and
use \\?\ prefix when necessary. If your build is not already Unicode then
you will have an additional headache.


--
Eugene
http://www.gershnik.com


Eugene Gershnik

unread,
Jun 29, 2005, 2:04:53 PM6/29/05
to
Doron Holan [MS] wrote:
> the 32K limit has todo with the definition of UNICODE_STRING, where
> the length of the string in bytes is contained in a USHORT. Since
> the size of a USHORT didn't change on win64, the limit did not change
> iether.

As usual the real explanation is very simple. ;-)
Thanks!


--
Eugene
http://www.gershnik.com


Gareth Haslip

unread,
Jul 1, 2005, 3:36:01 PM7/1/05
to
btw you can get around the security risk of these long path names, by doing
dir /x in cmd.exe and renaming using the short dos names,

e.g. rename abcdef~1 abc

"Eugene Gershnik" <gers...@hotmail.com> wrote in message

news:ubM5$YOfFH...@tk2msftngp13.phx.gbl...

David Craig

unread,
Jul 1, 2005, 3:56:32 PM7/1/05
to
Only if there are short file names. They can be suppressed.

"Gareth Haslip" <gareth...@gmail.com> wrote in message
news:BWgxe.12670$iT1....@newsfe1-win.ntli.net...

Gareth Haslip

unread,
Jul 1, 2005, 4:55:56 PM7/1/05
to
you mean there are some folder names that RtlGenerate8dot3Name fails to
generate a short name for?

"David Craig" <No...@NoWhere.not> wrote in message
news:OOV43bnf...@TK2MSFTNGP10.phx.gbl...

David Craig

unread,
Jul 1, 2005, 6:20:01 PM7/1/05
to
You can set a flag that will prevent short names from being created. I
think it is for NTFS only.

"Gareth Haslip" <gareth...@gmail.com> wrote in message

news:w5ixe.12905$iT1....@newsfe1-win.ntli.net...

Eugene Gershnik

unread,
Jul 1, 2005, 7:23:09 PM7/1/05
to
David Craig wrote:
> You can set a flag that will prevent short names from being created. I
> think it is for NTFS only.

HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

IIRC many "tweaks and tips" sites recommend to set it to speed up hard disk
IO. Not sure how effective this would be but there are definitly people out
there that use this setting.

--
Eugene
http://www.gershnik.com

0 new messages