2

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、使用可能な空きバイト数を正確に計算できます。

ただし、問題は、ドライブを指定する必要がなく、代わりに「現在の」ドライブを使用することを望んでいたことです。私がオンラインで見つけたドキュメント(ここ)は次のように述べています。

lpDirectoryName [入力、オプション]

ディスク上のディレクトリ。このパラメーターが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.

2回目の編集

私が言及したコメントに埋もれています:

GetCurrentDirectory を試してみたところ、正しい絶対パスが返されますが、先頭に\\?\

4

2 に答える 2

5

接頭辞を付けることを除いて、正しい絶対パスを返します\\?\

それがこの謎の鍵です。返されたのは、ネイティブ APIパス名を持つディレクトリの名前です。Windows は、内部的には、winapi プログラミングで慣れ親しんだものとは大きく異なるオペレーティング システムです。Windows カーネルにはまったく異なる API があり、DEC VMS オペレーティング システムによく似ています。偶然ではありません。David Cutler は DEC で働いていました。そのネイティブ OS の上には、もともと Win32、POSIX、OS/2 という 3 つの API レイヤーがありました。これにより、他のオペレーティング システムから Windows NT へのプログラムの移植が容易になりました。POSIX 層と OS/2 層は誰も気にかけませんでした。それらは XP の時点で削除されました。

Win32 の悪名高い制限の 1 つは、MAX_PATH の値である 260 です。これは、ファイル パス名を格納する C 文字列の最大許容サイズを設定します。ネイティブ API では、32000 文字というはるかに大きな名前を使用できます。ネイティブ API 形式のパス名を使用することで、Win32 の制限を回避できます。これは、おなじみのパス名と同じですが、接頭辞が\\?\.

したがって、GetCurrentDirectory() からこのような文字列が返されたのは、現在のディレクトリ名が 259 文字を超えているためです。さらに推定すると、GetDiskFreeSpaceEx() にはバグがあり、NULL を渡すと表示される長い名前が拒否されるため、失敗しました。ある程度理解できますが、通常、長い名前を扱うように求められることはありません。誰もがドライブ名を渡すだけです。

これは、このような長い名前のディレクトリを作成したときに起こることの典型です。物がランダムに倒れ始めます。一般に、MAX_PATH を使用する多くの C コードがあり、それよりも長いパス名を処理する必要がある場合、そのコードは惨めに失敗します。これは、C プログラムでスタック バッファ オーバーフローを作成する能力のためにも、非常に悪用可能な問題です。技術的には、慎重に作成されたファイル名を使用してプログラムを操作し、マルウェアを挿入することができます。

この問題を解決する方法はありません。GetDiskFreeSpaceEx() のバグはすぐには修正されません。そのディレクトリを削除すると、さらに多くの問題が発生する可能性があり、これを学習経験として書き留めてください。

于 2013-02-15T10:03:57.550 に答える
1

現在のドライブとディレクトリを取得して、それを関数に渡す必要があると確信しています。GetDiskFreeSpaceEx()ディレクトリ名を として使用しようとしたことを覚えています"."が、うまくいきませんでした。

于 2013-02-15T01:39:04.387 に答える