Using TWin32FindData to determine the short name (DOS name) of a file

Determining the short name (DOS name) of a file

Copyright © 2000 Ernesto De Spirito

KnowledgeBase Vortex 2.9

TWin32FindData

The FindData field of the TSearchRec record used by the FindFirst and FindNext functions and the FindClose procedure, is yet another record:

type
TWin32FindData = record
  dwFileAttributes: DWORD;
  ftCreationTime: TFileTime;
  ftLastAccessTime: TFileTime;
  ftLastWriteTime: TFileTime;
  nFileSizeHigh: DWORD;
  nFileSizeLow: DWORD;
  dwReserved0: DWORD;
  dwReserved1: DWORD;
  cFileName: array[0..MAX_PATH - 1] of AnsiChar;
  cAlternateFileName: array[0..13] of AnsiChar;
end;

It contains additional information, like the creation, last write and last access times (that can be converted to TDateTime using FileTime2DateTime), and the short name (DOS name or 8.3 name) of the file in the cAlternateFileName field. This field is a null (zero) terminated string, and is empty (the first char is #0) if the long name and the short name are the same.

For example, this function would return the short name of a given file:

uses SysUtils;

function ShortName(const FileName: TFileName): TFileName;
var
  SearchRec: TSearchRec;
begin
  if FindFirst(FileName, faAnyFile, SearchRec) = 0 then
  begin
    if SearchRec.FindData.cAlternateFileName[0] = #0 then
      Result := SearchRec.Name
    else
      Result := SearchRec.FindData.cAlternateFileName;
    FindClose(SearchRec);
  end else
    Result := '';
end
uses Windows;

function FileTime2DateTime(FileTime: TFileTime): TDateTime;
var
  FileDate: record
    DosTime, DosDate: Word;
  end;
begin
  FileTimeToDosDateTime(FileTime, FileDate.DosDate,
    FileDate.DosTime);
  Result := FileDateToDateTime(PInteger(@FileDate)^);
end;

GetShortPathName

Windows provides an API to get the short file name (including the short version of the file path if a path is included). Here we wrote a function to ecanpsulate this API call:

uses SysUtils, Windows;

function GetShortFilename(const FileName: TFileName): TFileName;
var
  buffer: array[0..MAX_PATH-1] of char;
begin
  SetString(Result, buffer, GetShortPathName(
    pchar(FileName), buffer, MAX_PATH-1));
end;