|
Registriert seit: 5. Jan 2005 Ort: Stadthagen 9.454 Beiträge Delphi 10 Seattle Enterprise |
#1
Warum wurde die Win32Api Funktion
Code:
in Delphi so deklariert
BOOL WINAPI GetDiskFreeSpaceEx(
_In_opt_ LPCTSTR lpDirectoryName, _Out_opt_ PULARGE_INTEGER lpFreeBytesAvailable, _Out_opt_ PULARGE_INTEGER lpTotalNumberOfBytes, _Out_opt_ PULARGE_INTEGER lpTotalNumberOfFreeBytes );
Delphi-Quellcode:
und nicht so
function GetDiskFreeSpaceEx(
{} lpDirectoryName: LPCWSTR; // äh, wieso var und ohne Typen-Angabe? {} var {} lpFreeBytesAvailableToCaller, {} lpTotalNumberOfBytes; // ja, das verstehe ich wieder {} lpTotalNumberOfFreeBytes: PLargeInteger ): BOOL; stdcall;
Delphi-Quellcode:
Warum werden zwei Parameter bewusst falsch implementiert und der letzte korrekt?
function GetDiskFreeSpaceEx(
{} lpDirectoryName: LPCWSTR; {} lpFreeBytesAvailableToCaller: PLargeInteger; {} lpTotalNumberOfBytes: PLargeInteger; {} lpTotalNumberOfFreeBytes: PLargeInteger ): BOOL; stdcall; Folgender Aufruf (nach der Win32Api wäre das völlig korrekt) wird sofort angemeckert.
Delphi-Quellcode:
Eine mögliche Antwort darauf könnte sein, dass diese Funktion in der RTL verwendet wird.
GetDisFreeSpaceEx(
'C:\', nil, // <- Mecker nil, // <- Mecker nil );
Delphi-Quellcode:
So, weil dort also zwei Parameter immer gesetzt werden und der letzte Parameter nicht benötigt wird und somit auf nil
gesetzt werden soll, hat man also den Api-Aufruf so deklariert, dass der zu dieser Funktion passt.
unit System.SysUtils;
function InternalGetDiskSpace(Drive: Byte; var TotalSpace, FreeSpaceAvailable: Int64): Bool; var RootPath: array[0..4] of Char; RootPtr: PChar; begin RootPtr := nil; if Drive > 0 then begin RootPath[0] := Char(Drive + $40); RootPath[1] := ':'; RootPath[2] := '\'; RootPath[3] := #0; RootPtr := RootPath; end; Result := GetDiskFreeSpaceEx(RootPtr, FreeSpaceAvailable, TotalSpace, nil); end; Gut man hätte die Api-Funktion auch richtig deklarieren können und diese Funktion so umsetzen:
Delphi-Quellcode:
Ich finde es jetzt auf die Schnelle nicht, aber solche fehlerhaften Übersetzungen der Api wurden/werden regelmässig als Bug gemeldet und mit der gleichen stoischen Regelmässigkeit als as designed geschlossen. Ja, nee .. is klar.
function InternalGetDiskSpace( Drive: Byte; var TotalSpace, FreeSpaceAvailable: Int64 ): Bool;
var RootPath: array [ 0 .. 4 ] of Char; RootPtr: PChar; begin RootPtr := nil; if Drive > 0 then begin RootPath[ 0 ] := Char( Drive + $40 ); RootPath[ 1 ] := ':'; RootPath[ 2 ] := '\'; RootPath[ 3 ] := #0; RootPtr := RootPath; end; Result := GetDiskFreeSpaceEx( RootPtr, PLargeInteger( FreeSpaceAvailable ), PLargeInteger( TotalSpace ), nil ); end; Ich mache mir die Welt, wie sie mir gefällt. ![]() Übrig bleibt dann nur noch, sich diese Funktionen selber zu deklarieren - gut dann aber auch so richtig richtig:
Delphi-Quellcode:
unit netAlike.Winapi.Windows;
interface uses Winapi.Windows; procedure CheckApiCall( ApiCallResult: BOOL; const AdditionalInfo: string = '' ); {$REGION 'GetDiskFreeSpaceEx'} /// <summary> /// Retrieves information about the amount of space that is available on a disk volume, which is the total amount of space, /// the total amount of free space, and the total amount of free space available to the user that is associated with the calling thread. /// </summary> /// <param name="lpDirectoryName">[in, optional] /// <para>A directory on the disk.</para> /// <para>If this parameter is NULL, the function uses the root of the current disk.</para> /// <para>If this parameter is a UNC name, it must include a trailing backslash, for example, "\\MyServer\MyShare\".</para> /// <para>This parameter does not have to specify the root directory on a disk. The function accepts any directory on a disk.</para> /// <para>The calling application must have <see cref="FILE_LIST_DIRECTORY"/> access rights for this directory.</para> /// </param> /// <param name="lpFreeBytesAvailableToCaller">[out, optional] /// <para> /// A pointer to a variable that receives the total number of free bytes on a disk that are available /// to the user who is associated with the calling thread. /// </para> /// <para>This parameter can be NULL.</para> /// <para>If per-user quotas are being used, this value may be less than the total number of free bytes on a disk.</para> /// </param> /// <param name="lpTotalNumberOfBytes">[out, optional] /// <para> /// A pointer to a variable that receives the total number of bytes on a disk that are available to the user /// who is associated with the calling thread. /// </para> /// <para>This parameter can be NULL.</para> /// <para>If per-user quotas are being used, this value may be less than the total number of bytes on a disk.</para> /// <para>To determine the total number of bytes on a disk or volume, use <see cref="IOCTL_DISK_GET_LENGTH_INFO"/>.</para> /// </param> /// <param name="lpTotalNumberOfFreeBytes">[out, optional] /// <para>A pointer to a variable that receives the total number of free bytes on a disk.</para> /// <para>This parameter can be NULL.</para> /// </param> function GetDiskFreeSpaceEx( { IN OPT } lpDirectoryName: LPCWSTR; { OUT OPT } lpFreeBytesAvailableToCaller: PLargeInteger; { OUT OPT } lpTotalNumberOfBytes: PLargeInteger; { OUT OPT } lpTotalNumberOfFreeBytes: PLargeInteger ): BOOL; stdcall; {$EXTERNALSYM GetDiskFreeSpaceEx} function GetDiskFreeSpaceExA( { IN OPT } lpDirectoryName: LPCSTR; { OUT OPT } lpFreeBytesAvailableToCaller: PLargeInteger; { OUT OPT } lpTotalNumberOfBytes: PLargeInteger; { OUT OPT } lpTotalNumberOfFreeBytes: PLargeInteger ): BOOL; stdcall; {$EXTERNALSYM GetDiskFreeSpaceExA} function GetDiskFreeSpaceExW( { IN OPT } lpDirectoryName: LPCWSTR; { OUT OPT } lpFreeBytesAvailableToCaller: PLargeInteger; { OUT OPT } lpTotalNumberOfBytes: PLargeInteger; { OUT OPT } lpTotalNumberOfFreeBytes: PLargeInteger ): BOOL; stdcall; {$ENDREGION} {$REGION 'GetVolumeInformation'} /// <summary> /// Retrieves information about the file system and volume associated with the specified root directory. /// </summary> /// <param name="lpRootPathName">[in, optional] /// <para>A pointer to a string that contains the root directory of the volume to be described.</para> /// <para> /// If this parameter is NULL, the root of the current directory is used. A trailing backslash is required. /// For example, you specify \\MyServer\MyShare as "\\MyServer\MyShare\", or the C drive as "C:\". /// </para> /// </param> /// <param name="lpVolumeNameBuffer">[out, optional] /// <para> /// A pointer to a buffer that receives the name of a specified volume. The buffer size is specified by /// the nVolumeNameSize parameter. /// </para> /// </param> /// <param name="nVolumeNameSize">[in] /// <para>The length of a volume name buffer, in TCHARs. The maximum buffer size is MAX_PATH+1.</para> /// <para>This parameter is ignored if the volume name buffer is not supplied.</para> /// </param> /// <param name="lpVolumeSerialNumber">[out, optional] /// <para>A pointer to a variable that receives the volume serial number.</para> /// <para>This parameter can be NULL if the serial number is not required.</para> /// <para> /// This function returns the volume serial number that the operating system assigns when a hard disk is formatted. /// To programmatically obtain the hard disk's serial number that the manufacturer assigns, use the Windows Management /// Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber. /// </para> /// </param> /// <param name="lpMaximumComponentLength">[out, optional] /// <para>A pointer to a variable that receives the maximum length, in TCHARs, of a file name component that a specified file system supports.</para> /// <para>A file name component is the portion of a file name between backslashes.</para> /// <para> /// The value that is stored in the variable that *lpMaximumComponentLength points to is used to indicate that a /// specified file system supports long names. For example, for a FAT file system that supports long names, the /// function stores the value 255, rather than the previous 8.3 indicator. Long names can also be supported on /// systems that use the NTFS file system. /// </para> /// </param> /// <param name="lpFileSystemFlags">[out, optional] /// <para>A pointer to a variable that receives flags associated with the specified file system.</para> /// <para>This parameter can be one or more of the following flags. However, FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED are mutually exclusive.</para> /// </param> /// <param name="lpFileSystemNameBuffer">[out, optional] /// <para> /// A pointer to a buffer that receives the name of the file system, for example, the FAT file system or the NTFS file system. /// The buffer size is specified by the nFileSystemNameSize parameter. /// </para> /// </param> /// <param name="nFileSystemNameSize">[in] /// <para>The length of the file system name buffer, in TCHARs. The maximum buffer size is MAX_PATH+1.</para> /// <para>This parameter is ignored if the file system name buffer is not supplied.</para> /// </param> function GetVolumeInformation( { IN OPT } lpRootPathName: LPCWSTR; { OUT OPT } lpVolumeNameBuffer: LPWSTR; { IN } nVolumeNameSize: DWORD; { OUT OPT } lpVolumeSerialNumber: LPDWORD; { OUT OPT } lpMaximumComponentLength: LPDWORD; { OUT OPT } lpFileSystemFlags: LPDWORD; { OUT OPT } lpFileSystemNameBuffer: LPWSTR; { IN } nFileSystemNameSize: DWORD ): BOOL; stdcall; {$EXTERNALSYM GetVolumeInformation} function GetVolumeInformationA( { IN OPT } lpRootPathName: LPCSTR; { OUT OPT } lpVolumeNameBuffer: LPSTR; { IN } nVolumeNameSize: DWORD; { OUT OPT } lpVolumeSerialNumber: LPDWORD; { OUT OPT } lpMaximumComponentLength: LPDWORD; { OUT OPT } lpFileSystemFlags: LPDWORD; { OUT OPT } lpFileSystemNameBuffer: LPSTR; { IN } nFileSystemNameSize: DWORD ): BOOL; stdcall; {$EXTERNALSYM GetVolumeInformationA} function GetVolumeInformationW( { IN OPT } lpRootPathName: LPCWSTR; { OUT OPT } lpVolumeNameBuffer: LPWSTR; { IN } nVolumeNameSize: DWORD; { OUT OPT } lpVolumeSerialNumber: LPDWORD; { OUT OPT } lpMaximumComponentLength: LPDWORD; { OUT OPT } lpFileSystemFlags: LPDWORD; { OUT OPT } lpFileSystemNameBuffer: LPWSTR; { IN } nFileSystemNameSize: DWORD ): BOOL; stdcall; {$EXTERNALSYM GetVolumeInformationW} {$ENDREGION} implementation uses System.SysUtils; procedure CheckApiCall( ApiCallResult: BOOL; const AdditionalInfo: string ); begin if not ApiCallResult then RaiseLastOsError( GetLastError, sLineBreak + AdditionalInfo ); end; function GetDiskFreeSpaceEx; external kernelbase name 'GetDiskFreeSpaceExW'; function GetDiskFreeSpaceExA; external kernelbase name 'GetDiskFreeSpaceExA'; function GetDiskFreeSpaceExW; external kernelbase name 'GetDiskFreeSpaceExW'; function GetVolumeInformation; external kernelbase name 'GetVolumeInformationW'; function GetVolumeInformationA; external kernelbase name 'GetVolumeInformationA'; function GetVolumeInformationW; external kernelbase name 'GetVolumeInformationW'; end.
Kaum macht man's richtig - schon funktioniert's
![]() Zertifikat: Sir Rufo (Fingerprint: ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |