Solved

diskfreespace

Posted on 2000-02-29
21
347 Views
Last Modified: 2010-04-04
hallo to all,

under D3/WIN98 i tried to determine the size of a disk
with the function getdiskfreespace.

i always receive freeclusters=65526 and totalclusters=65526.
but there are large disks (6 GB, 8 GB). that cannot be correct !

i think the problem is, that perhaps the function returns
only integer-values and no longint-values.

any idea how i can get the correct disksize ?

thanks
titz
0
Comment
Question by:titz
  • 7
  • 4
  • 3
  • +4
21 Comments
 
LVL 7

Expert Comment

by:RBertora
ID: 2568842
Hi, straight from
the win32 help:


The GetDiskFreeSpace function returns incorrect values for volumes that are larger than 2 gigabytes. The function caps the values stored into *lpNumberOfFreeClusters and *lpTotalNumberOfClusters so as to never report volume sizes that are greater than 2 gigabytes.


BOOL GetDiskFreeSpaceEx(

    LPCTSTR lpDirectoryName,      // pointer to directory name on disk of interest  
    PULARGE_INTEGER lpFreeBytesAvailableToCaller,      // pointer to variable to receive free bytes on disk available to the caller
    PULARGE_INTEGER lpTotalNumberOfBytes,      // pointer to variable to receive number of bytes on disk
    PULARGE_INTEGER lpTotalNumberOfFreeBytes      // pointer to variable to receive free bytes on disk
   );      
 

Parameters

lpDirectoryName

Pointer to a null-terminated string that specifies a directory on the disk of interest. This string can be a UNC name.

If lpDirectoryName is NULL, the GetDiskFreeSpaceEx function obtains information about the disk that contains the currect directory.
Note that lpDirectoryName does not have to specify the root directory on a disk. The function accepts any directory on the disk.

lpFreeBytesAvailableToCaller

Pointer to a variable to receive the total number of free bytes on the disk that are available to the user associated with the calling thread.

If the operating system implements per-user quotas, this value may be less than the total number of free bytes on the disk.

lpTotalNumberOfBytes

Pointer to a variable to receive the total number of bytes on the disk.

lpTotalNumberOfFreeBytes

Pointer to a variable to receive the total number of free bytes on the disk.
This parameter can be NULL.

Rob;-)
0
 
LVL 7

Expert Comment

by:RBertora
ID: 2568844
ie try
GetDiskFreeSpaceEx
0
 
LVL 1

Author Comment

by:titz
ID: 2569864
hi,

i have D3 and there is no such thing like PULARGE_INTEGER. maybe in D4 or D5.
even my help does not know the getdiskfreespaceex-
call.

to define these variables as longint is not possible
and a larger size is in D3 not possible. or ?

any idea ?

thanks
titz
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2570560
In Delphi 3 use COMP in leiu of PULARGE_INTEGER.


 
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2570571
also, you couled just define the LargeInteger yourself.. it's just another type:

Type
  _LARGE_INTEGER = record
    case Integer of
    0: (
      LowPart: DWORD;
      HighPart: Longint);
    1: (
      QuadPart: LONGLONG);
  end;


Good luck!!
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2571000
I don't know if Delphi 3 has the DiskFree function but this one returns an int64.
0
 
LVL 1

Author Comment

by:titz
ID: 2573692
hi,

the correct parameters for getdiskfreespaceex in D3 are:
LPCTSTR  name
freebytesavailable : integer
totalnumberofbytes : integer
totalnumberofbytesfree  : Pinteger

only with these definitions a compilation was possible.
(COMP or _large_inter does not work for compilation-errors).
but the result was not correct, for the totalnumberofbytes
is an integer. and this is to small for 6Gbyte.
that is the same problem i started with.

any other ideas ?
i have none.

by the way: under WIN2000 the
function getfreediskspace works correct !

thanks
titz


0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2573709
Does Delphi 3 have the DiskFree function (see also my previous comment)?
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2573734
From the WinAPI help file:

BTW, the function is NOT Delphi version dependent, only the datatypes are. For this I suggested that you define your own LargeInteger record.



BOOL GetDiskFreeSpaceEx(

    LPCTSTR lpDirectoryName,      // pointer to directory name on disk of interest  
    PULARGE_INTEGER lpFreeBytesAvailableToCaller,      // pointer to variable to receive free bytes on disk available to the caller
    PULARGE_INTEGER lpTotalNumberOfBytes,      // pointer to variable to receive number of bytes on disk
    PULARGE_INTEGER lpTotalNumberOfFreeBytes      // pointer to variable to receive free bytes on disk
   );      
 
0
 
LVL 4

Expert Comment

by:Radler
ID: 2574826
Hi titz,

I pass by troulbles with Win95a and the metions forgeten it.
well I'm using this, if int64 ins'nt supported by your compiler use extended type.

