views:

556

answers:

3

How to convert this function to Delphi 2010 (Unicode)?

function TForm1.GetTarget(const LinkFileName:String):String;
var
   //Link : String;
   psl  : IShellLink;
   ppf  : IPersistFile;
   WidePath  : Array[0..260] of WideChar;
   Info      : Array[0..MAX_PATH] of Char;
   wfs       : TWin32FindData;
begin
  if UpperCase(ExtractFileExt(LinkFileName)) <> '.LNK' Then
  begin
    Result:='NOT a shortuct by extension!';
    Exit;
  end;

  CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, psl);
  if psl.QueryInterface(IPersistFile, ppf) = 0 Then
  Begin
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PAnsiChar(LinkFileName), -1, @WidePath, MAX_PATH);
    ppf.Load(WidePath, STGM_READ);
    psl.GetPath((@info), MAX_PATH, wfs, SLGP_UNCPRIORITY);
    Result := info;

  end
  else
    Result := '';
end;

Thanks

+1  A: 

As far as I can tell, ppf.Load should be able to just take your LinkFileName directly with a cast to PChar (which is now PWideChar). Removing the MultiByteToWideChar line and using PChar(LinkFileName) instead of copying to a temporary variable should do it.

This would make the code look like this:

function TForm1.GetTarget(const LinkFileName:String):String;
var
   //Link : String;
   psl  : IShellLink;
   ppf  : IPersistFile;
   //WidePath  : Array[0..260] of WideChar;
   Info      : Array[0..MAX_PATH] of Char;
   wfs       : TWin32FindData;
begin
  if UpperCase(ExtractFileExt(LinkFileName)) <> '.LNK' Then
  begin
    Result:='NOT a shortuct by extension!';
    Exit;
  end;

  CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, psl);
  if psl.QueryInterface(IPersistFile, ppf) = 0 Then
  Begin
    ppf.Load(PChar(LinkFileName), STGM_READ);
    psl.GetPath((@info), MAX_PATH, wfs, SLGP_UNCPRIORITY);
    Result := info;    
  end
  else
    Result := '';
end;

psl.GetPath is declared as using a LPTSTR in MSDN, so I believe you should get the Unicode version without changing that part.

Michael Madsen
A: 

I have made some more changes to Michael's answer to use the proper string conversion to upper case, check for error conditions and remove unnecessary stuff:

function TForm1.GetTarget(const LinkFileName: String): String;
var
  psl: IShellLink;
  ppf: IPersistFile;
  wfs: TWin32FindData;
begin
  if Character.ToUpper(ExtractFileExt(LinkFileName)) <> '.LNK' Then
    Exit('NOT a shortcut by extension!');

  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
    IShellLink, psl));
  if psl.QueryInterface(IPersistFile, ppf) = 0 Then
  Begin
    OleCheck(ppf.Load(PChar(LinkFileName), STGM_READ));
    SetLength(Result, MAX_PATH);
    OleCheck(psl.GetPath(PChar(Result), MAX_PATH, wfs, SLGP_UNCPRIORITY));
    Result := PChar(Result);
  end;
end;
mghie
A: 

Hello, thanks for the answers .... The first option worked perfectly, but the second gives error here ...

if Character.ToUpper (ExtractFileExt (LinkFileName)) <> '. LNK' Then Exit ( 'NOT a shortcut by extension');

Regards Leonardo

pleonardomv
Welcome to Stack Overflow. The "answer" section is for *answers* to the question. What you have posted here is not an answer. It belongs as a *comment* responding to Mghie's answer. Your reputation is still low, so you can't leave comments everywhere, but the minimum is waived for your own questions, so you are allowed to comment here. I recommend you delete this "answer" before other people come along and vote it down (since it's not helpful in answering your question).
Rob Kennedy
Sorry, but I have a hard time to help you if all you tell me is "gives error here". What error? Maybe you just did not include the Character unit? I tried the code in Delphi 2009, with success, so it's definitely OK.
mghie