GetDiskFreeSpace returns wrong total clusters under XP

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?!?
LVL 3
aphillipsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mokuleCommented:
Hi,
I'm using GetDiskFreeSpace under xp.
Works OK. Could You please give the code?
0
Mikal613Commented:
Just For Knowlege  

http://support.microsoft.com/kb/q231497/

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
  debug.Print " Total free:", Format$(GetDiskSpaceFree(sDrive), "###,###,###,###,##0")
  debug.Print " Bytes free:", Format$(GetDiskBytesAvailable(sDrive), "###,###,###,###,##0")
  debug.Print
  debug.Print " Disk used :", Format$(GetDiskSpaceUsed(sDrive), "###,###,###,###,##0")
0
aphillipsAuthor Commented:
> 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,
        &SectorsPerCluster,
        &BytesPerSector,
        &NumberOfFreeClusters,
        &TotalNumberOfClusters))
{
        // never gets here, even for drive 'X' or '?'
        return FALSE;
}
m_SectorSize = BytesPerSector;

ULARGE_INTEGER total_bytes;
VERIFY(::GetDiskFreeSpaceEx(vol,
        NULL,
        &total_bytes,
        NULL));
m_Length = total_bytes.QuadPart;  // m_Length is an __int64
0
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

aphillipsAuthor Commented:
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.
0
aphillipsAuthor Commented:
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.
0
aphillipsAuthor Commented:
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.

0
moduloCommented:
PAQed with points refunded (250)

modulo
Community Support Moderator
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
aphillipsAuthor Commented:
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).
0
aphillipsAuthor Commented:
Yes, I did see that I got the refund, thanks.

However, I was just trying to explain/apologise.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.