+3  A: 

What HRESULT value is CoGetObject() actually returning?

Do not cast a WideString to a pWideString when calling a COM function. Pass it in as-is and let Delphi handle the marshalling details for you.

And there is no need to call CoCreateInstance() after calling CoGetObject(). CoGetObject() already returns the required COM object to you. Use it as-is.

Try this:

function CopyItem(const aSrcItem, aDest, aNewName: string): HResult;
const
  CLSID_FileOp: TGUID = '{3ad05575-8857-4850-9277-11b85bdb8e09}';
var
  lFileOperation: ShlObj.IFileOperation;
  psiFrom: IShellItem;
  psiTo: IShellItem;
  BindOpts: TBindOpts3;
  MonikerName: WideString;
begin
  try
    Result := CoInitialize(nil);
    OleCheck(Result);
    try
      ZeroMemory(@BindOpts, Sizeof(TBindOpts3)); 
      BindOpts.cbStruct := Sizeof(TBindOpts3); 
      BindOpts.hwnd := 0; 
      BindOpts.dwClassContext := CLSCTX_LOCAL_SERVER; 

      MonikerName := 'Elevation:Administrator!new:' + GUIDToString(CLSID_FileOp); 
      Result := CoGetObject(MonikerName, @BindOpts, ShlObj.IFileOperation, lFileOperation); 
      OleCheck(Result);

      Result := lFileOperation.SetOperationFlags(FOFX_SHOWELEVATIONPROMPT or FOFX_NOCOPYHOOKS or FOFX_REQUIREELEVATION);  
      OleCheck(Result);

      Result := SHCreateItemFromParsingName(PChar(aSrcItem), nil, IShellItem, psiFrom); 
      OleCheck(Result);

      if aDest <> '' then 
      begin 
        Result := SHCreateItemFromParsingName(PChar(aDest), nil, IShellItem, psiTo); 
        OleCheck(Result);
      end; 

      Result := lFileOperation.CopyItem(psiFrom, psiTo, PChar(aNewName), nil); 
      OleCheck(Result);

      Result := lFileOperation.PerformOperations;
      OleCheck(Result);
    finally 
      CoUninitialize; 
    end; 
  except
    on E: Exception do ShowMessage(d.ToString());
  end;
end;
Remy Lebeau - TeamB