我正在尝试在我的C ++ win32应用程序中使用GetDiskFreeSpaceEx来获取“当前”驱动器上的总可用字节数。我在Windows 7上。
我正在使用此示例代码:http://support.microsoft.com/kb/231497
它有效!好吧,差不多。如果我提供驱动器,它会起作用,例如:
...
szDrive[0] = 'C'; // <-- specifying drive
szDrive[1] = ':';
szDrive[2] = '\\';
szDrive[3] = '\0';
pszDrive = szDrive;
...
fResult = pGetDiskFreeSpaceEx ((LPCTSTR)pszDrive,
(PULARGE_INTEGER)&i64FreeBytesToCaller,
(PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
fResult变为true
,我可以继续准确计算可用的空闲字节数。
然而,问题在于我希望不必指定驱动器,而只是使用“当前”驱动器。我在网上找到的文档(Here)声明:
lpDirectoryName [in,optional]
磁盘上的目录。如果此参数为 NULL ,则该函数使用当前磁盘的根目录。
但是如果我为目录名传递NULL,那么GetDiskFreeSpaceEx最终返回false
,数据仍然是垃圾。
fResult = pGetDiskFreeSpaceEx (NULL,
(PULARGE_INTEGER)&i64FreeBytesToCaller,
(PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
//fResult == false
这是奇怪的吗?当然我错过了什么?任何帮助表示赞赏!
修改
根据JosephH的评论,我做了一个GetLastError()调用。它返回了DWORD:
ERROR_INVALID_NAME 123(0x7B)
The filename, directory name, or volume label syntax is incorrect.
第二次编辑
在我提到的评论中被埋没了:
我尝试过GetCurrentDirectory并返回正确的绝对路径,除了它前缀为
\\?\
答案 0 :(得分:4)
它返回正确的绝对路径,除了它前缀为
\\?\
这是这个谜团的关键。你得到的是带有 native api 路径名的目录的名称。 Windows是一个操作系统,内部看起来与您熟悉winapi编程的非常不同。 Windows内核有一个完全不同的api,它很像DEC VMS操作系统。没有巧合,大卫卡特勒曾经为DEC工作过。在本机操作系统之上最初是三个api层,Win32,POSIX和OS / 2。他们可以轻松地将程序从其他操作系统移植到Windows NT。没有人关心POSIX和OS / 2层,它们在XP时被删除了。
Win32中一个臭名昭着的限制是MAX_PATH,260的值。它设置存储文件路径名的C字符串的最大允许大小。原生api允许更大的名称,32000个字符。您可以使用本机api格式使用路径名来绕过Win32限制。这与您熟悉的路径名相同,但前缀为\\?\
。
因此,你从GetCurrentDirectory()获得这样一个字符串的原因当然是因为你当前的目录名超过了259个字符。进一步推断,GetDiskFreeSpaceEx()失败,因为它有一个错误,它拒绝它传递NULL时看到的长名称。有点可以理解,通常不会要求处理长名称。每个人都只传递驱动器名称。
这对于创建具有如此长名称的目录时会发生的情况非常典型。东西开始随机掉落。通常,有一个 lot 的C代码使用MAX_PATH,当它必须处理比这更长的路径名时,代码将会失败。这也是一个非常可利用的问题,因为它能够在C程序中创建堆栈缓冲区溢出,技术上可以使用精心设计的文件名来操作程序并注入恶意软件。
这个问题没有真正的解决办法,GetDiskFreeSpaceEx()中的错误不会很快修复。删除该目录,可能会造成更多麻烦,并将其作为学习经验写下来。
答案 1 :(得分:1)
我很确定你必须检索当前的驱动器和目录并将其传递给该函数。我记得尝试使用目录名为GetDiskFreeSpaceEx()
的{{1}},但这不起作用。