Прояснение вопроса использования A/W функций

groovy

Новичок
Хотелось бы уточнить следующее, например, api функция CreateFile декларирована как:
C++:
HANDLE WINAPI CreateFile(
  _In_     LPCTSTR               lpFileName,
  _In_     DWORD                 dwDesiredAccess,
  _In_     DWORD                 dwShareMode,
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_     DWORD                 dwCreationDisposition,
  _In_     DWORD                 dwFlagsAndAttributes,
  _In_opt_ HANDLE                hTemplateFile
);
В Inno, если с точностью перевести, выглядит так:
Код:
function CreateFile(lpFileName: PAnsiChar; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFileA@kernel32.dll stdcall';
Прошу обратить внимание, что в первом параметре функции должен использоваться именно указатель PChar/PAnsiChar, по декларации никак не String.

Значит, ANSI версия компилятора может использовать только A версию api функций.
В Unicode можно использовать и A и W, но при использовании указателя Unicode версия Inno не понимает PChar и не имеет поддержки PWideChar, только PAnsiChar, которую понимает и ANSI версия компиля соответственно.

Предположим, что указатель в первом параметре функции, мы можем заменить строкой String или совместимой AnsiString: lpFileName: AnsiString;
Тогда возникает вопрос о целесообразности использования строк string и ansistring для Unicode версии компиля с использованием W api. Ведь Unicode версия недокументорованно поддерживает WideString, и тогда по логике мы должны использовать ее для W версии api:
Код:
function CreateFile(lpFileName: WideString; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFileW@kernel32.dll stdcall';
Неясным остается момент, что корректнее использовать в W api как строку: String или WideString? Может в каких-то определенных случаях есть разница?
 
Последнее редактирование:

El Sanchez

Новичок
в первом параметре функции должен использоваться именно указатель PChar/PAnsiChar, по декларации никак не String.
string есть ссылочный тип. Ссылка есть указатель без возможности присвоения ей nil, так что замена LPCTSTR на string кошерна.
В Unicode можно использовать и A и W
Ну вот зачем в Unicode вызывать ANSI-функцию? Если так хочется в Unicode вызывать разные версии CreateFile, то объявлять надо 2 функции: CreateFileA с типом первого параметра AnsiString и CreateFileW с типом первого параметра string.
Ведь Unicode версия недокументорованно поддерживает WideString, и тогда по логике мы должны использовать ее для W версии api
WideString это системный тип BSTR, применяется в COM/OLE. На практике в Inno использовать при описании интерфейсов.
 

groovy

Новичок
Если так хочется в Unicode вызывать разные версии CreateFile, то объявлять надо 2 функции: CreateFileA с типом первого параметра AnsiString и CreateFileW с типом первого параметра string.
Спасибо, но есть еще один вопрос, получаю 64-бит размер следующим образом:

Код:
const
    GENERIC_READ           = $80000000;
    GENERIC_WRITE          = $40000000;
    GENERIC_EXECUTE        = $20000000;
    GENERIC_ALL            = $10000000;
    FILE_SHARE_READ        = 1;
    FILE_SHARE_WRITE       = 2;
    FILE_SHARE_DELETE      = 4;
    CREATE_NEW             = 1;
    CREATE_ALWAYS          = 2;
    OPEN_EXISTING          = 3;
    OPEN_ALWAYS            = 4;
    TRUNCATE_EXISTING      = 5;
    FILE_READ_ATTRIBUTES   = $80;
    FILE_WRITE_ATTRIBUTES  = $100;
    FILE_FLAG_OPEN_REPARSE_POINT = $00200000;
    INVALID_HANDLE_VALUE   = (-1);

type
   PLARGE_INTEGER = record
   QuadPart: Int64;
end;

function CreateFile(lpFileName: String; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFileW@kernel32.dll stdcall';

function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';

function GetFileSizeEx(hFile: THANDLE; var lpFileSize: PLARGE_INTEGER): BOOL;
external 'GetFileSizeEx@kernel32.dll stdcall';

function FileSizeEx(FileName: String): Int64;
var
  hFile: THandle;
  lpFileSize: PLARGE_INTEGER;
begin
   Result := 0;
   if not FileExists(FileName) then
   begin
      Exit;
   end else
   hFile := CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
      if (INVALID_HANDLE_VALUE = hFile) then
      begin
         CloseHandle(hFile);
         Exit;                                         
      end;
      if GetFileSizeEx(hFile, lpFileSize) then
      begin
         Result := lpFileSize.QuadPart;
      end;
   CloseHandle(hFile);
end;

function InitializeSetup():Boolean;                                         
var
  I64: Int64;
begin
  I64 := FileSizeEx('C:\BIGFILE.BIN');
  MsgBox(IntToStr(I64), mbInformation, mb_OK);
  Result := False;
end;
Где второй параметр в api GetFileSizeEx var lpFileSize: PLARGE_INTEGER также можно заменить на out lpFileSize: PLARGE_INTEGER.

Опять возникает вопрос, что корректнее использовать в Inno для api с out параметрами: var или out?
Так то ясно, что директивы отличаются способом хранения переменных, где var может изменяться, а out нет. Однако, именно в api функциях есть все-таки разница в данном случае или подобных, где параметр не нужно изменять в пределах одной функции?
 
Последнее редактирование:
Сверху