none
FindFirstFile関数はx64環境においてシステムファイルが検索できない? RRS feed

  • 質問

  • 各OS環境で動作する、ファイルの検索機能を盛り込んだアプリケーションを開発中です。
    下記ソースコードにおいてx86環境のXP,Vista,Win7では、どちらのファイルも検索できることを確認しましたが、x64環境のWin7においてはシステムファイルの"serial.sys"が指定したフォルダ内に存在するにも関わらず検索できないようです(DLLファイルは検索できている)。
    FindFirstFile関数はx64環境においてシステムファイルが検索できない等の制約があるのでしょうか?
    もし制約がある場合、代替の方法でのファイル検索手段を教示ください。

    #include <windows.h>
    #include <stdio.h>

    void main()
    {
     char buf[100];
     int len=0;
     WIN32_FIND_DATA c_file;

     GetSystemDirectory(buf, 100);
     len = strlen(buf);
     strcpy(&buf[len], "\\serialui.dll");
     printf("%s\t", buf); 
     if(FindFirstFile(buf, &c_file) == INVALID_HANDLE_VALUE) {
      printf("見つからない\n");
     } else {
      printf("見つかった\n");
     }

     GetSystemDirectory(buf, 100);
     len = strlen(buf);
     strcpy(&buf[len], "\\drivers\\serial.sys");
     printf("%s\t", buf);
     if(FindFirstFile(buf, &c_file) == INVALID_HANDLE_VALUE) {
      printf("見つからない\n");
     } else {
      printf("見つかった\n");
     }
    }

     

    2010年8月24日 5:41

回答

すべての返信

  • このプログラムは、32ビットでビルドしていませんか?可能であれば、64ビットでビルドして試してみてください。

    私のx64OS環境では、System32\drivers に serial.sys はありますが、SysWOW64\drivers にはありませんでした。

    ちなみに、serialui.dll はどちらのフォルダにもありました。

     


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年8月24日 5:55
  • FindFirstFileの説明 にヒントがあります。
    If you are writing a 32-bit application to list all the files in a directory and the application may be run on a 64-bit computer, you should call the Wow64DisableWow64FsRedirectionfunction before calling FindFirstFile and call Wow64RevertWow64FsRedirection after the last call to FindNextFile. For more information, see File System Redirector.
    2010年8月24日 6:02
  • 早速の御回答有難うございます。
    FindFirstFile関数の前にWow64DisableWow64FsRedirection関数を盛り込むと"serial.sys"も正常に検索できました。
    念のため、FindNextFile関数を実行しない場合はFindFirstFile関数の後にWow64RevertWow64FsRedirectionを実行すれきと認識しましたが誤りないでしょうか?
    貴重な情報有難うございました。
    2010年8月24日 6:41
  • 環境を元に戻すのが目的ですので、FindNextFile()を呼ぶかどうかには依存しませんね。呼ぶべきです。

    ところでFindClose()していますか? 見る限りしていなさそうでハンドルリークしています。ドキュメントを読む癖をつけた方がいいと思います。

    でもフォーラムで質問する利点ということでアドバイスを…ファイルの存在を確認するだけなら、CRTにaccess() があります(mode=00)。
    2010年8月24日 7:07
  • 存在チェックだけということであれば、GetFileAttributes というAPIを利用する方法もあります。

    それと、ファイルパスを組み立てるなら、PathCombine などを使うとよいでしょう。ビルドしてないのでタイプミスとかあるかもしれませんが、全体的には下記のような感じになります。

    なお、Wow64DisableWow64FsRedirection API は、XPの32bit版には存在しないはずなので、古い環境で使う場合は、GetProcAddress する必要があります(サンプルは面倒なので書いてません)。

    #include <shlwapi.h> // PathCombine のために必要
    
    TCHAR filePath[MAX_PATH]; // ファイル名を格納する場合は最低でも常にMAX_PATH以上を確保すること
    PVOID oldValues;
    BOOL disabled = Wow64DisableWow64FsRedirection( &oldValues ); // 32bit版XPは、GetProcAddress する必要がある
    
    GetSystemDirectory( filePath, MAX_PATH );
    PathCombine( filePath, filePath, _T("serialui.dll") );
    DWORD fileAttr = GetFileAttributes( filePath );
    if( !(fileAttr&FILE_ATTRIBUTE_DIRECTORY) ){
     printf("見つかった\n");
    }
    else{
     printf("見つからない\n");
    }
    
    // drivers\\serial.sys も同様に処理
    
    // 無効化に成功していたら、元に戻す
    if( disabled ){
    	Wow64RevertWow64FsRedirection( oldValues );
    }
    
    

     


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/
    2010年8月24日 7:21
  • 益々の貴重な情報有難うございます。

    どのような方法で実現するか検討致します。

    2010年8月24日 7:42
  • 素朴な疑問ですが。。。。(全然的外れかもしれませんけど。。。)

    そもそも、なぜ seral.sys ドライバの存在の有無をチェックしているのでしょうか?
    ターゲット PC 上に seral.sys が存在していることと、COM ポート デバイスがターゲット PC 上に存在していることは、
    全く別次元の話だと思います。

    仮に、「COM ポート デバイスがターゲット PC 上に存在しているか?」を確認したいのであれば、
    Setup API を使用しないと的確に判別できないと思います。

    2010年8月24日 8:40
  • 最終目的はserial.sysの検索ではなく、別のシステムファイルの検索です。

    ただ、特殊なシステムファイルを例に出すよりも、馴染みのあるserial.sysを例に投稿させて頂いた次第です。

    2010年8月24日 23:45
  • 64ビットネイティブのシステムディレクトリ以下にあるファイルをWOW64プログラムから参照するのであれば、Wow64DisableWow64FsRedirectionfunctionを呼ぶ代わりにSysnativeリダイレクタを使うという方法もあります。

    http://msdn.microsoft.com/ja-jp/library/aa384187(VS.85).aspx

    ファイルリダイレクションを無効化すると、DLLのロードなども64ビットネイティブのシステムディレクトリを参照してしまうので、呼び出すAPIによってはDLLがロードできず(32ビットアプリで64ビットDLLをロードしようとして)エラーとなることもあります。

    2010年8月26日 5:00
  • Sysnativeリダイレクタは便利ですね。

    情報提供有難うございます。

    2010年8月26日 6:45
  • 提示されている URL でも記載されていますが、Sysnative は Vista(x64) 以降の追加要素です。
    それより前の 64bit Windows をフォローする必要がある場合は使えない可能性を考慮してください。
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年8月26日 13:32
    モデレータ
  • 確認していませんが、Vista以降なのでxp 32bitにもSysnativeはないように思います。

    つまり、常にSysnativeとsystem32の2ヶ所を見る必要があります。

    2010年8月26日 15:47