Thread overview
getDirectory of FileSystem.d
Feb 14, 2007
Alberto
Feb 14, 2007
kris
Feb 14, 2007
Frits van Bommel
February 14, 2007
I must get the current dir, and, I'm using getDirectory() from
FileSystem.d to do that.
A simple example:

FilePath appDir = FileSystem.getDirectory;

it works but there is a space at the end of path, so I have many errors
when I try to join paths.
Here's a log:

giano.globals - appDir: 'C:\Documents and Settings\Admin\Desktop\projects\giano '

I have tried to understand why by myself.
This is a cut of getDirectory() from FileSystem:

int length = GetCurrentDirectoryW (0, null);
if (length) {
    char[MAX_PATH] tmp = void;
    auto dir = new wchar [length];
    GetCurrentDirectoryW (length, dir.ptr);
    return new FilePath (Utf.toUtf8 (dir, tmp));
}

in MSDN I read:

Return Value
If the function succeeds, the return value specifies the number of
characters that are written to the buffer, not including the terminating
null character.
If the function fails, the return value is zero. To get extended error
information, call GetLastError.
If the buffer that is pointed to by lpBuffer is not large enough, the
return value specifies the required size of the buffer, in characters,
including the null-terminating character.

null is passed as buffer to GetCurrentDirectoryW, so the return value
should specifies the required size of the buffer including the
null-terminating character, but D string doesn't have one.
So, this line:

auto dir = new wchar [length];

should be fixed in:

auto dir = new wchar [length-1];

and the same for the ANSI version
or I'm wrong?


February 14, 2007
Alberto wrote:
> I must get the current dir, and, I'm using getDirectory() from
> FileSystem.d to do that.
> A simple example:
> 
> FilePath appDir = FileSystem.getDirectory;
> 
> it works but there is a space at the end of path, so I have many errors
> when I try to join paths.
> Here's a log:
> 
> giano.globals - appDir: 'C:\Documents and
> Settings\Admin\Desktop\projects\giano '
> 
> I have tried to understand why by myself.
> This is a cut of getDirectory() from FileSystem:
> 
> int length = GetCurrentDirectoryW (0, null);
> if (length) {
>     char[MAX_PATH] tmp = void;
>     auto dir = new wchar [length];
>     GetCurrentDirectoryW (length, dir.ptr);
>     return new FilePath (Utf.toUtf8 (dir, tmp));
> }
> 
> in MSDN I read:
> 
> Return Value
> If the function succeeds, the return value specifies the number of
> characters that are written to the buffer, not including the terminating
> null character.
> If the function fails, the return value is zero. To get extended error
> information, call GetLastError.
> If the buffer that is pointed to by lpBuffer is not large enough, the
> return value specifies the required size of the buffer, in characters,
> including the null-terminating character.
> 
> null is passed as buffer to GetCurrentDirectoryW, so the return value
> should specifies the required size of the buffer including the
> null-terminating character, but D string doesn't have one.
> So, this line:
> 
> auto dir = new wchar [length];
> 
> should be fixed in:
> 
> auto dir = new wchar [length-1];
> 
> and the same for the ANSI version
> or I'm wrong?
> 
> 


That looks like a bug. Would you mind filing a bug-report over here, please?  http://www.dsource.org/projects/tango/newticket
February 14, 2007
Alberto wrote:
> int length = GetCurrentDirectoryW (0, null);
> if (length) {
>     char[MAX_PATH] tmp = void;
>     auto dir = new wchar [length];
>     GetCurrentDirectoryW (length, dir.ptr);
>     return new FilePath (Utf.toUtf8 (dir, tmp));
> }
> 
[snip]
> null is passed as buffer to GetCurrentDirectoryW, so the return value
> should specifies the required size of the buffer including the
> null-terminating character, but D string doesn't have one.
> So, this line:
> 
> auto dir = new wchar [length];
> 
> should be fixed in:
> 
> auto dir = new wchar [length-1];
> 
> and the same for the ANSI version
> or I'm wrong?

The code is wrong, but I think you're also wrong about how to fix it ;).

GetCurrentDirectoryW will _still_ try to write the null character to terminate the string. So space for it needs to be allocated. Since the null character shouldn't be returned, the length of 'dir' should be decreased by one before use.

So the fix is to either insert something like 'dir = dir[0 .. $-1];' (or 'dir.length = length - 1;') before the return statement, or to change the 'dir' in the return statement to 'dir[0 .. $-1]'.