FSDirWalker 1.1を公開しました [ソフトウェア]
8月29日にFSDirWalker 1.1.200.0を公開しました。
ダウンロードはこちらから:
http://www001.upp.so-net.ne.jp/yamashita/products/fstools/fsdirwalker/fsdirwalker.htm"
新機能としてACLエディタ及び代替ストリームエディタを追加しました。また、簡易的ながらファイルリストに表示されるファイルのドラッグ&ドロップにも対応しました。
詳細な履歴はこちらから。
ダウンロードはこちらから:
http://www001.upp.so-net.ne.jp/yamashita/products/fstools/fsdirwalker/fsdirwalker.htm"
新機能としてACLエディタ及び代替ストリームエディタを追加しました。また、簡易的ながらファイルリストに表示されるファイルのドラッグ&ドロップにも対応しました。
詳細な履歴はこちらから。
2015-09-02 20:10
コメント(0)
FSDirWalkerを公開しました (4) [ソフトウェア]
このタイトルの連載としては最後です。
内部の細かい話が中心でしたので、今回はUI周りについて書きたいと思います。
その前に、(3)の補足というか、おまけを。
ネイティブAPIにRtlGetLongestNtPathLengthという関数があります。名前からしてパスの最大値が得られるのではと期待したのですが、実際は269という値が返る(Windows 7の場合)だけです。
(Windows 7の場合)
269(0x10D)という値は何なのでしょう?他のバージョンのWindowsがどんな値を返すか確認していませんし、歴史的経緯も判りませんが(少なくともWindows2000には存在しました)当初はこの値だったのでしょうか。それともファイルパスのことではないのでしょうか?
FSDirWalkerはUIデザインを含め仕様・設計思想自体が一回り、いや二~三回りほど古くさいと感じられるかもしれません。
書き始めたのが6年前なので仕方ないといえば仕方ないのですが(6年間と言っても連続してずっとという訳ではありません。時間があり、思い出した時に少しずつという感じでしたが、1年ぐらい間が開いたこともあります)。
その間にWindows Vista,Windows 7の”ゴージャスな”デスクトップからWindows 8/8.1のMetro(あえてメトロと呼びます)とフラットデザイン、そしてWindows 10のUWPとどんどん変化してますが、FSDirWalkerの基本はWindows XP、いやWindows 2000/NT4スタイルのままです。
まあ、これは私自身が時代に追いつけない「ロートル」だからですが、他にも多少の理由があります。
扱う対象がファイルシステムでしたのでWin32ベースになることは必然なものの、UIまで生のWin32で書くのはもはや厳しい。しかしMFCは避けたい。
極初期の頃はProcessWalker系列が使っている「フレームワーク」(Win32ベースで独自に起こしたUIライブラリ)を使用していたのですが、しばらく使ってみると今回のアプリケーションの目的に対しても、保守の面からも「重量級」に感じられす様になったのです。
そこで元々興味があったWTLが良いのではないかと思いつき、試しに使ってみたところ比較的使いやすく、使えそうなクラスも多かったのでUI部分を中心に採用することにしました。
その後、ファイル処理コアやネイティブAPIを扱うライブラリなどを残して「独自フレームワーク」を使っていた部分を捨て、UIを一から書き直して全面的にATL/WTLに移行した経緯があります。
その上で、ATL/WTL以外はWPFや.NETも含め可能な限り外部のランタイムライブラリに依存しない様に意識しました。そのため、.NETがインストールされていない環境や、Windows保守モードのコマンドプロンプト(Windows PE/REといった最小限のGUI環境)からも実行可能となっています。
とは言え、WTLもパーフェクトではなく、好みのデザインするためにいろいろ回避しなければならなかったのですが、その辺はいずれ機会があれば記したいと思います。
とりあえず連載形式は今回で終わりにしますが、今後も引き続きトピックを見つけて記事を載せる予定です。
内部の細かい話が中心でしたので、今回はUI周りについて書きたいと思います。
その前に、(3)の補足というか、おまけを。
ネイティブAPIにRtlGetLongestNtPathLengthという関数があります。名前からしてパスの最大値が得られるのではと期待したのですが、実際は269という値が返る(Windows 7の場合)だけです。
_RtlGetLongestNtPathLength@0: 7753D8BF mov eax,10Dh 7753D8C4 ret |
269(0x10D)という値は何なのでしょう?他のバージョンのWindowsがどんな値を返すか確認していませんし、歴史的経緯も判りませんが(少なくともWindows2000には存在しました)当初はこの値だったのでしょうか。それともファイルパスのことではないのでしょうか?
―◇―
FSDirWalkerはUIデザインを含め仕様・設計思想自体が一回り、いや二~三回りほど古くさいと感じられるかもしれません。
書き始めたのが6年前なので仕方ないといえば仕方ないのですが(6年間と言っても連続してずっとという訳ではありません。時間があり、思い出した時に少しずつという感じでしたが、1年ぐらい間が開いたこともあります)。
その間にWindows Vista,Windows 7の”ゴージャスな”デスクトップからWindows 8/8.1のMetro(あえてメトロと呼びます)とフラットデザイン、そしてWindows 10のUWPとどんどん変化してますが、FSDirWalkerの基本はWindows XP、いやWindows 2000/NT4スタイルのままです。
まあ、これは私自身が時代に追いつけない「ロートル」だからですが、他にも多少の理由があります。
扱う対象がファイルシステムでしたのでWin32ベースになることは必然なものの、UIまで生のWin32で書くのはもはや厳しい。しかしMFCは避けたい。
極初期の頃はProcessWalker系列が使っている「フレームワーク」(Win32ベースで独自に起こしたUIライブラリ)を使用していたのですが、しばらく使ってみると今回のアプリケーションの目的に対しても、保守の面からも「重量級」に感じられす様になったのです。
そこで元々興味があったWTLが良いのではないかと思いつき、試しに使ってみたところ比較的使いやすく、使えそうなクラスも多かったのでUI部分を中心に採用することにしました。
その後、ファイル処理コアやネイティブAPIを扱うライブラリなどを残して「独自フレームワーク」を使っていた部分を捨て、UIを一から書き直して全面的にATL/WTLに移行した経緯があります。
その上で、ATL/WTL以外はWPFや.NETも含め可能な限り外部のランタイムライブラリに依存しない様に意識しました。そのため、.NETがインストールされていない環境や、Windows保守モードのコマンドプロンプト(Windows PE/REといった最小限のGUI環境)からも実行可能となっています。
とは言え、WTLもパーフェクトではなく、好みのデザインするためにいろいろ回避しなければならなかったのですが、その辺はいずれ機会があれば記したいと思います。
とりあえず連載形式は今回で終わりにしますが、今後も引き続きトピックを見つけて記事を載せる予定です。
2015-07-11 16:00
コメント(0)
FSDirWalker 1.0.180.1 BugFilx公開しました [ソフトウェア]
今回、「連載」はお休みしての割り込みです。FSDirWalkerのバグ修正版(1.0.180.1)を公開しました。
前回ブログで32767文字のパスについて、いい気になって偉そうにあれこれ書きながら動作確認したところ、いくつかバグを見つけてしまって修正に追われる事に。
(テストはしていたのですが、まだまだ不足しておりました…)
それらのバグの中に、Windows 7がブルースクリーンで停止するバグを発見し至急の修正となったものです。
カーネルがクラッシュするので重大なバグですが、FSDirWalkerにはカーネルモードモジュールは含まれていません。
これは、ユーザーモードで渡したパラメータが元でWindowsのカーネルモード側でクラッシュするもので、極々希にある様です(ドライバ自身や自作のカーネルモードモジュール、マルウェアなどではなくユーザーモード側からの操作という意味で)。
そのバグは、ファイルのリネーム時に起きたもので、リネーム後のパス+ファイル名が32767文字を超えるとブルースクリーンで落ちるというものでした。
特殊な処理である上、長大なパスやファイル名作成しなければならないので、通常の使用環境ではこの問題に直面することはまず無いと思います。
しかし、意図した操作をすれば100%再現性のあるBSODとなると放っておけないので、急ぎ修正版をリリースしました。
以下、具体的に説明します。
(FSDirWalkerでの再現例です)
あるボリュームに、次の様なルートディレクトリを基点としたパスを持つファイルがあるとします。
全体で32767文字のパス、最後の"zz"はファイル名。
まず、ボリュームのルートディレクトリをオープンし、次にそのルートを親に残りった"a\a....\a"のディレクトリの部分をオープンします。更にそれを親にして最終的にファイル"zz"をオープンします。
そのファイルの名前を"zzz"にリネームしたいとします。その操作のためにネイティブAPIのNtSetInformationFile関数にFileRenameInformationを指定し、引数の構造体に新しい名前"zzz"を指定します。
ところが、もし、この操作が成功すると、自身の名前とすべての親の名前を合わせた全体のパスの長さは32768文字になってしまい、有効長の32767文字を超えることになります。
結果的に不正になるパラメータを渡す操作にも問題があるのですが、このケースは相対パスのファイル名で指定しているので、パス文字列の全体長が分かりにくい状況です。
ですので、NtSetInformationFileが何らかのエラーを返して欲しいところですが、Windows 7ではブルースクリーンが表示されて停止してしまいます。
以下は、クラッシュ時のメモリダンプからのスタックトレースです。
カーネルモードのNtSetInformationFileから始まり、ntfs.sysのリネーム処理の最中に引き起こされている模様です。
ここでは、ディレクトリやファイルを相対オープンしていますが、ボリューム名を含めた絶対パスでファイルをオープンしても、リネーム後の新しいパス+ファイル名が32767文字を超えてしまう様なら、同じ現象が起きます。
このバグは、手元の複数のWindows 7 SP1で必ず再現しました(64bit版でも発生)ので、私の環境特有という訳では無いと思いますが、MSのKnowledge Baseで探してみたところ私の探し方が悪いのか、掲載されていないのか見つけることができませんでした。どなたかご存知でしたらご教示ください。
なお、Windows 8.1、Windows 10では再現しませんでしたので何らかの修正が入ったのかもしれません。
Windows 7の不具合だとは思うのですが、修正は望めないのでFSDirWalker側で回避することにしました。
上記の様なリネームの処理の際、新しいパスが32767を超えない様にチェックする処理を追加しています。
なお、今回FSDirWalkerは他にもいくつかバグを修正していますので、興味がある方はこちらからどうぞ。
前回ブログで32767文字のパスについて、いい気になって偉そうにあれこれ書きながら動作確認したところ、いくつかバグを見つけてしまって修正に追われる事に。
(テストはしていたのですが、まだまだ不足しておりました…)
それらのバグの中に、Windows 7がブルースクリーンで停止するバグを発見し至急の修正となったものです。
カーネルがクラッシュするので重大なバグですが、FSDirWalkerにはカーネルモードモジュールは含まれていません。
これは、ユーザーモードで渡したパラメータが元でWindowsのカーネルモード側でクラッシュするもので、極々希にある様です(ドライバ自身や自作のカーネルモードモジュール、マルウェアなどではなくユーザーモード側からの操作という意味で)。
そのバグは、ファイルのリネーム時に起きたもので、リネーム後のパス+ファイル名が32767文字を超えるとブルースクリーンで落ちるというものでした。
特殊な処理である上、長大なパスやファイル名作成しなければならないので、通常の使用環境ではこの問題に直面することはまず無いと思います。
しかし、意図した操作をすれば100%再現性のあるBSODとなると放っておけないので、急ぎ修正版をリリースしました。
以下、具体的に説明します。
(FSDirWalkerでの再現例です)
あるボリュームに、次の様なルートディレクトリを基点としたパスを持つファイルがあるとします。
"\a\a....\a\zz" |
まず、ボリュームのルートディレクトリをオープンし、次にそのルートを親に残りった"a\a....\a"のディレクトリの部分をオープンします。更にそれを親にして最終的にファイル"zz"をオープンします。
そのファイルの名前を"zzz"にリネームしたいとします。その操作のためにネイティブAPIのNtSetInformationFile関数にFileRenameInformationを指定し、引数の構造体に新しい名前"zzz"を指定します。
ところが、もし、この操作が成功すると、自身の名前とすべての親の名前を合わせた全体のパスの長さは32768文字になってしまい、有効長の32767文字を超えることになります。
結果的に不正になるパラメータを渡す操作にも問題があるのですが、このケースは相対パスのファイル名で指定しているので、パス文字列の全体長が分かりにくい状況です。
ですので、NtSetInformationFileが何らかのエラーを返して欲しいところですが、Windows 7ではブルースクリーンが表示されて停止してしまいます。
以下は、クラッシュ時のメモリダンプからのスタックトレースです。
0: kd> k ChildEBP RetAddr WARNING: Stack unwind information not available. Following frames may be wrong. a3e537cc 83641c48 nt!IoGetRelatedDeviceObject+0x80b a3e53870 83a1fba9 nt!Kei386EoiHelper+0x27e0 a3e538bc 898846bc hal!KfLowerIrql+0x61 a3e53b04 898c0c0f Ntfs!NtfsSetRenameInfo+0x153e a3e53b84 898161ae Ntfs!NtfsCommonSetInformation+0x674 a3e53bf0 83637d8d Ntfs!NtfsFsdSetInformation+0x107 a3e53c08 8957920c nt!IofCallDriver+0x64 a3e53c2c 895793cb fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2aa a3e53c64 83637d8d fltmgr!FltpDispatch+0xc5 a3e53c7c 8385cae2 nt!IofCallDriver+0x64 a3e53d18 8363ea66 nt!NtSetInformationFile+0x953 a3e53d34 776c70f3 nt!ZwYieldExecution+0xb66 a3e53d38 badb0d00 ntdll!KiFastSystemCall+0x3 |
カーネルモードのNtSetInformationFileから始まり、ntfs.sysのリネーム処理の最中に引き起こされている模様です。
ここでは、ディレクトリやファイルを相対オープンしていますが、ボリューム名を含めた絶対パスでファイルをオープンしても、リネーム後の新しいパス+ファイル名が32767文字を超えてしまう様なら、同じ現象が起きます。
このバグは、手元の複数のWindows 7 SP1で必ず再現しました(64bit版でも発生)ので、私の環境特有という訳では無いと思いますが、MSのKnowledge Baseで探してみたところ私の探し方が悪いのか、掲載されていないのか見つけることができませんでした。どなたかご存知でしたらご教示ください。
なお、Windows 8.1、Windows 10では再現しませんでしたので何らかの修正が入ったのかもしれません。
Windows 7の不具合だとは思うのですが、修正は望めないのでFSDirWalker側で回避することにしました。
上記の様なリネームの処理の際、新しいパスが32767を超えない様にチェックする処理を追加しています。
なお、今回FSDirWalkerは他にもいくつかバグを修正していますので、興味がある方はこちらからどうぞ。
2015-07-05 14:50
コメント(0)
FSDirWalkerを公開しました (3) [ソフトウェア]
今回は、MAX_PATHを超えたパスを扱いたい件です。
Windowsエクスプローラなどでパスを扱う場合、多くは最大長をMAX_PATHとしています。
MAX_PATHは260と定義されているので、パスは最大260文字(大抵はC言語で扱うので文字列末尾の\0を除くと259文字まで)となります。
しかし、NTFSの様なファイルシステムではMAX_PATHをはるかに超える32767文字(最大16383階層程度)までのパスを扱うことができます。
私は「大深度パス」などと勝手に呼んでますが、Windows標準ではこの長いパスを扱えるツールが無いことが、FSDirWalkerを作成した理由のひとつです。
プログラムから扱う場合は、Win32 APIに渡すファイルパスに"\\?\"プリフィックス(また出ました)を付けて呼び出すことでMAX_PATHの制限を回避できます。
ですから、最初は扱うファイルパスにプリフィックスを付けて、32K文字を格納できるバッファを用意すれば実現できるのではと思いましたが、案の定それほど単純な話ではありませんでした。
32767文字というのは、ネイティブAPIが扱うパス文字列がUNICODE_STRING構造体で表現される事に由来しています。
UNICODE_STRINGはワイド文字列へのポインタと長さの情報で構成されます。LengthはUSHORTですので0~65535まで表現できますが、これは文字数ではなく文字列を格納するのに必要なバイト数になっています。ワイド文字は1文字が2バイトですので、実質上の最大値は65534バイト、つまり32767文字が最大文字数になります。
当初は漠然とボリューム名とファイルのパスを合わせて32767文字だと思っていたのですが、ある時、更に下の階層にファイルやディレクトリが存在するはずなのにパス文字数が32767文字に達してしまって参照できないケースがあることに気づきました。そこでよくよく調べてみると、Windowsのファイルシステムではボリュームデバイスとボリューム内のファイル(パス)と分けて管理していることが判りました。つまり、ボリューム名を含まないファイルへのパスだけで32767文字使えるのです。
これは厄介です。いままでWin32でのファイル操作を含め、フルパス文字列のみで一意にボリューム上のファイルやディレクトリを識別してオープンできたものが、最低でもボリュームとファイル(パス)に分けてオープンしなければならないことを意味するからです。
ファイルをオープンしたり、ディレクトリ内のファイルを列挙する際にすべて「分割オープン」しないと「ディレクトリの底」到達できないのです。これは、私の知る限りWin32では実現できません。
この問題は、NTDLLが提供するネイティブAPIを使用することでクリアしました。もともと別の理由で既にネイティブAPIを常用していたので、その点の移行は簡単でした。
ネイティブAPIのNtCreateFile/NtOpenFileは引数として親オブジェクトのハンドルを指定できるので、それを利用することにします。あるファイルへのフルパスを受け取ってオープンする場合、まずボリュームのルートディレクトリをオープンしてハンドルを手に入れた後、それを親ハンドルにして残りをルート相対パスとして別途オープンするのです。この方法であれば、32767文字パスの「底」まで到達できます。
そうなると、「底」のディレクトリを親としてオープンし、そこから更に下の階層にファイルやディレクトリを作成できそうな感じがしましたが、それはエラーが返され実行できませんでした。USHORTによる上限とは別に、内部的に文字数の上限をチェックしているのかもしれません。
参照に関しては解決しましたが、「大深度ディレクトリ」には解決できていない問題があります。
ひとつはディレクトリのコピーや削除などを処理する際、入れ子になっているサブディレクトリの処理のために関数を再帰的に呼び出すことがあります。その際にリソースの上限に達してしまうことです。
具体的にはスタックとハンドルです。スタックはディレクトリを再帰する度に消費され、ネストが深い場合スタックオーバーフローを起こします。
スタックサイズを大きく取れば使い切ることはありませんが、どの程度確保すればよいか塩梅が難しく他の部分でのスタック消費量と調整が必要です。
ハンドルの方は32bit版で顕在化します。やはり再帰ごとにディレクトリ内容を列挙するためにディレクトリのオープンを繰り返しハンドルを取得しますが、やはりネストが深くなるとプロセスに割り当てられたハンドルを使い切ってしまうことです。
テスト用の小さなスタブでも使い切ってしまうので、実際のアプリケーションではスタブよりも早く使い切ってしまうでしょう。こちらはプロセスのハンドルテーブルを拡張する方法も知りませんし、ディレクトリをオープンしないで(または毎回クローズして)ネストを処理する方法も思いつきませんでしたので、解決できていません。そのため、現状ではコピーや削除で処理できる階層を1024階層までと制限する仕様になっています。
(なお、ハンドルの方は、64bit環境では十分なハンドル領域があるので深い階層でも処理できる様ですが、現在のFSDirWalkerは32bit版と同じ制限としています)。
もうひとつは、ディレクトリツリー表示です。当然何万階層もツリービューコントロールで表示できる筈も無く、したがって現在はルートから253階層までの表示となっています。
ツリービューコントロールは254階層あたりから階層レベルを折り返して(右に伸びたツリーが左に戻って)表示される様です。このあたりを制御可能なのか不明でしたので制限となっていますが、そもそも百階層程度のツリー表示でも見難いので悩ましいところです。
(続く)
Windowsエクスプローラなどでパスを扱う場合、多くは最大長をMAX_PATHとしています。
MAX_PATHは260と定義されているので、パスは最大260文字(大抵はC言語で扱うので文字列末尾の\0を除くと259文字まで)となります。
しかし、NTFSの様なファイルシステムではMAX_PATHをはるかに超える32767文字(最大16383階層程度)までのパスを扱うことができます。
私は「大深度パス」などと勝手に呼んでますが、Windows標準ではこの長いパスを扱えるツールが無いことが、FSDirWalkerを作成した理由のひとつです。
―◇―
プログラムから扱う場合は、Win32 APIに渡すファイルパスに"\\?\"プリフィックス(また出ました)を付けて呼び出すことでMAX_PATHの制限を回避できます。
ですから、最初は扱うファイルパスにプリフィックスを付けて、32K文字を格納できるバッファを用意すれば実現できるのではと思いましたが、案の定それほど単純な話ではありませんでした。
32767文字というのは、ネイティブAPIが扱うパス文字列がUNICODE_STRING構造体で表現される事に由来しています。
struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING; |
当初は漠然とボリューム名とファイルのパスを合わせて32767文字だと思っていたのですが、ある時、更に下の階層にファイルやディレクトリが存在するはずなのにパス文字数が32767文字に達してしまって参照できないケースがあることに気づきました。そこでよくよく調べてみると、Windowsのファイルシステムではボリュームデバイスとボリューム内のファイル(パス)と分けて管理していることが判りました。つまり、ボリューム名を含まないファイルへのパスだけで32767文字使えるのです。
これは厄介です。いままでWin32でのファイル操作を含め、フルパス文字列のみで一意にボリューム上のファイルやディレクトリを識別してオープンできたものが、最低でもボリュームとファイル(パス)に分けてオープンしなければならないことを意味するからです。
ファイルをオープンしたり、ディレクトリ内のファイルを列挙する際にすべて「分割オープン」しないと「ディレクトリの底」到達できないのです。これは、私の知る限りWin32では実現できません。
この問題は、NTDLLが提供するネイティブAPIを使用することでクリアしました。もともと別の理由で既にネイティブAPIを常用していたので、その点の移行は簡単でした。
ネイティブAPIのNtCreateFile/NtOpenFileは引数として親オブジェクトのハンドルを指定できるので、それを利用することにします。あるファイルへのフルパスを受け取ってオープンする場合、まずボリュームのルートディレクトリをオープンしてハンドルを手に入れた後、それを親ハンドルにして残りをルート相対パスとして別途オープンするのです。この方法であれば、32767文字パスの「底」まで到達できます。
そうなると、「底」のディレクトリを親としてオープンし、そこから更に下の階層にファイルやディレクトリを作成できそうな感じがしましたが、それはエラーが返され実行できませんでした。USHORTによる上限とは別に、内部的に文字数の上限をチェックしているのかもしれません。
―◇―
参照に関しては解決しましたが、「大深度ディレクトリ」には解決できていない問題があります。
ひとつはディレクトリのコピーや削除などを処理する際、入れ子になっているサブディレクトリの処理のために関数を再帰的に呼び出すことがあります。その際にリソースの上限に達してしまうことです。
具体的にはスタックとハンドルです。スタックはディレクトリを再帰する度に消費され、ネストが深い場合スタックオーバーフローを起こします。
スタックサイズを大きく取れば使い切ることはありませんが、どの程度確保すればよいか塩梅が難しく他の部分でのスタック消費量と調整が必要です。
ハンドルの方は32bit版で顕在化します。やはり再帰ごとにディレクトリ内容を列挙するためにディレクトリのオープンを繰り返しハンドルを取得しますが、やはりネストが深くなるとプロセスに割り当てられたハンドルを使い切ってしまうことです。
テスト用の小さなスタブでも使い切ってしまうので、実際のアプリケーションではスタブよりも早く使い切ってしまうでしょう。こちらはプロセスのハンドルテーブルを拡張する方法も知りませんし、ディレクトリをオープンしないで(または毎回クローズして)ネストを処理する方法も思いつきませんでしたので、解決できていません。そのため、現状ではコピーや削除で処理できる階層を1024階層までと制限する仕様になっています。
(なお、ハンドルの方は、64bit環境では十分なハンドル領域があるので深い階層でも処理できる様ですが、現在のFSDirWalkerは32bit版と同じ制限としています)。
もうひとつは、ディレクトリツリー表示です。当然何万階層もツリービューコントロールで表示できる筈も無く、したがって現在はルートから253階層までの表示となっています。
ツリービューコントロールは254階層あたりから階層レベルを折り返して(右に伸びたツリーが左に戻って)表示される様です。このあたりを制御可能なのか不明でしたので制限となっていますが、そもそも百階層程度のツリー表示でも見難いので悩ましいところです。
(続く)
2015-07-01 23:39
コメント(0)
FSDirWalkerを公開しました (2) [ソフトウェア]
前回の続きで
・ドライブやボリュームGUIDの割り当ての無いボリューム(パーティション)の内容を参照したい。
についてです。
Windowsでのドライブ名は、実際のところMS-DOSから続く過去の遺産(後方互換)として継続している面があり、内部的にはショートカットの一種の様な扱いになっており、パーティションやデバイスにドライブを割り当て無しにする事もできます。また、PCのリストア用データ格納の為にドライブ無しで最初から予約されているパーティションもあります。
ドライブ名が無くても、通常はボリュームマネジャがGUID形式の識別子を割り当てており、それを元に識別することができます。以下はWin32での書式です。
(xxx...は16進数)
ドライブの無いボリュームにアクセスする場合、例えばコマンドプロンプトでは次の様に参照します。
Windowsエクスプローラでも上記の形式を直接アドレスバーに入力すればフォルダを参照できます。
(アプリケーションによってはこの形式を解釈できない場合があります)
ところが、希にGUID形式のボリューム名が割り当てられていない予約ボリュームを見かけることがあります(私も大量のPCを見た訳では無いので割合は解からないのですが)。
その場合は、ネイティブオブジェクトのネームスペース形式を使って参照するしかありません。
以下は、そのネイティブ表記したボリュームオブジェクトのパスです。
この形式でディレクトリやファイルにアクセスする場合次の様になります。
この名前空間は、ネイティブAPI(ユーザーモードではNTDLL.DLLが提供するシステムコール)ではそのまま使うことができますし、Win32 APIレベルでは "\\?\GLOBALROOT" というプリフィックスを付けて渡すことでネイティブのネームスペースと解釈してもらえます。
しかし、私の知る限りコマンドプロンプトのdirコマンドやWindowsエクスプローラではこのプリフィックスは解釈できない様なのでそのままでは内容を参照できません。
NTFSであれば、mklinkコマンドでドライブもGUID名も無いボリューム対してシンボリックリンクを作成することで参照できる様になりますが、私としてはその様な常設の方法ではなく一時的に確認できれば良いと考えました。それに私のことだからリンクを作ったまま忘れてしまって、そのうち誤操作してしまいそうです。
(ボリューム内容を参照する標準ツールで"\\?\GLOBALROOT" プリフィックスを解釈できるコマンドをご存知でしたらご教示頂きたいです)
(追記) 記事を上げた後にネイティブオブジェクト名の参照方法として、以下の様な記述に思い当たりました。
Windows7のコマンドプロンプトは受け入れますが、XPでは不可な様です。ルートを参照する場合は変則的ですが、以下の様に指定すると受け入れます。
"\\?\","\\.\","\\?\GLOBALROOT"といったプリフィックスは、何れもWin32API呼び出しの際付与し、パスを解釈させる為のものですが、そのままコマンドライン上で通用することは恥ずかしながらいままで知りませんでした。他にもありましたらぜひご教示頂きたいです。
以上の様に、ドライブの無いボリュームを参照する方法はありますが、GUID形式にしても覚えていられないので一度探さなければならないし、ネイティブの場合も単純な方法が無く手間がかかる。そんなところから、もっと「カジュアルに」参照したい、と考えFSDirWalkerを書き始めた理由のひとつでした。
(続く)
・ドライブやボリュームGUIDの割り当ての無いボリューム(パーティション)の内容を参照したい。
についてです。
Windowsでのドライブ名は、実際のところMS-DOSから続く過去の遺産(後方互換)として継続している面があり、内部的にはショートカットの一種の様な扱いになっており、パーティションやデバイスにドライブを割り当て無しにする事もできます。また、PCのリストア用データ格納の為にドライブ無しで最初から予約されているパーティションもあります。
ドライブ名が無くても、通常はボリュームマネジャがGUID形式の識別子を割り当てており、それを元に識別することができます。以下はWin32での書式です。
\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} |
ドライブの無いボリュームにアクセスする場合、例えばコマンドプロンプトでは次の様に参照します。
dir \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\windows\system32 |
Windowsエクスプローラでも上記の形式を直接アドレスバーに入力すればフォルダを参照できます。
(アプリケーションによってはこの形式を解釈できない場合があります)
ところが、希にGUID形式のボリューム名が割り当てられていない予約ボリュームを見かけることがあります(私も大量のPCを見た訳では無いので割合は解からないのですが)。
その場合は、ネイティブオブジェクトのネームスペース形式を使って参照するしかありません。
以下は、そのネイティブ表記したボリュームオブジェクトのパスです。
\Device\HarddiskVolume1 |
この形式でディレクトリやファイルにアクセスする場合次の様になります。
\Device\HarddiskVolume1\Windows\System32 |
この名前空間は、ネイティブAPI(ユーザーモードではNTDLL.DLLが提供するシステムコール)ではそのまま使うことができますし、Win32 APIレベルでは "\\?\GLOBALROOT" というプリフィックスを付けて渡すことでネイティブのネームスペースと解釈してもらえます。
しかし、私の知る限りコマンドプロンプトのdirコマンドやWindowsエクスプローラではこのプリフィックスは解釈できない様なのでそのままでは内容を参照できません。
NTFSであれば、mklinkコマンドでドライブもGUID名も無いボリューム対してシンボリックリンクを作成することで参照できる様になりますが、私としてはその様な常設の方法ではなく一時的に確認できれば良いと考えました。それに私のことだからリンクを作ったまま忘れてしまって、そのうち誤操作してしまいそうです。
(ボリューム内容を参照する標準ツールで"\\?\GLOBALROOT" プリフィックスを解釈できるコマンドをご存知でしたらご教示頂きたいです)
(追記) 記事を上げた後にネイティブオブジェクト名の参照方法として、以下の様な記述に思い当たりました。
dir \\.\HarddiskVolume1\Boot |
dir \\.\HarddiskVolume1\\ |
以上の様に、ドライブの無いボリュームを参照する方法はありますが、GUID形式にしても覚えていられないので一度探さなければならないし、ネイティブの場合も単純な方法が無く手間がかかる。そんなところから、もっと「カジュアルに」参照したい、と考えFSDirWalkerを書き始めた理由のひとつでした。
(続く)
2015-06-29 23:20
コメント(0)