Opened 13 years ago
Closed 11 years ago
#2054 closed Bug (Rejected)
DirCreate incorrectly reports success when path is longer than 255 chars
Reported by: | wraithdu | Owned by: | |
---|---|---|---|
Milestone: | Component: | AutoIt | |
Version: | 3.3.7.21 | Severity: | None |
Keywords: | DirCreate | Cc: |
Description
DirCreate returns 1 (success) when the path is longer than 255 characters. However the path created is truncated to 255 characters, thus creating some unknown shortened path. This occurs even using correct unicode long path notation:
\\?\C:\some\really\long\path or \\?\UNC\server\share\some\really\long\path
DirCreate should either return 0 (failure) when a normal path is given that is longer that 255 characters, or it needs to actually create the correct extra long path when proper unicode long path notation is used.
See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx for reference.
Attachments (0)
Change History (8)
comment:1 Changed 13 years ago by Jpm
comment:2 Changed 13 years ago by wraithdu
That's not correct. The directory is not created properly. *A* directory *is* created, but it's not the one specified in the function. The path is truncated to 255 chars and a 255 char length directory is created.
In fact FileExists does work correctly on paths longer than 255 chars, but you have to create them via other means to test this.
Here is the path from your test as it was created:
C:\some\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\lo
It is 255 chars long.
Try this for comparison. You'll have to rename some directories to remove the final path since it will be too long (>255).
$sPath = "\\?\C:\some\" $sPath &= "really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\really\long\path" ; ConsoleWrite("Path len: " & StringLen($sPath) & " : " & $sPath & @CRLF) $ret = _LFC_CreateDirectory($sPath) ConsoleWrite("Return: " & $ret & @CRLF) ConsoleWrite("Dir exists: " & FileExists($sPath) & @CRLF) ; to be sure... ConsoleWrite("Dir exists2: " & FileExists($sPath & "nothere") & @CRLF) ConsoleWrite("Dir exists3: " & FileExists(StringTrimRight($sPath, 2)) & @CRLF) ; remove fails ConsoleWrite("Removed: " & DirRemove($sPath, 1) & @CRLF) Func _LFC_CrackPath($sPath) ; make sure path is terminated If StringRight($sPath, 1) <> "\" Then $sPath &= "\" ; get prefix Local $aRet = StringRegExp($sPath, "(?i)^\\\\\?\\unc\\|\\\\\?\\|\\\\", 1) If Not IsArray($aRet) Then $aRet = "" Else $aRet = $aRet[0] EndIf ; capture and remove the root If ($aRet = "\\") Or ($aRet = "\\?\UNC\") Then ; UNC network path $aRet = StringRegExp($sPath, "(?i)^(" & StringReplace(StringReplace($aRet, "\", "\\"), "?", "\?") & ".*?\\.*?\\)", 1) Else ; $aRet = "" or \\?\ => local path Local $iTrim = StringLen($aRet) + 3 Local $aRet[1] = [StringLeft($sPath, $iTrim)] EndIf Local $aPath = StringTrimLeft($sPath, StringLen($aRet[0])) ; check if path given was just a root If $aPath <> "" Then ; crack path, prepend \ to get first segment $aPath = StringRegExp("\" & $aPath, "\\(.*?)(?=\\)", 3) ReDim $aRet[UBound($aPath) + 1] For $i = 0 To UBound($aPath) - 1 $aRet[$i + 1] = $aPath[$i] Next EndIf ; Return $aRet EndFunc ;==>_LFC_CrackPath Func _LFC_CreateDirectory($sPath) ; check path already exists If FileExists($sPath) Then ; check if it is a direcotry If StringInStr(FileGetAttrib($sPath), "D") Then Return 1 Else Return SetError(1, 0, 0) EndIf EndIf ; Local $aPath = _LFC_CrackPath($sPath) ; make sure root exists Local $sSegment = $aPath[0] If Not FileExists($sSegment) Then Return SetError(2, 0, 0) Local $ret For $i = 1 To UBound($aPath) - 1 $sSegment &= $aPath[$i] & "\" If Not FileExists($sSegment) Then ; create sub-path $ret = DllCall("kernel32.dll", "bool", "CreateDirectoryW", "wstr", $sSegment, "ptr", 0) If @error Or Not $ret[0] Then Return SetError(3, 0, 0) EndIf Next Return 1 EndFunc ;==>_LFC_CreateDirectory
comment:3 Changed 13 years ago by Jpm
I understand, I can add that the removal is only possible if the full path of the last created directory if less than ~260 chars.
Explorer itself cannot remove it (I am running Win7 Sp1 32-bit)
comment:4 follow-up: ↓ 5 Changed 13 years ago by wraithdu
So you're confirming this is an error/bug as to the behavior of DirCreate? Because DirCreate, as I showed, is not creating the extra long path properly.
If so, thank you :)
comment:5 in reply to: ↑ 4 Changed 13 years ago by Jpm
Replying to wraithdu:
So you're confirming this is an error/bug as to the behavior of DirCreate? Because DirCreate, as I showed, is not creating the extra long path properly.
If so, thank you :)
Before your ticket I already warn the other dev that we may have to support
\\?\
Perhaps they will do something. I am a banned Dev Thanks to Valik
comment:6 Changed 13 years ago by Valik
JPM, you are not a developer any longer, please stop acting like one.
Yes, JP brought it to our attention that long paths are not supported. All path related functions use a hard-coded buffer length of MAX_PATH. I detest hard-coded buffer sizes and I know that it needs changed to support variable length paths. The problem is I'm trying to get a release out before we all die and we can't make significant changes like this just weeks before said release.
It was fine to create the ticket but all this discussion with JP has been pointless. Long paths will be supported at some point after the next release and this ticket should be irrelevant at that time.
comment:7 Changed 13 years ago by wraithdu
Not a problem, thank you for the response.
Would it be reasonable to make a smaller change, and have DirCreate return an error when given a path greater than the buffer size, instead of returning success and creating some unknown truncated path? It's this latter behavior that should ideally be avoided.
comment:8 Changed 11 years ago by Jon
- Resolution set to Rejected
- Status changed from new to closed
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
In fact the dir is created when using
?\
the only thing you can perhaps contest is FileExists or DirRemove does not found such path