diff options
Diffstat (limited to 'vfs')
| -rw-r--r-- | vfs/UVFSCore.pas | 112 | ||||
| -rw-r--r-- | vfs/uVFSprototypes.pas | 75 |
2 files changed, 91 insertions, 96 deletions
diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas index ee2a6ca..8bba788 100644 --- a/vfs/UVFSCore.pas +++ b/vfs/UVFSCore.pas @@ -41,7 +41,6 @@ type FVFSGetPrefix: TVFSGetPrefix; FVFSGetFileSystemSize: TVFSGetFileSystemSize; FVFSGetFileSystemFree: TVFSGetFileSystemFree; - FVFSLogin: TVFSLogin; FVFSFileExists: TVFSFileExists; FVFSFileInfo: TVFSFileInfo; FVFSMkDir: TVFSMkDir; @@ -65,7 +64,6 @@ type FVFSTwoSameFiles: TVFSTwoSameFiles; FVFSGetExts: TVFSGetExts; FVFSGetServices: TVFSGetServices; - FVFSSetPassword: TVFSSetPassword; FVFSGetPasswordRequired: TVFSGetPasswordRequired; FVFSSetCallbacks: TVFSSetCallbacks; public @@ -88,23 +86,21 @@ type FGlobs: Pointer; FSourcePlugin: TVFSPlugin; FBlockSize: Cardinal; - FProgressFunc: TEngineProgressFunc; - FSenderThread: Pointer; BreakProcessingKind: integer; - FPassword: string; - procedure SetFPassword(Value: string); public ArchiveMode: boolean; + Password: string; + PasswordUsed: boolean; constructor Create(SourcePlugin: TVFSPlugin); - function VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): boolean; - function VFSOpenEx(OpenFile: string): TVFSResult; + function VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; + function VFSOpenEx(OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult; function VFSClose: boolean; destructor Destroy; override; function GetListing(var List: TList; const AddDotFiles: boolean): integer; override; function GetListing(var List: TList; const AddDotFiles: boolean; APath: string): integer; override; function ChangeDir(const NewPath: string): integer; override; - function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): integer; + function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer; function ExplicitChDir(const NewPath: string): integer; override; function GetFileSystemSize: Int64; override; function GetFileSystemSize(const APath: string): Int64; override; @@ -134,21 +130,22 @@ type function GetPath: string; override; procedure SetPath(Value: string); override; function GetPrefix: string; override; - function Login(Username, Password: string): integer; override; function GetBlockSize: Cardinal; override; procedure SetBlockSize(Value: Cardinal); override; function CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; function CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; + function CopyFileInEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; + function CopyFileOutEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; function IsOnSameFS(const Path1, Path2: string): boolean; override; function TwoSameFiles(const Path1, Path2: string): boolean; override; - function SetPassword(Password: string): integer; function GetPasswordRequired: boolean; published property Path: string read GetPath write SetPath; property BlockSize: Cardinal read GetBlockSize write SetBlockSize; - property Password: string read FPassword write SetFPassword; end; @@ -199,7 +196,6 @@ begin @FVFSGetPrefix := dlsym(ModuleHandle, 'VFSGetPrefix'); @FVFSGetFileSystemSize := dlsym(ModuleHandle, 'VFSGetFileSystemSize'); @FVFSGetFileSystemFree := dlsym(ModuleHandle, 'VFSGetFileSystemFree'); - @FVFSLogin := dlsym(ModuleHandle, 'VFSLogin'); @FVFSFileExists := dlsym(ModuleHandle, 'VFSFileExists'); @FVFSFileInfo := dlsym(ModuleHandle, 'VFSFileInfo'); @FVFSMkDir := dlsym(ModuleHandle, 'VFSMkDir'); @@ -223,7 +219,6 @@ begin @FVFSTwoSameFiles := dlsym(ModuleHandle, 'VFSTwoSameFiles'); @FVFSGetExts := dlsym(ModuleHandle, 'VFSGetExts'); @FVFSGetServices := dlsym(ModuleHandle, 'VFSGetServices'); - @FVFSSetPassword := dlsym(ModuleHandle, 'VFSSetPassword'); @FVFSGetPasswordRequired := dlsym(ModuleHandle, 'VFSGetPasswordRequired'); @FVFSSetCallbacks := dlsym(ModuleHandle, 'VFSSetCallbacks'); // Initialize the extensions list @@ -294,7 +289,8 @@ begin ArchiveMode := False; BreakProcessingKind := 0; FGlobs := nil; - FPassword := ''; + Password := ''; + PasswordUsed := False; if @FSourcePlugin.FVFSNew <> nil then FGlobs := FSourcePlugin.FVFSNew(@VFSLogFunc); end; @@ -308,23 +304,28 @@ begin end; end; -function TVFSEngine.VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): boolean; +function TVFSEngine.VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; begin Result := False; if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) then begin if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, CallbackData); + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(URI)) = cVFS_OK; if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil); + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); end; end; -function TVFSEngine.VFSOpenEx(OpenFile: string): TVFSResult; +function TVFSEngine.VFSOpenEx(OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult; begin Result := cVFS_OK; - if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) - then Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)); + if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) then begin + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); + end; end; function TVFSEngine.VFSClose: boolean; @@ -510,30 +511,22 @@ begin DebugMsg(['^^VFS (II): ChangeDir end.']); end; -function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): integer; +function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer; begin if (FGlobs <> nil) and (@FSourcePlugin.FVFSChangeDir <> nil) then begin if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, CallbackData); + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); Result := ChangeDir(NewPath); if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil); + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); end; end; - procedure TVFSEngine.SetPath(Value: string); begin ChangeDir(Value); end; -function TVFSEngine.Login(Username, Password: string): integer; -begin - if (FGlobs <> nil) and (@FSourcePlugin.FVFSLogin <> nil) - then Result := FSourcePlugin.FVFSLogin(FGlobs, PChar(Username), PChar(Password)) - else Result := cVFS_OK; -end; - function TVFSEngine.FileExists(const FileName: string; const Use_lstat: boolean = False): Boolean; begin if (FGlobs <> nil) and (@FSourcePlugin.FVFSFileExists <> nil) @@ -840,32 +833,31 @@ end; (********************************************************************************************************************************) - -function VFSCopyCallBackFunc(iPos, iMax:Int64; data: Pointer): LongBool; cdecl; +function TVFSEngine.CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; begin -// DebugMsg(['VFSCopyCallBackFunc called (iPos = ', iPos, ', iMax = ', iMax, ')']); - Result := True; - if not Assigned(data) then Exit; - if Assigned(TVFSEngine(data).FProgressFunc) then - try - Result := TVFSEngine(data).FProgressFunc(TVFSEngine(data).FSenderThread, iPos); - except - on E: Exception do DebugMsg(['*** Exception raised in VFSCopyCallBackFunc(iPos=', iPos, ', iMax=', iMax, ', data=', data, '): (', E.ClassName, '): ', E.Message]); - end; + Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil); end; function TVFSEngine.CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +begin + Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil); +end; + +function TVFSEngine.CopyFileOutEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; var Res: TVFSResult; begin Result := False; try if @FSourcePlugin.FVFSCopyOut <> nil then begin - FSenderThread := Sender; - FProgressFunc := ProgressFunc; // DebugMsg(['0 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); // DebugMsg([' Pointer(FGlobs) = 0x', IntToHex(Int64(FGlobs), 16), ', Pointer(@NewVFSCopyCallBackFunc) = 0x', IntToHex(Int64(@NewVFSCopyCallBackFunc), 16), ', Pointer(Self) = 0x', IntToHex(Int64(Self), 16)]); try - Res := FSourcePlugin.FVFSCopyOut(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Res := FSourcePlugin.FVFSCopyOut(FGlobs, PChar(SourceFile), PChar(DestFile), Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); except on E: Exception do begin DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); @@ -879,7 +871,7 @@ begin cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); - cVFS_Cancelled: Result := False; + cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile); end; end else Result := False; except @@ -887,16 +879,19 @@ begin end; end; -function TVFSEngine.CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +function TVFSEngine.CopyFileInEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; + Append: boolean; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; var Res: TVFSResult; begin Result := False; try if @FSourcePlugin.FVFSCopyIn <> nil then begin - FSenderThread := Sender; - FProgressFunc := ProgressFunc; try - Res := FSourcePlugin.FVFSCopyIn(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Res := FSourcePlugin.FVFSCopyIn(FGlobs, PChar(SourceFile), PChar(DestFile), Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); except on E: Exception do begin DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); @@ -909,7 +904,7 @@ begin cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); - cVFS_Cancelled: Result := False; + cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile); end; end else Result := False; except @@ -920,25 +915,12 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) -function TVFSEngine.SetPassword(Password: string): integer; -begin - if @FSourcePlugin.FVFSSetPassword <> nil then Result := FSourcePlugin.FVFSSetPassword(FGlobs, PChar(Password)) - else Result := 0; - FPassword := Password; -end; - function TVFSEngine.GetPasswordRequired: boolean; begin if @FSourcePlugin.FVFSGetPasswordRequired <> nil then Result := FSourcePlugin.FVFSGetPasswordRequired(FGlobs) else Result := False; end; -procedure TVFSEngine.SetFPassword(Value: string); -begin - SetPassword(Value); -end; - - (********************************************************************************************************************************) (********************************************************************************************************************************) function GetBinaryPath: string; diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas index ba848e9..43190a4 100644 --- a/vfs/uVFSprototypes.pas +++ b/vfs/uVFSprototypes.pas @@ -69,7 +69,8 @@ const VFS_ASK_PASSWORD_NEED_DOMAIN = 1 shl 2; VFS_ASK_PASSWORD_SAVING_SUPPORTED = 1 shl 3; // Plugin reports if gnome-keyring is available VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED = 1 shl 4; - VFS_ASK_PASSWORD_SAVE_INTERNAL = 1 shl 15; // Save password into internal Connection Manager + VFS_ASK_PASSWORD_SAVE_INTERNAL = 1 shl 14; // Save password into internal Connection Manager + VFS_ASK_PASSWORD_ARCHIVE_MODE = 1 shl 15; // Callback from archive, change the UI a little bit type @@ -145,6 +146,38 @@ type end; type + // Return index of the choice selected or negative number when dialog has been cancelled + // cancel_choice: index which represents the cancellation choice. Set to -1 (e.g.) to disable this feature + PVFSAskQuestionCallback = ^TVFSAskQuestionCallback; + TVFSAskQuestionCallback = procedure (const AMessage: PChar; + const Choices: PPChar; + choice: PInteger; + cancel_choice: Integer; + user_data: Pointer); cdecl; + + PVFSAskPasswordCallback = ^TVFSAskPasswordCallback; + // Remember to allocate passed strings separately (use strdup() when setting reply) + // Modules are eligible for keeping passwords during one session; calling callback again means the last password was wrong and user should enter new one + // Returns True (1) if succeeded or False (0) if cancelled + TVFSAskPasswordCallback = function (const AMessage: PChar; + const default_user: PChar; + const default_domain: PChar; + const default_password: PChar; + flags: TVFSAskPasswordFlags; + username: PPChar; + password: PPChar; + anonymous: PInteger; + domain: PPChar; + password_save: PVFSPasswordSave; + user_data: Pointer): LongBool; cdecl; + + // Return False to break the operation + PVFSProgressCallback = ^TVFSProgressCallback; + TVFSProgressCallback = function (position: Int64; + max: Int64; + user_data: Pointer): LongBool; cdecl; + +type // Log function which could plugin call - the application must handle the messages (e.g. write them to the stdout) PVFSLogFunc = ^TVFSLogFunc; TVFSLogFunc = procedure(S: PChar); cdecl; @@ -177,8 +210,6 @@ type TVFSOpen = function (g:TVFSGlobs; const sName: PChar): TVFSResult; cdecl; // TODO: Opens the location (file or URI/URL) // In case of URI, do not supply password encoded in the string; plugin will automatically spawn the TVFSAskPasswordCallback callback - TVFSLogin = function (g:TVFSGlobs; const User, Pass: PChar): TVFSResult; cdecl; - // TODO: Performs login to the server TVFSClose = function (g:TVFSGlobs): TVFSResult; cdecl; // Closes the file or connection to the server TVFSMkDir = function (g:TVFSGlobs; const sDirName: PChar): TVFSResult; cdecl; @@ -214,19 +245,20 @@ type // TODO: Runs the command read from inside the archive (typically installing the rpm package) - TVFSCopyCallBackFunc = function (iPos, iMax: Int64; data: Pointer):LongBool; cdecl; - // Callback function used during the copy process; return False to break the copy process - - TVFSCopyOut = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + TVFSCopyOut = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: LongBool): TVFSResult; cdecl; // Performs the copy process from inside of module to the file in the local system // (thus sSrcName is a path from inside of module and sDstName is path in the local filesystem where the file should be copied) // The data pointer is then used to call the callback function in // Note: if you need to transfer a file between two VFS modules, you need to do it manually - either first copy to local FS or use the Open, Read, Write functions of the module (NOTE: both VFS modules have to support these functions) - TVFSCopyIn = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + TVFSCopyIn = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: LongBool): TVFSResult; cdecl; // Performs the copy process from the local filesystem into the module + // Prototype function for packing new files into archive + TVFSPack = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; CompressionLevel: integer; const Password: PChar): TVFSResult; cdecl; + + // This is the set of basic functions which can manipulate with the data // There is a TVFSFileDes object which identifies the processed file (filedescriptor) // All these functions needs a pointer to an int variable to store the error code @@ -253,7 +285,6 @@ type TVFSFileInfo = function (g:TVFSGlobs; AFileName: PChar; VFSItem: PVFSItem): TVFSResult; cdecl; // Gets a single info item without need to list a whole directory - TVFSSetPassword = function (g:TVFSGlobs; pass: PChar): TVFSResult; cdecl; TVFSGetPasswordRequired = function (g:TVFSGlobs): LongBool; cdecl; /// pridat neco jako set_loglevel ?? @@ -261,29 +292,11 @@ type //// pridat typ pluginu - jestli archive nebo protocol - prip. jeste pridat ktery protokoly je to schopno handlovat - // Return index of the choice selected or negative number when dialog has been cancelled - // cancel_choice: index which represents the cancellation choice. Set to -1 (e.g.) to disable this feature - PVFSAskQuestionCallback = ^TVFSAskQuestionCallback; - TVFSAskQuestionCallback = procedure (const AMessage: PChar; - const Choices: PPChar; - choice: PInteger; - cancel_choice: Integer; - user_data: Pointer); cdecl; - - PVFSAskPasswordCallback = ^TVFSAskPasswordCallback; - // Remember to allocate passed strings separately (use strdup() when setting reply) - TVFSAskPasswordCallback = function (const AMessage: PChar; - const default_user: PChar; - const default_domain: PChar; - flags: TVFSAskPasswordFlags; - username: PPChar; - password: PPChar; - anonymous: PInteger; - domain: PPChar; - password_save: PVFSPasswordSave; - user_data: Pointer): LongBool; cdecl; - TVFSSetCallbacks = procedure (g: TVFSGlobs; ask_question_callback: PVFSAskQuestionCallback; ask_password_callback: PVFSAskPasswordCallback; Data: Pointer); cdecl; + TVFSSetCallbacks = procedure (g: TVFSGlobs; ask_question_callback: PVFSAskQuestionCallback; + ask_password_callback: PVFSAskPasswordCallback; + progress_func: PVFSProgressCallback; + user_data: Pointer); cdecl; |