{Retorna o espaco livre de uma unidade de disco}
function _DiskFree( Drive : byte ) : int64;
var
  RootPath: array[0..4] of Char;
  RootPtr: PChar;
  SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters: cardinal;
  OS : OSVERSIONINFO;
  TotalFree, TotalExisting : int64;
begin
      RootPtr := nil;
      if Drive > 0 then
      begin
        StrCopy(RootPath, 'A:\');
        RootPath[0] := Char(Drive + $40);
        RootPtr := RootPath;
      end;
      OS.dwOSVersionInfoSize:=SizeOf(OSVERSIONINFO);
      GetVersionEx( OS );
      if (OS.dwMajorVersion = 4) and ( OS.dwBuildNumber < 1000) and ( OS.dwPlatformId = 1) then begin //Usar modo do OSR1
            if GetDiskFreeSpace(RootPtr, SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters) then begin
                  Result := (SectorsPerCluster * BytesPerSector * FreeClusters);
            end else begin
                  Result := -1;
            end;
      end else begin //Usar os servicos do NT ou Win95B ou superior
            if not GetDiskFreeSpaceEx(RootPtr,Result , TotalExisting, @TotalFree) then begin
                  Result := -1;
            end;
      end;
end;

T++, Radler.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 1

Author Comment

by:titz
ID: 2577364
hi,

now there several answers and i tried all:

epsylon: D3 has the DISKFREE-function, but it is
         only an integer!

radler: int64 is not defined in D3
the correct parameters for getdiskfreespaceex in D3 are:
LPCTSTR  name
freebytesavailable : integer
totalnumberofbytes : integer
totalnumberofbytesfree  : Pinteger
and only these types are supported.

what kind of extended do you mean ?

drdelphi: your large_integer-definition does not work
           because of compiler-error.

i think there will be no solution under D3 and WIN98.

but now we have carneval . therefore i will be back at tuesday or so.
have nice days !
titz
0
 
LVL 4

Expert Comment

by:Radler
ID: 2578448
Hi titz,

Are you Brazilian ?
I'm from Recife, at my opinion the best carneval from Brazil :-)
Extended ?
See what the Delphi docs from delphi tell me
Real48      2.9 x 10^–39 .. 1.7 x 10^38      11–12      6
Single      1.5 x 10^–45 .. 3.4 x 10^38      7–8      4
Double      5.0 x 10^–324 .. 1.7 x 10^308      15–16      8
Extended      3.6 x 10^–4951 .. 1.1 x 10^4932      19–20      10
Comp      –2^63+1 .. 2^63 –1      19–20      8
Currency      –922337203685477.5808.. 922337203685477.5807      19–20      8
You really ran my code ?

T++, Radler, and my return is tuesday too !
0
 
LVL 4

Expert Comment

by:jeurk
ID: 2581059
hello,
I suggest you try that first, just create a new
program add a button.

the result is in bytes but you know that already.

and cut and paste the following unit.

///==========================

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    btnButton1: TButton;
    procedure btnButton1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function GetDiskFreeSpaceEx(lpDirectoryName: PAnsiChar;
   var lpFreeBytesAvailableToCaller : Integer;
   var lpTotalNumberOfBytes: Integer;
   var lpTotalNumberOfFreeBytes: Integer) : bool;
   stdcall;
   external kernel32
   name 'GetDiskFreeSpaceExA';


 procedure GetDiskSizeAvail(TheDrive : PChar;
                            var TotalBytes : double;
                            var TotalFree : double);
 var
   AvailToCall : integer;
   TheSize : integer;
   FreeAvail : integer;
 begin
   GetDiskFreeSpaceEx(TheDrive,
                      AvailToCall,
                      TheSize,
                      FreeAvail);
 {$IFOPT Q+}
  {$DEFINE TURNOVERFLOWON}
  {$Q-}
 {$ENDIF}
   if TheSize >= 0 then
     TotalBytes := TheSize else
   if TheSize = -1 then begin
     TotalBytes := $7FFFFFFF;
     TotalBytes := TotalBytes * 2;
     TotalBytes := TotalBytes + 1;
   end else
   begin
     TotalBytes := $7FFFFFFF;
     TotalBytes := TotalBytes + abs($7FFFFFFF - TheSize);
   end;

   if AvailToCall >= 0 then
     TotalFree := AvailToCall else
   if AvailToCall = -1 then begin
     TotalFree := $7FFFFFFF;
     TotalFree := TotalFree * 2;
     TotalFree := TotalFree + 1;
   end else
   begin
     TotalFree := $7FFFFFFF;
     TotalFree := TotalFree + abs($7FFFFFFF - AvailToCall);
   end;
 end;

procedure TForm1.btnButton1Click(Sender: TObject);
 var
   TotalBytes : double;
   TotalFree : double;
 begin
   GetDiskSizeAvail('C:\',
                    TotalBytes,
                    TotalFree);
   ShowMessage(FloatToStr(TotalBytes));
   ShowMessage(FloatToStr(TotalFree));
 end;

end.


CU.
0
 
LVL 1

Author Comment

by:titz
ID: 2593091
hi Radler,
iam very sorry, but i am not brasilian. i am german, and we too have now carnaval. but i think you are right: i like the carnaval in brasil more than here.  
but the carnaval here is better than no carnaval !

i tried your code.
but i had compiler-problems: the error-message was, that the variable-types are not the right ones (sectorspercluser, ...:cardinal).
That was the problem. i think you have a newer version of delphi than i. because the definitions of real48 or int64 are not known in delphi.

hi jeurk,
i will try your suggestion tomorrow.
i will be back soon.
thanks,
titz
0
 
LVL 1

Author Comment

by:titz
ID: 2597243
hi jeurk,

the values have nothing to do with reality.
Even sometimes the totalbytes is lower than totalfree.
i tried it on several large disks (4Gbyte to 8 Gbyte).
i do not understand some parts of your program:
i think that you gues that the values of
getdiskfreespaceex are correct but only negative.

cheers to all
titz
0
 

Expert Comment

by:frangers99
ID: 2603784
go to http://www.delphipages.com and have a look under System/API there is a freeware component that does API calls (like diskspace) easily. It's called TinyAPI I think, have a look it's on the 2nd last page of the System/API components page.

Andrew
0
 
LVL 1

Author Comment

by:titz
ID: 2606085
hi andrew,

i did not find it under System/API.
can you give me the correct name, please ?

titz
0
 
LVL 4

Accepted Solution

by:
jeurk earned 50 total points
ID: 2611661
hello,

Let's try again ;)

here is a program I did myself cuting and pasting from D5 ;)

