I found some code to access the Win32 dialogs. It works fine, and
returns a long file name string. But to work with the rest of the
application I need to convert the long file names back to short file
names. I found some Win32 Delphi code (below) that does this, but
can't figure out how to call the Win32 kernel function
GetShortPathName(). (I can convert the rest of the code to its Delphi
I equivalent with no problem.)
Is there a way to call the KERNEL32.DLL function GetShortPathName()
from Delphi I code without a thunk? (Obviously, I'm guessing and don't
know what I'm talking about.)
Or just as good, does anyone have a Delphi I code snippit for
accomplishing the same thing?
function GetShortName(sLongName : string) : string;
var
sShortName : string;
nShortNameLen : integer;
begin
SetLength(sShortName, MAX_PATH);
nShortNameLen := GetShortPathName(PChar(sLongName),
PChar(sShortName), MAX_PATH-1);
if nShortNameLen = 0 then begin
{ handle errors... }
end;
SetLength(sShortName, nShortNameLen);
Result := sShortName;
end;
>Is there a way to call the KERNEL32.DLL function GetShortPathName()
>from Delphi I code without a thunk?
No. However, in Win95/98, there is a 16-bit equivalent to
GetShortPathName:
const
MAX_PATH = 260;
function GetShortPathName(LongPath: String): String;
var
Source: PChar;
Dest: PChar;
begin
Source := StrAlloc(Length(LongPath) + 1);
StrPCopy(Source, LongPath);
Dest := StrAlloc(MAX_PATH + 1);
try
asm
push ds
mov ax,$7160
mov cx,$0001
lds si,Source
les di,Dest
int $21
pop ds
end;
Result := StrPas(Dest);
finally
StrDispose(Source);
StrDispose(Dest) end end;
This won't work in NT, where thunking is the only alternative.
-Steve
>...in Win95/98, there is a 16-bit equivalent to GetShortPathName:....
>This won't work in NT, where thunking is the only alternative.
Your code was *exactly* what I needed...and I don't have to get this
running on NT (hopefully it will be ported to 32-bit before then), so
all is well with the world.<g>
Thanks!
Another question: Now I'm looking for a way to convert a short file
name to a long one. The code I had found to do that (below) doesn't
work...Searchrec.Name (called in the GetLongPathChunk helper function)
returns only the short file name, not a long name.
Do you know of a workaround or other approach?
function GetLongPathChunk(sShortName: string; var bError: boolean) :
string;
{ Return long chunk of file path.
Called by GetLongName fn, below.}
var
bAddSlash : boolean;
SearchRec : TSearchRec;
nStrLen : integer;
begin
bError := False;
Result := sShortName;
nStrLen := Length(sShortName);
bAddSlash := False;
{Remove trailing slash}
if sShortName[nStrLen] = '\' then begin
bAddSlash := True; {Store state so we can add back slash}
dec(nStrLen);
sShortName := Copy(sShortName, 1, nStrLen);
end;
{Get next chunk of file path}
if((nStrLen-Length(ExtractFileDrive(sShortName))) > 0) then begin
if FindFirst(sShortName, faAnyFile, SearchRec) = 0 then begin
{*****}
{***** In following line, SearchRec.name only returns *****}
{***** a short path name, not the desired long name *****}
{*****}
Result := ExtractFilePath(sShortName) + SearchRec.name;
if bAddSlash then begin
Result := Result + '\';
end;
end else begin
{ handle errors...}
bError := True;
end;
FindClose(SearchRec);
end;
end;
function GetLongFileName(sShortName : string) : string;
{ Returns long (Win32) file name from short (Win 3.1) name.}
var
s : string;
p : integer;
bError : boolean;
begin
Result := sShortName;
s := '';
p := Pos('\', sShortName);
while (p > 0) do begin
s := GetLongPathChunk(s + Copy(sShortName, 1, p), bError);
Delete(sShortName, 1, p);
p := Pos('\', sShortName);
if bError then
Exit;
end;
if sShortName <> '' then begin
s := GetLongPathChunk(s + sShortName, bError);
if bError then
Exit;
end;
Result := s;
end;
Thanks,
Mark Wilsdorf
>Another question: Now I'm looking for a way to convert a short file
>name to a long one. The code I had found to do that (below) doesn't
>work...Searchrec.Name (called in the GetLongPathChunk helper function)
>returns only the short file name, not a long name.
I don't recall the original context of your question, but I think this
is the answer:
function GetLongPathName(const PathName: String): String;
var
Drive: String;
Path: String;
SearchRec: TSearchRec;
begin
Drive := ExtractFileDrive(PathName);
Path := Copy(PathName, Length(Drive) + 1, Length(PathName));
if (Path = '') or (Path = '\') then
begin
Result := PathName;
if Result[Length(Result)] = '\' then
Delete(Result, Length(Result), 1);
end
else begin
Path := GetLongPathName(ExtractFileDir(PathName));
if FindFirst(PathName, faAnyFile, SearchRec) = 0 then
begin
Result := Path + '\' + SearchRec.FindData.cFileName;
FindClose(SearchRec);
end
else Result := Path + '\' + ExtractFileName(PathName);
end;
end;
-Steve