Am 2013-09-07 12:52, schrieb Bart:

> Note that '//?/C:/foo/bar' in contrast happily opens 'C:\foo\bar'
> (nice touch from M$).

Why is this a "nice touch"? IMO it is crap. This kind of inconsistencies in MS 
programs lead to false assumptions and mislead the user (programmer). If characters are 
forbitten then they should be forbidden and not *sometimes* be allowed and *sometimes* be 
converted to something different. Being consequent in this respect would have saved a lot 
of headaches for generations of programmers.


> My question is: should DoDirSeparators handle this case and leave the
> filename untouched if it starts with '\\?\', or should we leave it up
> to the programmer not calling functions like ExpandFilename if a
> filename starts with '\\?\'

In general I would prefer if this '\\?\' prefix is hidden away from the 
programmer at all. File names should be just that: File names. On windows 
*every* API function that expects file names should be prepended with '\\?\' 
internally while for Linux this should be omitted. But the programmer should 
not need to know about this. Internal functions that use WinAPI calls should 
add the prefix theirself in all cases(!) (if supported) and omit it for Linux. 
For all situations where the file name is moved/converted from one function to 
another (when no OS-API functions is involved) it should just leave the name as 
it is.

I have written my own functions which do this because it is a nightmare to find out which 
kind of string encoding is expected/required by what function within FPC/Lazarus. The 
documentation just says "string" but never says whether it is UTF8, UTF16 or 
whatever. So when I want to be sure what happens I have to reinvent the wheel and write 
my own OS independend functions which in my case *always* expect UTF8 (which is my 
standard encoding in all situations) and convert to UTF16 and add the prefix '\\?\' when 
feeding it to a WinAPI function:

function WinAPIPathName(const Pfad : UTF8String) : UTF8String;
begin
Result := Pfad;
if (length(Result)<=3) or
   (Result[1]='\') and
   (Result[2]='\') and
   (Result[3]='?') and
   (Result[4]='\') then exit;
if (length(Result)>=2) and
   (Result[1]='\') and
   (Result[2]='\') then      // UNC-path, i.e. "\\server\share"
   begin
   Result := '\\?\UN'+Result;
   Result[7] := 'C';
   end
else
   Result := '\\?\'+Result;
end;

which I then call like this:

H  := FindFirstFileW(pwidechar(UTF8Decode(WinAPIPathName(Pathname))),FW);

This way I don't need to bother about path lengths and unicode issues. I just 
use UTF8 in my programs. And when I need other encodings I know that I have to 
convert them before calling functions that need UTF8.

What I would expect as a programming interface when writing programs for 
multiple operating systems would be functions like
RenameFileUTF8 and RenameFileUTF16 where I know that I have to use UTF8 
(Ansi-)Strings or UTF16 (Ansi-)Strings as parameter without the need to prepend 
'\\?\' because it is done (if needed) by the internal OS-dependend function.


_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to