-create a new program
add a button.

and this is the unit :

======================================
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    btnButton1: TButton;
    procedure btnButton1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  ULARGE_INTEGER = record
    case Integer of
      0: (
        LowPart: DWORD;
        HighPart: DWORD);
      1: (
        QuadPart: LONGLONG);
  end;

  PULargeInteger = ^TULargeInteger;
  TULargeInteger = ULARGE_INTEGER;

var
  Form1: TForm1;
  GetDiskFreeSpaceEx: function(Directory: PChar; var FreeAvailable,
    TotalSpace, TotalFree: ULARGE_INTEGER): Bool stdcall = nil;

implementation

{$R *.DFM}

procedure InitDriveSpacePtr;
var
  Kernel: THandle;
begin
  Kernel := GetModuleHandle(Windows.Kernel32);
  if Kernel <> 0 then
    @GetDiskFreeSpaceEx := GetProcAddress(Kernel, 'GetDiskFreeSpaceExA');
end;

function InternalGetDiskSpace(Drive: Byte;
  var TotalSpace, FreeSpaceAvailable: ULARGE_INTEGER): Bool;
var
  RootPath: array[0..4] of Char;
  RootPtr: PChar;
  Test: ULARGE_INTEGER;
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, Test);
end;

//DiskFree returns the number of free bytes on the specified drive, where 0 = Current, 1 = A, 2 = B, and so on.
//DiskFree returns -1 if the drive number is invalid.

function DiskFree(Drive: Byte): ULARGE_INTEGER;
var
  TotalSpace: ULARGE_INTEGER;
begin
  if not InternalGetDiskSpace(Drive, TotalSpace, Result) then
    Result.QuadPart := -1;
end;

procedure TForm1.btnButton1Click(Sender: TObject);
var
  disk: byte;
  freeS: ULARGE_INTEGER;
  resultinMB:integer;
begin
  InitDriveSpacePtr; //to get the pointer on the getdiskfreespaceEx function
  disk := 3; //for H:

  freeS := DiskFree(disk);
  resultinMB := round(freeS.QuadPart / 1024 / 1024);

  showmessage('The disk has '+intToStr(resultinMB)+' mega bytes free');

  //the total size in byte of the disk is in quadpart
end;

end.

//I have tested it under D3 and it is working on my 15Gb disk

Have fun
0
 
LVL 4

Expert Comment

by:jeurk
ID: 2611666
Euh, 3 is for C: ;)
0
 
LVL 1

Author Comment

by:titz
ID: 2616923
hi,

that is the solution !!!!

fantastic ! it works on all disks correct !
Many thanks !

titz
0
 
LVL 4

Expert Comment

by:jeurk
ID: 2619003
You're welcome.
Remember that it will not work under 95
if you don't have osr2.x
And I think if your drive is a fat32 on the network it will not
work correctly either. But this is ms's fault.
CU
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now