This happens at file system level so you there is no much you can do if you don't want to disable SFN generation at all.
The way I use to handle this problem is to:
1) Before the file is copied, I check if the file name exists.
2) If there is a collision then I first rename the existing file top some temporary name
3) Then I copy the file
4) rename the first file back.
To detect the collision do something like this:
function IsCollition(const Source, Destination: string; var ExistingName: string): boolean;
var
DesFD: TSearchRec;
Found: boolean;
ShortSource, FoundName: string;
begin
ShortSource:= ExtractFileName(SourceName);
Found:= false;
FoundName:= WS_NIL;
if (FindFirst(DestinationName, faAnyFile, DesFD) = 0) then
begin
Found:= true;
FoundName:= DesFD.Name;
SysUtils.FindClose(DesFD);
end;
if (not Found) or (SameFileName(ShortSource, FoundName)) then
begin
Result:= false;
end else
begin
// There iis a collision:
// A file exists AND it's long name is not equal to the original name
Result:= true;
end;
ExistingName:= FoundName;
end;