[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now


GetDiskFreeSpace returns wrong total clusters under XP

Posted on 2004-11-10
Medium Priority
Last Modified: 2013-12-03
I have some code that was working under Windows 2000 but returns bizarre results under XP (SP1).

GetDiskFreeSpace on a diskette drive returns 805,306,368 (0x30000000) for TotalNumberOfClusters.  GetDiskFreeSpaceEx returns 1,407,374,883,553,280 (0x0005000000000000) for TotalNumberOfBytes.

The above was using "A:\\" as the volume name.  However I tried "C:\\", "X:\\" (where X drive is not present) and even "?:\\" and I always get the same result from GetDiskFreeSpace and GetDiskFreeSpaceEx (which do not return 0 for error).  SectorsPerCluster always returns 4096 and BytePerSector is always 512.  I doubt these values are the same for A: and C:.

And why does GetDiskFreeSpace on "?:\\" not even return an error.

I searched help and the web on this problem but could not find a mention of it.

I realise that I can use IOCTL_DISK_GET_LENGTH_INFO, but what is wrong with GetDiskFreeSpace under XP?!?
Question by:aphillips
LVL 17

Expert Comment

ID: 12553032
I'm using GetDiskFreeSpace under xp.
Works OK. Could You please give the code?
LVL 48

Expert Comment

ID: 12554606
Just For Knowlege  


Here is code you should try

Public Declare Function GetDiskFreeSpace Lib "kernel32" _
   Alias "GetDiskFreeSpaceA" _
  (ByVal lpRootPathName As String, _
   lpSectorsPerCluster As Long, _
   lpBytesPerSector As Long, _
   lpNumberOfFreeClusters As Long, _
   lpTtoalNumberOfClusters As Long) As Long
Public Declare Function GetDiskFreeSpaceEx Lib "kernel32" _
   Alias "GetDiskFreeSpaceExA" _
   (ByVal lpRootPathName As String, _
   lpFreeBytesAvailableToCaller As Currency, _
   lpTotalNumberOfBytes As Currency, _
   lpTotalNumberOfFreeBytes As Currency) As Long

debug.Print " Disk size:", Format$(GetDiskSpace(sDrive), "###,###,###,###,##0")
  debug.Print " Total free:", Format$(GetDiskSpaceFree(sDrive), "###,###,###,###,##0")
  debug.Print " Bytes free:", Format$(GetDiskBytesAvailable(sDrive), "###,###,###,###,##0")
  debug.Print " Disk used :", Format$(GetDiskSpaceUsed(sDrive), "###,###,###,###,##0")

Author Comment

ID: 12561064
> I'm using GetDiskFreeSpace under xp.

The code with the problem was built with VC7 (ie Visual Studio.Net) and run under XP SP1.

I tried exactly the same code at home but built with VC6 and run under XP (not SP1) and it works fine.  In that case I get SectorsPerCluster = 1, BytesPerSector = 512 and correct values for number of clusters.

> Could You please give the code?

// Disk volume - file name of form <\\.\D:>
_TCHAR vol[4] = _T("?:\\");
vol[0] = 'A';  // or 'C' or 'X' or '?'
DWORD SectorsPerCluster;
DWORD BytesPerSector;
DWORD NumberOfFreeClusters;
DWORD TotalNumberOfClusters;

if (!::GetDiskFreeSpace(vol,
        // never gets here, even for drive 'X' or '?'
        return FALSE;
m_SectorSize = BytesPerSector;

ULARGE_INTEGER total_bytes;
m_Length = total_bytes.QuadPart;  // m_Length is an __int64
Get quick recovery of individual SharePoint items

Free tool – Veeam Explorer for Microsoft SharePoint, enables fast, easy restores of SharePoint sites, documents, libraries and lists — all with no agents to manage and no additional licenses to buy.


Author Comment

ID: 12561338
Stepping into the assembler the C++ generated code pushes the parameters and calls __imp__GetDiskFreeSpaceA@20 (72AC6Ch).  Stepping into that I see this:

0157D4A0  push        ebp  
0157D4A1  mov         ebp,esp
0157D4A3  mov         eax,dword ptr [ebp+18h]
0157D4A6  push        eax  
0157D4A7  mov         ecx,dword ptr [ebp+14h]
0157D4AA  push        ecx  
0157D4AB  mov         edx,dword ptr [ebp+10h]
0157D4AE  push        edx  
0157D4AF  mov         eax,dword ptr [ebp+0Ch]
0157D4B2  push        eax  
0157D4B3  call        0157D440
0157D4B8  mov         eax,1
0157D4BD  pop         ebp  
0157D4BE  ret         14h  

There is something wrong here as the return value (EAX) is always 1.  I know that GetDiskFreeSpace should sometimes return 0.

This also ignores the 1st parameter (volume name string) which explains why I get the same result what ever I pass in the string.

Do you think something has hooked or intercepted the call?  I am not sure where this code is from.

Author Comment

ID: 12561622
I worked out the problem.  I noticed that something seemed to have hooked GetDiskFreeSpace and when I stepped into it I noticed that the code was in "appvcore.dll" in the call stack.  Using TaskInfo I worked out that appvcore.dll was in C:\WINDOWS\AppPatch and part of "Windows Application Verifier".

About 6 months ago I was asked to test a Microsoft tool called AppVerifier which was supposed to tell you about all the things your software was doing wrong.  I tried it a few times and got nothing useful out of it.  (It produced masses of warnings and errors all of which turned out to be what was wanted or benign.)

Anyway, I did not realise that once you have added a program into AppVerifier to be checked it somehow hooks the Application even when AppVerifier (appverif.exe) itself is not even running.  So the software has been running under App Verifier all that time (and creating huge log files).

Obviously there is something wrong with how AppVerifier hooks GetDiskFreeSpace and GetDiskFreeSpaceEx.  After I removed the application from AppVerifier's list it now works fine.

Author Comment

ID: 12562999
Some final notes:

1. App Verifier is apparently interccepting and changing the values returned by GetDiskFreeSpace and GetDiskFreeSpaceEx in order to detect bugs caused by disk sizes greater greater than 32 bits.  For GetDiskFreeSpace: multiplying number of free clusters or total clusters by cluster size would give a number that overflows 32 bits and has zero in the lower 32 bits.  For GetDiskFreeSpaceEx: using the lower 32 bits of the sizes returned from give disk sizes and free spaces of zero.

I guess the intent is that programs that check free disk space but only use 32 bit values will report errors like "you have 0 bytes free".

However, here are a few problems with the strategy:

 a) Floppy drives should be excluded since they are never going to be > 2 Gbytes.
 b) Ignoring passed drive letters is extremely confusing.  GetDiskFreeSpace should return the same errors that it normally does.
 c) Why return 0x0005000000000000 (GetDiskFreeSpaceEx)? 0x000000010000000 would be a more obvious value.
 d) It might detect bugs to return these values for free space but I can't see any reason to return these values for total disk space (and causes nasty side-effects as in my case).
 e) The total size returned by GetDiskFreeSpaceEx is inconsistent with that from IOCTL_DISK_GET_LENGTH_INFO.
 e) I don't see the need for GetDiskFreeSpaceEx.  If someone explicitly use GetDiskFreeSpaceEx (rather than GetDiskFreeSpace) they are obviously aware of large disk sizes so why would they ignore the full 64 bit size?

2. IOCTL_DISK_GET_LENGTH_INFO (which I mentioned in the original post) does not work for floppies.


Accepted Solution

modulo earned 0 total points
ID: 13023261
PAQed with points refunded (250)

Community Support Moderator

Author Comment

ID: 13158973
Sorry, I solved this myself, and thought I asked for a refund.  I also didn't see any emails informing of posts in this topic (may have been lost in SPAM).

Author Comment

ID: 13169632
Yes, I did see that I got the refund, thanks.

However, I was just trying to explain/apologise.

Featured Post

Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…

834 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