Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teach the installer to create Cygwin symlinks even in non-US locales #265

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions installer/install.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2368,24 +2368,50 @@ function GetFileAttributes(Path:PAnsiChar):DWORD;
function SetFileAttributes(Path:PAnsiChar;dwFileAttributes:DWORD):BOOL;
external '[email protected] stdcall';
function CryptStringToBinary(sz:string;cch:LongWord;flags:LongWord;binary:string;var size:LongWord;skip:LongWord;flagsused:LongWord):Integer;
external '[email protected] stdcall';
const
CRYPT_STRING_HEX = $04;
HEX_CHARS = '0123456789abcdef';
function CharToHex(C:Integer):string;
begin
Result:=HEX_CHARS[((C div 16) and 15)+1]+HEX_CHARS[(C and 15)+1];
end;
function CreateCygwinSymlink(SymlinkPath,TargetPath:String):Boolean;
var
Attribute:DWord;
i:Integer;
Hex,Buffer:string;
Stream:TStream;
Size:LongWord;
begin
Result:=True;
// assuming that the target is actually all-ASCII, convert to UTF-16
for i:=Length(TargetPath) downto 1 do
TargetPath:=Copy(TargetPath,1,i)+#0+Copy(TargetPath,i+1,Length(TargetPath)-i);
// insert `!<symlink>\xff\xfe` prefix, and append `\0\0`
TargetPath:='!<symlink>'+#255+#254+TargetPath+#0+#0;
Hex:='213c73796d6c696e6b3efffe'; // "!<symlink>\xff\xfe"
for i:=1 to Length(TargetPath) do
Hex:=Hex+CharToHex(Ord(TargetPath[i])); // append wide characters as hex
Hex:=Hex+'0000'; // append a wide NUL
// write the file
if not SaveStringToFile(SymlinkPath,TargetPath,False) then begin
LogError('Could not write "'+SymlinkPath+'"');
Stream:=TFileStream.Create(SymlinkPath,fmCreate);
try
Size:=Length(Hex) div 2;
SetLength(Buffer,Size);
if (CryptStringToBinary(Hex,Length(Hex),CRYPT_STRING_HEX,Buffer,Size,0,0)=0) or (Size<>Length(Hex) div 2) then
RaiseException('could not decode hex '+Hex);
Stream.WriteBuffer(Buffer,Size);
except
LogError('Could not write "'+SymlinkPath+'" '+GetExceptionMessage());
Result:=False;
finally
Stream.Free
end;
// Set system bit (required for Cygwin to interpret this as a symlink)
Expand Down